Sunday, December 19, 2010

Value investing screener

I needed a way to run a series of financial calculations over the entire Australian Stock Exchange (ASX).

Conventional stock screeners allow you to order by a whole bunch of parameters, but not your own customized formulas.

So I wrote a ASX value screener that focuses specifically on value investing. It consists of a calculator and a screener allowing you to calculate the future intrinsic value along the likes of Warren Buffett, Benjamin Graham and Australia's Roger Mongomerty.

I had this as an excel spreadsheet at first, but I figured if I wanted it - maybe someone else would too. So I used Ruby on Rails with the hobo plugin and I was up and running in a few minutes.

I spent a few months tidying up the design and getting user feedback, I'm pretty happy with the result. There's a small amount of traffic so I'm happy to keep the site up as it's regularly being used.

Sunday, October 10, 2010

Stu Bru 2

Stu Bru 2 was a noticeable improvement over Stu Bru 1. It was an Coopers IPA kit with 500g of light DME, 300 grams of dextrose. The addition of the DME has certainly helped the body and even though the Golding hops aren't 100% to my taste, it's still a very pleasant beer.

The head retention was good (if that matters at all). The flavour needs a little bit more personality, I'm hoping to use the Cascade hops to make the next version of this, and I'll up the bitterness too, it was a little tame for my tastebuds.

The alcohol should be quite low but after having just 750ml, I noticed this has a fair bit of kick. So I'll be drinking these slowly.

Here's a few photos from bottling:
Beer and bottles
Building up a sweat capping. Where are my 750ml bottles?
At least now these bottles contain some flavour. What a pain to cap though.


Voila! Putting them in containers in case they over-carbonate...aka explode.

Hobo on Heroku

Ok, this was an ordeal that I don't want to have to repeat. So here's how to get your Hobo 1.0.0 app up and running on Heroku.

I'm not going over registering at Heroku or setting up Hobo. I'll presume that you are competent enough to do this yourself with the current guides on their respective sites.
The basics for this post is Tom Locke's recipe at HoboCentral. Also note that the Heroku default server is Aspen (aspen-mri-1.8.6).

So I set up a simple Hobo 1.0.0 app with 1 model. Using ruby 2.3.8, I can test on my app on the development server - no problems.

You will need to add a .gems file in your root directory, that should have all the extra gems that you require. Heroku has a good set, but in order for completeness and futureproofing - add all the ones that you require. Mine looked like this (it will change by the end of this post):

rails -v 2.3.8
will_paginate --version 2.3.11
hobosupport --version 1.0.0
hobofields --version 1.0.0 --ignore-dependencies
hobo --version 1.0.0 --ignore-dependencies

When submitting this to heroku it doesn't start as:
Missing the Rails 2.3.8 gem. Please `gem install -v=2.3.8 rails`, update your RAILS_GEM_VERSION setting in config/environment.rb for the Rails version you do have installed, or comment out RAILS_GEM_VERSION to use the latest version installed.

I kept hitting this and there appears to be a problem with Heroku's server of choice 'thin' and hobo and 2.3.8 rails - it will not work with 2.3.8 - this means that you will have to roll back to 2.3.5 to get it up and running. I don't know enough about thin, all I know is that getting the thin gem and trying locally has the same error.

After changing to 2.3.5 in config/environment.rb and .gems:

rails -v 2.3.5
pg --version 0.8.0
will_paginate --version 2.3.11
hobosupport --version 1.0.0
hobofields --version 1.0.0 --ignore-dependencies
hobo --version 1.0.0 --ignore-dependencies

(I also added pg's gem not 100% sure that I need it, but I saw it on heroku's example)

This gets you past the rails problems, only to hit:

/config/initializers/cookie_verification_secret.rb:7: undefined method `cookie_verifier_secret=' for ActionController::Base:Class (NoMethodError)

This seems to be a hobo version error, some new functionality that doesn't work in 2.3.5, my app doesn't require user protection, so I manually edited cookie_verification_secret.rb, commenting out that line.

This is not an ideal solution (in fact I would just call it a hack), you would probably need to step back to an older version of Hobo, I'm hoping to look ahead to Hobo 1.3.x so I'm not worried about finding the correct old hobo version.

Once I did this I was able to:
heroku rake db:migrate

...and finally the app is up and running.

Hope this helps someone.

Wednesday, October 6, 2010

JNI - where's the env->CallStringMethod?

It makes me cry. JNI is a necessary evil, but still evil.

Why isn't there some nice way to call a CallStringMethod? Especially when working with
Android's bundles, which have getString. It would make life a million times easier.


Anyway here's a workaround:

jstring my_java_string = (jstring)env->CallObjectMethod(bundle, myBundle.getString, env->NewStringUTF("test"));
if(
my_java_string == NULL){
// Error
return;
}
char*
my_c_string = strdup(env->GetStringUTFChars(my_java_string, 0));
env->ReleaseStringUTFChars(
my_java_string, my_c_string);

Sunday, September 19, 2010

First Brew tasting

I was unsure that the brew was fermenting, as there were no bubbles whenever I checked. Then the bad (read: useless) bottle capper meant that there was such a loose seal that the beer didn't carbonate. This also led to a lack of cleaning of the bottles after the bottling as I didn't want to disturb the delicate seal. This caused mold, so I had to clean and dry the whole batch.

After purchasing a better bottle capper and re-sugaring the bottles (and waiting about 2 weeks) - Tasting time!

So bearing in mind that it was a bare bones homebrew kit (no dry malt extract - DME, hops etc.) it tasted like a slightly carbonated malty cordial with a slight apple aftertaste. I'd give it a 2 out of 10. Alcohol content really isn't a concern for me, it's all about flavour. But I would estimate about 4% due to some unreliable gravity readings.

The lessons learnt from this brew are:
  1. Don't skimp on a bottle capper - buy a good one!
  2. Dextrose is good but still gives a slightly appley after taste.
  3. No DME makes a fairly body-less beer.
  4. Thoroughly wash and dry the bottles after bottling and muck on the outside will cause mold.
So now I'm making a Coopers IPA to hopefully bring out some true flavour. I have used DME instead of half the sugar, and after reading up on other people's blogs and tasting the malt extract I decided to hold back on adding any extra hops.

So I'll report back with the results :)

Saturday, September 11, 2010

Google AI Comp

I'm entering the Google AI comp again this time - looking forward to challenge and aiming for a top ten result. Halla tummarna :)

For starters I'll get a basic bot then explore a few more advanced techniques. Watch this space.

Monday, August 9, 2010

First Brew

I remember Dad preparing a batch of homebrew in the evening then a lazy sunday spent bottling the 20 litres or so of beer. I have always wanted to brew over here in sweden but due to lack of linguistic knowledge, I have never found a place that I could pick up a plastic vat to ferment the beer. Until this afternoon. I went to Malmö and picked up a 25L vat with all the necessary equipment on my way to band practice.

As much fun as it was using it as a drum at practice, I brought it home tonight and using a Cooper's Pale Ale extract and a kilo of dexterous made my first brew. All ready to bottle over the weekend. I'll report back with photos and a flavour report.

Saturday, August 7, 2010

Open Drums

I wanted to be able to record any ideas I had for drum beats quick and easily. This was much simpler that I expeced.

After getting OpenDrums, and installing a few graphics packages:

$ sudo apt-get install libsdl1.2-dev libsdl-image1.2-dev libsdl-mixer1.2-dev
$ make

It works like a charm, now to change the default sounds to something a little more realistic.

Monday, August 2, 2010

Canon Pixma MP270 driver in 64bit Ubuntu

Canon provides the 32bit drivers to the Pixma MP270, but not 64 bit driver. Instead of building them from source, just get the 32 bit drivers from canon's site.

In the packages directory there are 2 debs. All you need to do now is:

sudo dpkg -i --force-architecture ./cnijfilter-common_3.20-1_i386.deb
sudo dpkg -i --force-architecture ./cnijfilter-mp270series_3.20-1_i386.deb

And the printer should work :)

Sunday, August 1, 2010

Ruby on rails 3 - rvm, bundle, eeeekk

Having a freshly loaded Ubuntu 10.04 on my main desktop (after checking it out for months on my laptop), I thought I'd get ruby on rails set up. After setting up Rails 2 with the minimum of fuss, I took the challenge of upgrading to Rails 3 (release candidate).

RVM is now an essential component of any rails environment, letting you change between rails version in an instant (Theoretically, but more on that soon).

Installing it was as simple as:
$ bash < <( curl http://rvm.beginrescueend.com/releases/rvm-install-head )

After installing all the necessary ubuntu packages

$ rvm install 1.9.2-rc2
$ rvm 1.9.2-rc2
$ gem install rails --pre

I can't seem to switch between rubies as I would like, but I'm sure I can solve this soon.

To start a new project we have to forget the rails 2 ways and start with:

$ rails new test
_project

You should see the usual files (plus a few new ones) being created.

$ cd test_project
$ bundle install

This is where I had some problems with mysql. I had installed every possible mysql package but it stll wasn't working.

Using activeresource (3.0.0.rc)
Using bundler (1.0.0.rc.1)
Installing mysql (2.8.1) with native extensions /usr/local/lib/site_ruby/1.8/rubygems/installer.rb:483:in `build_extensions': ERROR: Failed to build gem native extension. (Gem::Installer::ExtensionBuildError)

/usr/bin/ruby1.8 extconf.rb
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lm... yes
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lz... yes
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lsocket... no
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lnsl... yes
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lmygcc... no
checking for mysql_query() in -lmysqlclient... no
*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of
necessary libraries and/or headers. Check the mkmf.log file for more
details. You may need configuration options.

Provided configuration options:
--with-opt-dir
--without-opt-dir
--with-opt-include
--without-opt-include=${opt-dir}/include
--with-opt-lib
--without-opt-lib=${opt-dir}/lib
--with-make-prog
--without-make-prog
--srcdir=.
--curdir
--ruby=/usr/bin/ruby1.8
--with-mysql-config
--without-mysql-config
--with-mysql-dir
--without-mysql-dir
--with-mysql-include
--without-mysql-include=${mysql-dir}/include
--with-mysql-lib
--without-mysql-lib=${mysql-dir}/lib
--with-mysqlclientlib
--without-mysqlclientlib
--with-mlib
--without-mlib
--with-mysqlclientlib
--without-mysqlclientlib
--with-zlib
--without-zlib
--with-mysqlclientlib
--without-mysqlclientlib
--with-socketlib
--without-socketlib
--with-mysqlclientlib
--without-mysqlclientlib
--with-nsllib
--without-nsllib
--with-mysqlclientlib
--without-mysqlclientlib
--with-mygcclib
--without-mygcclib
--with-mysqlclientlib
--without-mysqlclientlib


Gem files will remain installed in /home/stumacd/RoR/projects/wiki/ruby/1.8/gems/mysql-2.8.1 for inspection.
Results logged to /home/stumacd/RoR/projects/wiki/ruby/1.8/gems/mysql-2.8.1/ext/mysql_api/gem_make.out
from /usr/local/lib/site_ruby/1.8/rubygems/installer.rb:446:in `each'
from /usr/local/lib/site_ruby/1.8/rubygems/installer.rb:446:in `build_extensions'
from /usr/local/lib/site_ruby/1.8/rubygems/installer.rb:198:in `install'
from /usr/lib/ruby/gems/1.8/gems/bundler-1.0.0.rc.1/lib/bundler/source.rb:96:in `install'
from /usr/lib/ruby/gems/1.8/gems/bundler-1.0.0.rc.1/lib/bundler/installer.rb:51:in `run'
from /usr/lib/ruby/gems/1.8/gems/bundler-1.0.0.rc.1/lib/bundler/spec_set.rb:12:in `each'
from /usr/lib/ruby/gems/1.8/gems/bundler-1.0.0.rc.1/lib/bundler/spec_set.rb:12:in `each'
from /usr/lib/ruby/gems/1.8/gems/bundler-1.0.0.rc.1/lib/bundler/installer.rb:40:in `run'
from /usr/lib/ruby/gems/1.8/gems/bundler-1.0.0.rc.1/lib/bundler/installer.rb:8:in `install'
from /usr/lib/ruby/gems/1.8/gems/bundler-1.0.0.rc.1/lib/bundler/cli.rb:115:in `install'
from /usr/lib/ruby/gems/1.8/gems/bundler-1.0.0.rc.1/lib/bundler/vendor/thor/task.rb:22:in `send'
from /usr/lib/ruby/gems/1.8/gems/bundler-1.0.0.rc.1/lib/bundler/vendor/thor/task.rb:22:in `run'
from /usr/lib/ruby/gems/1.8/gems/bundler-1.0.0.rc.1/lib/bundler/vendor/thor/invocation.rb:109
from /usr/lib/ruby/gems/1.8/gems/bundler-1.0.0.rc.1/lib/bundler/vendor/thor/invocation.rb:116:in `call'
from /usr/lib/ruby/gems/1.8/gems/bundler-1.0.0.rc.1/lib/bundler/vendor/thor/invocation.rb:116:in `invoke'
from /usr/lib/ruby/gems/1.8/gems/bundler-1.0.0.rc.1/lib/bundler/vendor/thor.rb:161:in `start'
from /usr/lib/ruby/gems/1.8/gems/bundler-1.0.0.rc.1/lib/bundler/vendor/thor/base.rb:379:in `start'
from /usr/lib/ruby/gems/1.8/gems/bundler-1.0.0.rc.1/lib/bundler/vendor/thor.rb:140:in `start'
from /usr/lib/ruby/gems/1.8/gems/bundler-1.0.0.rc.1/bin/bundle:13
from /usr/bin/bundle:19:in `load'
from /usr/bin/bundle:19

The trick was to install it with the correct parameters (found by using $ which mysql)

$ gem install mysql -- --with-mysql-conf=/usr/bin/mysql --with-mysql-lib=/usr/lib/mysql

This allowed all the applicable gems to be installed.

And now with a:

$ rails server

WEBrick was up and running and http://localhost:3000 was showing the standard page. Gold dust :)

Saturday, July 17, 2010

Decapus - 10 legged power supply



Having built guitar effects pedals for the last 10 years, I've progressed from battery power to requiring a power splitter for a decently powered DC adapter.

The overall plan is to put the power supply on the underside of the pedalboard, so I needed about 10 outputs and four to be longer than others.



It's a very simple design, but it really needs to work reliably and a minimum parts count was desireable.



So it's not that pretty, but it's rugged enough to sit on the bottom of the pedalboard without to any dramas.

Friday, July 16, 2010

Codility

I was reading a blog concerning how to hire new programmers. According to this blog, one of the classic mistakes some recruiters make is that they don't get the propsective candidate to write any code during the interview. This seems a bit odd, but I guess in some small companies they may not have the competence to select their first programmer. This blog mentioned Codility, a way to test a candidate's programming skills.

I headed over and liked the design and thought I'd take the demo test. I recommend you give it a go and come back after that.

It was a neat and easy to understand interface. I selected C as it's my weapon of choice for everything except for applications that need extensive string handling (in which case the String class makes bothering with Java worthwhile).

They had a fair problem and a suboptimal solution as a framework. After coding my most intuitive solution (for those who tried the demo, getting the righthand side total then:

for(i=0;i<n;i++){
rsum -= arr[i];
if (lsum == rsum) return i;
lsum += arr[i]; }


To avoid arithmetic overflow, the array consists of doubles to be on the safe side. I overlooked this the first time in.

Anyway, in the 30mins I got it except for the overflow, which I went back and checked that it worked. I wish there were a few more tests like this as work doesn't exercise all my c muscles :) Props to Codility hopefully a thing of the future.

Thursday, March 18, 2010

Round up of the Google AI Competition

Well the competition got a lot harder once the maps changed, the real top bots certainly rose to the top. Congratulations to the winners!

My reflections on the competition:
  • Nicely run and nice that it adapted to the demands of the players
  • Great to have the ability to watch the matches afterwards.
  • Some very talented AI guys out there - with a fair bit of time on their hands.

My bot:
  • Instead of doing a minimax on my move then the opponents move, it should have used the syncronous nature of movement to analyse the 9 (apart from the first move with all 4 directions available to both players) feasiable options.
  • I would have ideally trimmed the resultant decision tree in a logical manner, searching deep on both sideways options and that would often beat the opposition, by adventagously cutting the areas.
  • My initial implimentation of 'first to the most squares' was buggy, it would have been great to sort it out. so the bot didn't make such obvious bad moves.
  • Using a more optimized 'first to most squares' algorithm. I should have made a list of the coordinates to go over in the next run, meaning that only 1-20 squares were checked rather than all squares.
I lacked the time to impliment these options, but that's no excuse, just the way it was. I had great fun and I'll be looking for the next challenge from the University of Waterloo CS Club.

I'll throw my code up here for anyone that wants a slightly buggy (but very fixable) tron bot.

In fact I have a few versions - one in perticular was stable but didn't search very deep.

Sunday, February 21, 2010

Google AI bot

Well I achieved my initial goal of getting into the top 10, only to be hoinked out to around 100 as the opposition got a lot stronger once the maps changed to avoid draws.

The bots that seem to beat mine have great depth in their searches. I'm using minimax with alpha beta pruning which is probably what they're using so search depth isn't the issue. So I figure their evaluation functions are finding the better moves at the same depths. My rudimentary 'most available squares' approach needs an upgrade. Without adding too much time as the evaluation function is called quite frequently (around 10000 times per second).

With the middle island forming a significant 'block' I need to get better at luring them my way, cutting their approach off then going around the other side and cutting at a point favourable to me. I'm going to try changing the evaluation function that evaluates which player is first to each square. This should give me a better sense of where a future border will be and hence try to maximize my player's area.

Link to my bot

Wednesday, February 10, 2010

Google AI Competition

Hmmm, how good are AI comps? I am letting my inner geek take over for the next few days as I put the evil stumac bot in Google's AI comp.

I am currently 30th (out of 415 entrants) with a few things still to do to really make my bot competitive.

To begin with I implemented a basic strategy and that had me at 90th out of 400. When I say basic, I mean really basic (code to come after the competition).

I then added a minimax look ahead, this currently looks ahead 9 moves, a bug was causing me to lose games.

So now I will:
  • alpha beta prune my minimax.
  • upgrade my evaluation function.
  • add a 'in same area' check and revert to flooding if in separate areas.
  • Add a timing check (if possible) to give a good answer before timing out.
Should be fun!

Hopefully this should be able to get us into the top 10.