<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-3412628233251595896</id><updated>2011-07-30T23:08:09.360-07:00</updated><category term='fxruby'/><category term='FXCess'/><category term='Ruby'/><category term='DSL'/><category term='Statistics'/><category term='ID3A'/><category term='Drails'/><title type='text'>patrick on rails</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://patrickonrails.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3412628233251595896/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://patrickonrails.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>patrick</name><uri>http://www.blogger.com/profile/15733281720346208032</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>8</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-3412628233251595896.post-7151715227458944021</id><published>2010-04-22T19:53:00.001-07:00</published><updated>2010-04-22T20:33:04.487-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Ruby'/><category scheme='http://www.blogger.com/atom/ns#' term='DSL'/><category scheme='http://www.blogger.com/atom/ns#' term='Statistics'/><title type='text'>DSLs and Insomnia (a few notes)</title><content type='html'>&lt;span style="font-weight: bold;"&gt;Intro&lt;/span&gt;&lt;br /&gt;This has nothing to do with Rails on a superficial level.&lt;br /&gt;&lt;br /&gt;On a deeper level, since Rails is a DSL (Domain Specific Language) it probably might have to do with Rails in a tangential sense.&lt;br /&gt;&lt;br /&gt;To wit: I'm refactoring the code base for an application I was spending my nights and weekends on over the past year or so. The application has to do with a fairly wide range of numerical models and there is always that point where I have to suck it up when thinking that Ruby doesn't have much to do with Statistics per se.&lt;br /&gt;&lt;br /&gt;Or numerical wonkery in general. It seems that the practical application of math ideas has been conquered by Python (witness all the books on Machine Learning written for Python coders and the veritable dearth of any such work for Rubyists).&lt;br /&gt;&lt;br /&gt;Anyways, while in the grips of some cold medicine (which never lets me sleep right), I figured I might as well make some proper use of my time and started looking at the 50,000 km view of my codebase and came to the conclusion that I was going to make a DSL to deal with all the funkiness of my particular problem domain.&lt;br /&gt;&lt;br /&gt;But, first I needed to deal with some very basic statistical methods. Sums, averages, variances, standard deviations are all methods that I need as a core base of functions.&lt;br /&gt;&lt;br /&gt;Furthermore, I would like my application to have the ability to be generic enough that an end user who would know that he or she wants the standard deviation for a set of numbers would be able to type something like &lt;span style="font-style: italic;"&gt;out st_dev [1, 2, 3, 4, 5]&lt;/span&gt; and come up with the answer (something like 1.58) without having to deal with anything more complicated than the command line.&lt;br /&gt;&lt;br /&gt;So, this is how I implemented a small DSL which handles the four methods I've listed above and how one can use it without having to learn Ruby or fire up their spreadsheet.&lt;br /&gt;&lt;br /&gt;to start: Create a basic class:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;class Stat&lt;br /&gt;def self.load(filename)&lt;br /&gt;  new.instance_eval(File.read(filename), filename)&lt;br /&gt;end&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Now this simple method was something of a mystery to me when I first read encountered it (see reading list at the bottom of the page) but essentially what it does is take a string and then assume that the first word of the next line is a method within that class and then evaluate that line.&lt;br /&gt;&lt;br /&gt;This is only slightly different than typing ruby -e eval "puts 'ruby is perfect' " at your command prompt.&lt;br /&gt;&lt;br /&gt;What it does allow you to do is build up a small domain language with nothing but methods.&lt;br /&gt;&lt;br /&gt;Let me show you what I mean...&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Sum&lt;/span&gt;&lt;br /&gt;Definition: "Sum" will be a keyword that will take an array of items and then return the sum of the set. &lt;span style="font-style: italic;"&gt;Example: sum [1, 2, 3, 4, 5]&lt;/span&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="font-style: italic;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Out&lt;/span&gt;&lt;br /&gt;Definition: "Out" will be the keyword which prints out the result of the function. &lt;span style="font-style: italic;"&gt;Example: out sum[1, 2, 3, 4, 5]&lt;/span&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="font-style: italic;"&gt;&lt;span style="font-style: italic;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;Implementation:&lt;br /&gt;&lt;pre&gt;&lt;br /&gt;def sum elements&lt;br /&gt; total = 0&lt;br /&gt; elements.each {|x| total += x }&lt;br /&gt; return total&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;def out(expression)&lt;br /&gt; puts expression&lt;br /&gt;end&lt;br /&gt;&lt;/pre&gt;With these two methods, I'm able to create a separate file called "one.stat" and type in &lt;span style="font-style: italic;"&gt;out sum[1, 2, 3, 4, 5] &lt;/span&gt;and nearly be able to get a response from my DSL.&lt;br /&gt;&lt;br /&gt;I say nearly because there is a pretty important command that I left off and that is the one which calls the interpreter and then evaluates all of the separate items.&lt;br /&gt;&lt;br /&gt;Since the class is called Stat, then the last line of the stat.rb should be "Stat.load(ARGV.shift)" which in plain speak means "create an instance of the Stat class and call the load function on the name of the file that was typed in".&lt;br /&gt;&lt;br /&gt;In other words, now I can save my "one.stat" file and at the command prompt type "ruby stat.rb one.stat" and I will see on the command line that the number "15" has been printed.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Conclusion&lt;/span&gt;&lt;br /&gt;That's pretty much the beginning and the end of the simplest DSL tutorial you will probably find on the internet. As you can see, there were no state machines, no heaps or stacks to deal with, no Turing machines or any of the other nonsense that gets piled on when Rubyists start pontificating on the excellence of a DSL.&lt;br /&gt;&lt;br /&gt;I'll leave the mean, variance, and standard deviation methods up to the reader for their own edification. Also, once I manage to figure out why github and I are not getting along, I will provide the source code to this little excursion into DSL land as an addendum.&lt;br /&gt;&lt;br /&gt;Remember, a domain specific language can make some problems easier (making a web app with CGI in Ruby is an exercise in poking your eyes out with torn fingernails - believe me: I've tried) but, you end up with a sad side effect that you now have two codebases, the one in Ruby and the one in your DSL.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Reading notes:&lt;/span&gt;&lt;br /&gt;&lt;a href="http://www.valibuk.net/2009/03/domain-specific-languages-in-ruby/"&gt;http://www.valibuk.net/2009/03/domain-specific-languages-in-ruby/&lt;/a&gt; is one of the simpler introductions to creating DSLs in Ruby but also gets into creating a mini Turing machine which, while cute - is not a very good example of how practical this technique is.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://www.artima.com/rubycs/articles/ruby_as_dsl3.html"&gt;http://www.artima.com/rubycs/articles/ruby_as_dsl3.html&lt;/a&gt; is considered one of the more "definitive" texts on creating DSLs in Ruby and I found it more arcane than the previous one.&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt; &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3412628233251595896-7151715227458944021?l=patrickonrails.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://patrickonrails.blogspot.com/feeds/7151715227458944021/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://patrickonrails.blogspot.com/2010/04/dsls-and-insomnia-few-notes.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3412628233251595896/posts/default/7151715227458944021'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3412628233251595896/posts/default/7151715227458944021'/><link rel='alternate' type='text/html' href='http://patrickonrails.blogspot.com/2010/04/dsls-and-insomnia-few-notes.html' title='DSLs and Insomnia (a few notes)'/><author><name>patrick</name><uri>http://www.blogger.com/profile/15733281720346208032</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3412628233251595896.post-1308526105736974441</id><published>2009-06-23T18:32:00.001-07:00</published><updated>2009-06-23T18:37:37.917-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='FXCess'/><category scheme='http://www.blogger.com/atom/ns#' term='fxruby'/><category scheme='http://www.blogger.com/atom/ns#' term='ID3A'/><title type='text'>ID3A update</title><content type='html'>At this point it's all in the hands of the beta testers.&lt;br /&gt;One found an issue with XServer and FXRuby on MacOS because I had set the row header width to 0.&lt;br /&gt;&lt;br /&gt;I confirmed on my eeepc and changed it to 1 pixel.&lt;br /&gt;Problem finished.&lt;br /&gt;&lt;br /&gt;The expectation is that I have a tech demo tomorrow so I pushed through the big changes version v.02 which boiled down to a restructuring of the layout, more unit tests, and a batch query process.&lt;br /&gt;&lt;br /&gt;On the Drails front, I've renamed it to FXCess.&lt;br /&gt;&lt;br /&gt;Using the template that I started with PaperTrade, I was able to quickly build some unit tests which confirmed that I can not only use ActiveRecord to interact with a small sqlite3 db but, also build using TDD which, for a project in which I have a very clear idea of what's going to happen is the fastest way to build.&lt;br /&gt;&lt;br /&gt;So far:&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;C:\fxcess\test&gt;ruby test_all.rb&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Loaded suite test_all&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Started&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;.....&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Finished in 0.531 seconds.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;5 tests, 7 assertions, 0 failures, 0 errors&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3412628233251595896-1308526105736974441?l=patrickonrails.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://patrickonrails.blogspot.com/feeds/1308526105736974441/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://patrickonrails.blogspot.com/2009/06/id3a-update.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3412628233251595896/posts/default/1308526105736974441'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3412628233251595896/posts/default/1308526105736974441'/><link rel='alternate' type='text/html' href='http://patrickonrails.blogspot.com/2009/06/id3a-update.html' title='ID3A update'/><author><name>patrick</name><uri>http://www.blogger.com/profile/15733281720346208032</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3412628233251595896.post-1372937778045946037</id><published>2009-06-19T05:06:00.000-07:00</published><updated>2009-06-19T05:24:53.394-07:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='ID3A'/><category scheme='http://www.blogger.com/atom/ns#' term='Drails'/><title type='text'>ID3A is born</title><content type='html'>Well, after several weeks of hitting my head against the wall of my imposed deadline, I am releasing ID3A (ID3 Analyser) to beta testers tonight.&lt;br /&gt;&lt;br /&gt;There are a lot of lessons learned in this first rush to beta and I'm going to jot them down now so I don't forget:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Ruby rules in just about every way. The ease of the programming language provided me the flexibility to bounce the code around and find out where things went wrong faster than any other language I've used before.&lt;/li&gt;&lt;li&gt;While I was kvetching about the lack of an IDE last time, I have to point out that FXRuby is so straightforward that one only needs to use google and the API to put pieces together. Case in point, I needed a file dialog form and initially I was afraid that I would have to cobble one together but, the FXFileDialog widget was already created and packed more functionality than I really needed.&lt;/li&gt;&lt;li&gt;&lt;span style="font-style: italic;"&gt;requires matter&lt;/span&gt; - as in where to put the 'require' statement. This should be top level and make sure that the "require 'fox 16' " is the top line. Otherwise you'll have a nice mess in the stdout as FXRuby reloads your requirements a second time&lt;/li&gt;&lt;li&gt;Ocra is a funny beast. It's a handy replacement for rubyscript2exe now that the latter is broken due to some changes in the Ruby internals however, it has some of it's own "gotchas" such as: location matters when compiling the Ruby application. Since I was coding on a virtual Windows XP system, I found that if I compiled on the desktop, I could only run it that desktop. Finally, I compiled in the root folder (C:\) and found that it would work in my Vista system's desktop.&lt;/li&gt;&lt;/ul&gt;I'm releasing a beta first as I want to take another whack at the code and "pretty it up" before releasing the actual source. Since I'm using three OSS apps (ai4r, fxruby, ocra) it feels correct to release ID3A's source code at some point.&lt;br /&gt;&lt;br /&gt;I'm grateful that one of my beta testers is none other than Sergio Fierens (author of ai4r) and I found him to be a great resource for a functionality that I wanted to add to my app which wasn't explicitly built into ai4r.&lt;br /&gt;&lt;br /&gt;Right now the majority of the beta testers are stock market traders so I expect that there is a strong probability that there may be changes to the application skewed towards that contingent.&lt;br /&gt;&lt;br /&gt;While this might seem a far afield from 'rails' it's not - I am beginning to expect that it would be a very simple thing to 'port' RoR onto the desktop.&lt;br /&gt;&lt;br /&gt;I hereby dub that project "Drails" (Desktop Rails).&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3412628233251595896-1372937778045946037?l=patrickonrails.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://patrickonrails.blogspot.com/feeds/1372937778045946037/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://patrickonrails.blogspot.com/2009/06/id3a-is-born.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3412628233251595896/posts/default/1372937778045946037'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3412628233251595896/posts/default/1372937778045946037'/><link rel='alternate' type='text/html' href='http://patrickonrails.blogspot.com/2009/06/id3a-is-born.html' title='ID3A is born'/><author><name>patrick</name><uri>http://www.blogger.com/profile/15733281720346208032</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3412628233251595896.post-3356039132538991444</id><published>2009-06-17T06:27:00.000-07:00</published><updated>2009-06-17T06:48:28.021-07:00</updated><title type='text'>Beta Cut 1 of ID3 app</title><content type='html'>Getting laid off was something that really impacted my development process as I've had to focus the marjority of my time on finding another job.&lt;br /&gt;&lt;br /&gt;While that has not borne fruit as of yet, I have completed two drafts of a white paper on creating classification trees (a la ID3) and thinking about how to build a Windows app in Ruby.&lt;br /&gt;&lt;br /&gt;Thankfully, there is FXRuby - which once one gets over the annoyance of there not being a sensible IDE to build the interface, the actual coding is pretty straightforward. Coming from a background of creating GUI interfaces in VBA for 8 years, it's a new experience to have to manually type out the location, properties, and relationships for each widget.&lt;br /&gt;&lt;br /&gt;Fortunately, Ruby gets the backend portion right making anything cobbled together in Visual Basic (including .NET) to be fairly lacking in robustness.&lt;br /&gt;&lt;br /&gt;Having looked at a few of the GUI kits in Java, I am also thankful that the author of FXRuby has adhered to Ruby standards and not twisted it into some Ruby looking, Java accented monstrosity to build around. There are enough Java coders out there doing nasty stuff to Ruby already as it is.&lt;br /&gt;&lt;br /&gt;The actual compilation to a Windows app is much easier with Ocra than the previous rubyscript2exe and allows for some niceties such as bundling in specific dlls. Once this project is out to the beta testers, I'm going to take a whack at creating a generic database creation tool with FXRuby and sqlite3. Sort of a poor man's Access if you will.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3412628233251595896-3356039132538991444?l=patrickonrails.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://patrickonrails.blogspot.com/feeds/3356039132538991444/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://patrickonrails.blogspot.com/2009/06/beta-cut-1-of-id3-app.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3412628233251595896/posts/default/3356039132538991444'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3412628233251595896/posts/default/3356039132538991444'/><link rel='alternate' type='text/html' href='http://patrickonrails.blogspot.com/2009/06/beta-cut-1-of-id3-app.html' title='Beta Cut 1 of ID3 app'/><author><name>patrick</name><uri>http://www.blogger.com/profile/15733281720346208032</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3412628233251595896.post-2395490871534953885</id><published>2009-02-15T06:01:00.000-08:00</published><updated>2009-02-15T06:10:43.929-08:00</updated><title type='text'>A slight Change in Dev Environs</title><content type='html'>Vista 64bit doesn't seem to like me at the moment as I am having issues installing software.&lt;br /&gt;&lt;br /&gt;Fortunately, for the project and the timeline I have, I can easily switch to Linux as I am doing currently for the sole purpose of adding graphs.&lt;br /&gt;&lt;br /&gt;Now this causes a problem in that I wanted to port this app using the Ruby2exe application, and while that application will create a Windows exe from within Linux - the problem is that the graphing was initially going to be done with Gruff and that requires ImageMagick to be installed in one form or another on the target system.&lt;br /&gt;&lt;br /&gt;So, I'll have to root around for another graphing subsystem or perhaps use jRuby (which I would like to avoid at all costs because it's not portable in a way that is simple for the end user).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;New Code&lt;/span&gt;&lt;br /&gt;module StatTools&lt;br /&gt;  def sum(seq)&lt;br /&gt;    total = 0&lt;br /&gt;    seq.each do |line|&lt;br /&gt;    total += line&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  def mean(seq)&lt;br /&gt;    return sum(seq) / seq.size.to_f&lt;br /&gt;  end&lt;br /&gt;&lt;br /&gt;  def moving_average(seq, num)&lt;br /&gt;    total = []&lt;br /&gt;    pad = num - 1&lt;br /&gt;    1.upto(pad) do |line|&lt;br /&gt;      total &lt;&lt; 0&lt;br /&gt;    end&lt;br /&gt;    num.upto(seq.size) do |line|&lt;br /&gt;      total &lt;&lt; mean(seq.slice(line - num, num))&lt;br /&gt;  end&lt;br /&gt;end&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3412628233251595896-2395490871534953885?l=patrickonrails.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://patrickonrails.blogspot.com/feeds/2395490871534953885/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://patrickonrails.blogspot.com/2009/02/slight-change-in-dev-environs.html#comment-form' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3412628233251595896/posts/default/2395490871534953885'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3412628233251595896/posts/default/2395490871534953885'/><link rel='alternate' type='text/html' href='http://patrickonrails.blogspot.com/2009/02/slight-change-in-dev-environs.html' title='A slight Change in Dev Environs'/><author><name>patrick</name><uri>http://www.blogger.com/profile/15733281720346208032</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3412628233251595896.post-3804692299067535915</id><published>2009-02-08T08:05:00.001-08:00</published><updated>2009-02-08T08:49:25.642-08:00</updated><title type='text'>A "hackish" data loader</title><content type='html'>If I'm going to be dealing with whacks of data, I want a fairly clean way of loading the data into the database in the format I specified.&lt;br /&gt;&lt;br /&gt;So, while the first order of business would be the creation of the PaperTrade class (which will be the first gem I release out of this work), I wanted a quick and dirty way to load the files so I had to do a few things first.&lt;br /&gt;&lt;br /&gt;0. Create the table on the database.&lt;br /&gt;&lt;ul&gt;&lt;li&gt;So, I created a sqlite3 file called "db.db" (because I like palindromes)&lt;/li&gt;&lt;li&gt;I used the table definition below (at some point I'll come back and create a migration for this&lt;/li&gt;&lt;li&gt;CREATE TABLE stocks(&lt;br /&gt;id integer primary key,&lt;br /&gt;name varchar(20),&lt;br /&gt;date integer,&lt;br /&gt;open float,&lt;br /&gt;high float,&lt;br /&gt;low float,&lt;br /&gt;close float,&lt;br /&gt;volume integer,&lt;br /&gt;adj_close float);&lt;/li&gt;&lt;/ul&gt;1. Creation of the Data Loader class.&lt;br /&gt;    There are a few notes to this:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;I use a couple of modules to abstract out the ActiveRecord calls so that the loader script which creates the DataLoad class will not have to deal with anything - the only part that is a bit unwieldy is that there is an "include Tables" to pull in the creation of the abstracted Stocks class. &lt;span style="font-style: italic;"&gt;On the whole, I believe there should be a more elegant way of dealing with this but for now, it works. The only time I think it will bite me will be if I build more on to this so that multiple tables are created. That could get overly messy&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The date format that the csv data I receive back from Yahoo! is DD/MM/YY which apparently is what it thinks all Canadian localised date formats should be. So, I had to create a twist date method to deal with that and it's highly idiosyncratic to my uses - you may not get the same mileage if your date data does not comply with that format. &lt;span style="font-style: italic;"&gt;Also, there is a bit of a "Y19K" thing going on so don't import any data prior to 1919 or use this class after 2019 ;-)&lt;/span&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Since I felt so "clever" with my Tables include, I decided to do one for the require statements.&lt;/li&gt;&lt;li&gt;module Requires&lt;br /&gt;    require 'activerecord'&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;module Tables&lt;br /&gt;    class Stock &lt; ActiveRecord::Base&lt;br /&gt;    end&lt;br /&gt;end&lt;br /&gt;&lt;br /&gt;class DataLoad   &lt;br /&gt;    include Requires&lt;br /&gt;    def initialize(data_file_load, stock_name, db_file_name)&lt;br /&gt;        @file_load = data_file_load&lt;br /&gt;        @name = stock_name&lt;br /&gt;        @db_file_name = db_file_name&lt;br /&gt;        @adapter = 'sqlite3'&lt;br /&gt;    end&lt;br /&gt;   &lt;br /&gt;    def connect_to_db&lt;br /&gt;        # Connect to a database&lt;br /&gt;        ActiveRecord::Base.establish_connection(&lt;br /&gt;        {:adapter =&gt; @adapter,&lt;br /&gt;        :database =&gt; @db_file_name})&lt;br /&gt;    end&lt;br /&gt;   &lt;br /&gt;    def twist_date(stringer)&lt;br /&gt;        months = ["", "jan", "feb", "mar", "apr", "may", "jun", "jul",&lt;br /&gt;        "aug", "sep", "oct", "nov", "dec"]&lt;br /&gt;        split_string = stringer.split('/')&lt;br /&gt;        short_date = split_string.last&lt;br /&gt;        if short_date.to_i &gt; 19 then&lt;br /&gt;            return_date = '19' + short_date&lt;br /&gt;        else&lt;br /&gt;            return_date = '20' + short_date&lt;br /&gt;        end&lt;br /&gt;        return [return_date.to_i, months[split_string[1].to_i], split_string[0].to_i]&lt;br /&gt;    end&lt;br /&gt;&lt;br /&gt;    def data_file_load&lt;br /&gt;        @data_load = []&lt;br /&gt;        File.open(@file_load) do |file|&lt;br /&gt;            while line = file.gets&lt;br /&gt;                @data_load &lt;&lt; line.chomp!&lt;br /&gt;            end&lt;br /&gt;        @headers = @data_load.shift&lt;br /&gt;        @headers.gsub!(/\"/,'')&lt;br /&gt;        end&lt;br /&gt;    end&lt;br /&gt;   &lt;br /&gt;    def csv_to_db&lt;br /&gt;        @data_load.each do |line|&lt;br /&gt;        nter = Stock.new&lt;br /&gt;        nter.name = @name&lt;br /&gt;        date_twisted = twist_date(line.split(',').first)&lt;br /&gt;        nter.date = Time.local(date_twisted.first, date_twisted[1], date_twisted.last).to_i&lt;br /&gt;        nter.open = line.split(',')[1].to_f&lt;br /&gt;        nter.high = line.split(',')[2].to_f&lt;br /&gt;        nter.low = line.split(',')[3].to_f&lt;br /&gt;        nter.close = line.split(',')[4].to_f&lt;br /&gt;        nter.volume = line.split(',')[5].to_i&lt;br /&gt;        nter.adj_close = line.split(',')[6].to_f&lt;br /&gt;        nter.save&lt;br /&gt;        end&lt;br /&gt;    end&lt;br /&gt;end #class End&lt;/li&gt;&lt;/ul&gt;At this point in time, I haven't written any unit tests but that should be in an upcoming post.&lt;br /&gt;&lt;br /&gt;2. The data loader script:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;# This is a script to load tables to the database&lt;br /&gt;&lt;br /&gt;require 'data_load_class'&lt;br /&gt;&lt;br /&gt;puts "enter the name of the csv file to load"&lt;br /&gt;data_file_load = gets.chomp!&lt;br /&gt;&lt;br /&gt;puts "enter the name of the identifer for the stock ex: USO"&lt;br /&gt;stock_name = gets.chomp!&lt;br /&gt;&lt;br /&gt;puts "enter the name of the database file"&lt;br /&gt;db_file_name = gets.chomp!&lt;br /&gt;&lt;br /&gt;a_data_loader = DataLoad.new(data_file_load, stock_name, db_file_name)&lt;br /&gt;&lt;br /&gt;a_data_loader.connect_to_db&lt;br /&gt;&lt;br /&gt;# We can only create the tables after we've connected&lt;br /&gt;# to the database&lt;br /&gt;include Tables&lt;br /&gt;&lt;br /&gt;# Get the data&lt;br /&gt;a_data_loader.data_file_load&lt;br /&gt;&lt;br /&gt;# Load 'em up&lt;br /&gt;a_data_loader.csv_to_db&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;Since I'm blogging the code as it exists today, there are a bunch of unpolished bits.&lt;br /&gt;&lt;br /&gt;The parts I'm most unhappy about are:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;The whole creating the ActiveRecord Stock class. I did quite a bit of reading on how to do this and wasn't pleased with any of the current solutions. I think Rails has it's own way of doing this so that's a study task for me.&lt;/li&gt;&lt;li&gt;Creating my own Y19K bug wasn't too pleasing but, I wanted to deal with the data as I was receiving it and not have ot 'normalise' the data through OOCalc or Excel if at all possible.&lt;/li&gt;&lt;li&gt;Lack of unit tests - I recognize this is a bit askew from my last post but, the fact of the matter is that I have not yet internalised the whole TDD because I have not made up my mind as to whether or not BDD (a la RSpec) makes more sense to me.&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;See you soon.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3412628233251595896-3804692299067535915?l=patrickonrails.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://patrickonrails.blogspot.com/feeds/3804692299067535915/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://patrickonrails.blogspot.com/2009/02/hackish-data-loader.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3412628233251595896/posts/default/3804692299067535915'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3412628233251595896/posts/default/3804692299067535915'/><link rel='alternate' type='text/html' href='http://patrickonrails.blogspot.com/2009/02/hackish-data-loader.html' title='A &quot;hackish&quot; data loader'/><author><name>patrick</name><uri>http://www.blogger.com/profile/15733281720346208032</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3412628233251595896.post-3333150801211381996</id><published>2009-02-04T18:55:00.000-08:00</published><updated>2009-02-11T14:52:34.442-08:00</updated><title type='text'>A (thumbnail) functional design</title><content type='html'>See-ell-o (I keep toying with the name) will have two fronts but with one core.&lt;br /&gt;&lt;br /&gt;The two fronts will be:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Utilizing Rails framework aimed at the inter(tubes)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Utilizing FXRuby and focused on Windows(tm) and Wine(tm) targets&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;The back end will start out as sqlite3 but may morph into mysql on the web end all things depending on how the development goes.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 255, 51);"&gt;Rationale&lt;/span&gt;&lt;br /&gt;The functional purpose is to leverage as much of the ActiveRecord goodness there is because, for the most part there will be one gargantuan table to pull from as I do not intend to over normalize one bit.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 255, 51);"&gt;DB Schema (version 0.0)&lt;/span&gt;&lt;br /&gt;Let me explain, since the application will be creating various options for reversal to mean genomes in a GA solution candidate, there will not be any real need to create a table for each equity so, for all purposes there will be one table with the following structures layout:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;id&lt;/li&gt;&lt;li&gt;name&lt;/li&gt;&lt;li&gt;date (in unixtime)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;open&lt;/li&gt;&lt;li&gt;high&lt;/li&gt;&lt;li&gt;low&lt;/li&gt;&lt;li&gt;close&lt;/li&gt;&lt;li&gt;volume&lt;/li&gt;&lt;li&gt;adjusted close&lt;/li&gt;&lt;/ul&gt;The first release will be primary a wizard which walks the user through the process of importing a csv file (from either google or yahoo) and loading up the database with that information.&lt;br /&gt;&lt;br /&gt;Then selections such as:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;population size&lt;/li&gt;&lt;li&gt;generations&lt;/li&gt;&lt;li&gt;cross over&lt;/li&gt;&lt;li&gt;mutation&lt;/li&gt;&lt;li&gt;reproduction selection (how much % of qualified candidates will breed)&lt;/li&gt;&lt;/ul&gt;and then the application will rip into the data creating the all the necessary ancillary data (moving day averages) on the fly and calculate the fitness function for each candidate.&lt;br /&gt;&lt;br /&gt;Fitness function will operate as follows:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;A class called "Paper Trade" will be created using data from test portion of data range&lt;br /&gt;&lt;/li&gt;&lt;li&gt;The candidate will take the starting equity and using buy and sell rules trade the "tape"&lt;br /&gt;&lt;/li&gt;&lt;li&gt;If the candidate finishes the "tape" with a positive equity then it will survive, if it is negative, then that is immediate grounds for removal as a breeder&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;Finally, (either using Ruport or Gruff) a report will be generated with various levels of peformance metrics. &lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="color: rgb(51, 255, 51);"&gt;Testing&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;I will be using &lt;a href="http://eigenclass.org/hiki.rb?rcov"&gt;rcov&lt;/a&gt; to identify where to build the tests.&lt;br /&gt;&lt;br /&gt;So, I intend to provide unit tests to keep my skills sharp in that endeavor but I will not be bound by them except at the point where I will be releasing this application as a gem (for desktop) or a Rails app (for the burgeoning Web 2.x).&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold; color: rgb(51, 255, 51);"&gt;Development Tools&lt;/span&gt;&lt;br /&gt;My primary development environment will be my Windows Vista 64bit Home Premium system. While I realise this might not be the most sexy environment (aka a Macintosh) or the most robust (Linux Mint excellence) - the fact of the matter is that there are specific challenges I mean to address for those Ruby on Windows users.&lt;br /&gt;&lt;br /&gt;Editor =&gt; irb, Notepad++&lt;br /&gt;Database =&gt; Sqlite3&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;notes: &lt;/span&gt;&lt;br /&gt;I use irb as my main development tool. By adding the irb-history module (notes &lt;a href="http://blog.nicksieger.com/articles/2006/04/23/tweaking-irb"&gt;here&lt;/a&gt;) and overworking the Marshal.dump and Marshal.load features - I am almost able to reach the Lisp goodness that allows the entire state to be saved and loaded for development.&lt;br /&gt;&lt;br /&gt;Since, irb is my main battleground and joy - it would be overkill to actually install Eclipse/Netbeans/Aptana Studio on my system and I would find it very counter productive.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;sqlite3 on Vista 64 bit:&lt;br /&gt;&lt;/span&gt;If you  found this blog by using the above line as a search criteria, then something has probably gone very wrong with the Google Spider.&lt;br /&gt;&lt;br /&gt;What I can tell you, hapless wanderer is what worked for me was to create a directory on the C: drive called sqlite and inside it put both the .dll and the executable.&lt;br /&gt;&lt;br /&gt;Then I simply added the folder to the path and voila - instant sqlite goodness on my Windows machine. (It took me the better part of an evening to finally figure that one out)&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;Why Windows?&lt;br /&gt;&lt;/span&gt;Pers&lt;span style="font-style: italic;"&gt;&lt;/span&gt;istent bugger aren't you?&lt;br /&gt;Well, here are a few thoughts on the whole Ruby/Windows mess:&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Everyone knows that Ruby runs very slow on Windows.&lt;/li&gt;&lt;li&gt;Except me - the first production quality app I developed was deployed on Windows and it was a major fail. It wasn't until much later that I &lt;a href="http://www.ruby-forum.com/topic/167421"&gt;discovered&lt;/a&gt; this is a long standing problem with Ruby.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;At the end of the day, there is a magnitude or order more Windows users than the other platforms combined so not optimising the code for that platform would be akin to biting off my nose to spite my face.&lt;/li&gt;&lt;li&gt;Knowing how Ruby works on Windows should make me more adept at working in multiple environments. With the current economic circumstances, it seems prudent to understand as many possible variations as I can.&lt;/li&gt;&lt;li&gt;Also, by supporting Wine as a platform, I can write one set of code and deploy on either Mac or *nix at will.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;I'm not an OS elitist. Case in point, when I was spending my days as a graphic artist on Macs, I was spending my evenings tinkering with Windows 95/98 shareware to do similar work and on weekends was taking classes that used Amigas.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;Back to the lab.&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;span style="font-weight: bold;"&gt;&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3412628233251595896-3333150801211381996?l=patrickonrails.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://patrickonrails.blogspot.com/feeds/3333150801211381996/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://patrickonrails.blogspot.com/2009/02/thumbnail-functional-design.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3412628233251595896/posts/default/3333150801211381996'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3412628233251595896/posts/default/3333150801211381996'/><link rel='alternate' type='text/html' href='http://patrickonrails.blogspot.com/2009/02/thumbnail-functional-design.html' title='A (thumbnail) functional design'/><author><name>patrick</name><uri>http://www.blogger.com/profile/15733281720346208032</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-3412628233251595896.post-622597672735206066</id><published>2009-01-29T16:41:00.000-08:00</published><updated>2009-01-29T16:57:07.292-08:00</updated><title type='text'>Let Me Introduce Myself</title><content type='html'>This blog will be about my adventures in Rubyland, with and without Rails.&lt;br /&gt;&lt;br /&gt;And all the other stuff that goes along with trying to create an application that will work the same way offline as it does for an online user.&lt;br /&gt;&lt;br /&gt;The application will be called see-ello and, according to the design documents I have in my notebook, it will be a Genetic Algorithm application that will be used to determinethe most successful "reversal to mean" methodologies for trading the SPY ETF.&lt;br /&gt;&lt;br /&gt;Here's some definitions for the first time reader:&lt;br /&gt;Genetic Algorithms =&gt; &lt;a href="http://en.wikipedia.org/wiki/Genetic_algorithm"&gt;wikipedia link&lt;/a&gt;&lt;br /&gt;Reversal to Mean =&gt; &lt;a href="http://www.investopedia.com/terms/m/meanreversion.asp"&gt;investopedia link&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;About Me&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;I am a professional Ruby on Rails developer working in an industry that neither uses evolutionary computing technologies nor exists within the financial trading industry.&lt;br /&gt;&lt;br /&gt;That's about all I will say about my professional life here. My opinions are my own, just as my personal life is different from my professional life. Ruby is a passion for me and I am very happy to work with it and be paid to do so but, I have found the best philosophy for myself and for any employer that I have worked for, is to maintain a fundamental firewall between the two&lt;br /&gt;domains.&lt;br /&gt;&lt;br /&gt;Yo hablo un poquito Español per no intendo escribir acqui en esta idioma.&lt;br /&gt;&lt;br /&gt;Well, that's about it for now.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/3412628233251595896-622597672735206066?l=patrickonrails.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://patrickonrails.blogspot.com/feeds/622597672735206066/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://patrickonrails.blogspot.com/2009/01/let-me-introduce-myself.html#comment-form' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/3412628233251595896/posts/default/622597672735206066'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/3412628233251595896/posts/default/622597672735206066'/><link rel='alternate' type='text/html' href='http://patrickonrails.blogspot.com/2009/01/let-me-introduce-myself.html' title='Let Me Introduce Myself'/><author><name>patrick</name><uri>http://www.blogger.com/profile/15733281720346208032</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='16' height='16' src='http://img2.blogblog.com/img/b16-rounded.gif'/></author><thr:total>0</thr:total></entry></feed>
