2014年4月11日金曜日

SBI証券から無料でリアルタイム株価を取得するライブラリ

HFT(もどき)が個人でもできないかと方法を探していたのですが、個人にストリーミングの株価データを配信してくれるところが見つからず。
しかたがないので、SBI証券のリアルタイム更新を利用して、ほぼリアルタイム(3秒ディレイくらい)で株価を取得できるライブラリを作りました。
SBI証券のアカウントは必須です。

まずはインストール

  1. gem install Sbirsp  
使い方のサンプル
  1. require "sbirsp"  
  2.   
  3. Sbirsp.configure do |config|  
  4.   config.username = "user_id"  
  5.   config.password = "password"  
  6. end  
  7.   
  8. @client = Sbirsp::Client.new  
  9. @client.code = 9984  
  10. @client.show_stock_price  
  11.   
  12. loop do  
  13.   if @old_price != @client.price  
  14.     puts "#{@client.price}"  
  15.     @old_price = @client.price  
  16.   end  
  17. end  
複数クライアントを同じプロセス内で起動した時の動作が怪しいので、なんとか調整したい。

 githubにソースコードをアップしています。
  https://github.com/face-do/sbirsp

2013年3月15日金曜日

rubyからr言語を使って、キャンペーン前後で売上に変化があったか判断する

同一期間ではないので、対応のない場合のt検定を行います。
rubyからR言語を使うには、rsrubyというライブラリを使う。

まずはRのインストール
$ brew install R

で、rのpathを設定します。
$ export R_HOME=/Library/Frameworks/R.framework/Resources

次にrsrubyのインストール
$ gem install rsruby -- --with-R-include=/Library/Frameworks/R.framework/Headers --with-R-lib=/Library/Frameworks/R.framework/Libraries

で、準備は完了。

今回はこんな感じの想定です。
・送料無料キャンペーン(今まで送料無料ではなかった部分の売上が増える=平均単価が減少する仮説)
・送料無料キャンペーンをやっていなかった、去年の売上と今年の売上を比較
・月初から今日までの期間を考える


以下がコード

まずはヒストリカルグラフで確認
  1. require 'rsruby'  
  2.   
  3. r = RSRuby::instance  
  4. x = Order.where("created_at between ? and ?" , Time.now.beginning_of_month, Time.now).map(&:price).(&:to_f)  
  5. y = Order.where("created_at between ? and ?" , Time.now.beginning_of_month - 1.years, Time.now - 1.years).map(&:price).(&:to_f)  
  6.   
  7. r.eval_R(<<-RCOMMAND)  
  8.   
  9. hist(#{y.join(",")}, breaks = 5 ,col = "#0000ff40", border = "#0000ff", freq = TRUE)  
  10. hist(#{x.join(",")}, breaks = 5 ,col = "#ff00ff40", border = "#ff00ff", freq = TRUE, add = TRUE)  
  11.   
  12. RCOMMAND  
一応F検定
  1. r.var_test(x, y)  

t検定
  1. r.t_test(x, y, altenative="two.sided")  

するとこんな感じの結果がでます。

 {"statistic"=>{"t"=>1.8121550934930575}, "parameter"=>{"df"=>4.0}, "p.value"=>0.1441855869309796, "conf.int"=>[-14560.490812856453, 69286.49081285646], "estimate"=>{"mean of x"=>32613.0, "mean of y"=>5250.0}, "null.value"=>{"difference in means"=>0.0}, "alternative"=>"two.sided", "method"=>"Welch Two Sample t-test", "data.name"=>"c(63210L, 14385L, 74970L, 5250L, 5250L) and c(5250L, 5250L)"}

2013年3月4日月曜日

ruby2.0 on Rails4.0でABテストができる短縮URLサービスを作った

先日ruby2.0が公開され、Rails4.0がついにbetaとしてgem化されていたので、早速使ってみた。

作ったサービスは、こちら http://url-s.herokuapp.com/

ソースはgithubにあげてあります。

これは2種類以上のURLを登録できる短縮URLサービスです。
外部サービスを利用していてABテストができないときに、2種類のランディングページを用意しておいて、短縮URLでランダムに飛んでもらいテストするという用途を想定しています。

以下ruby2.0とRails4.0を使ってみた感想。

  • 起動早い。2.0のおかげだと思うけど、前の環境には戻りたくない
  • マジックコメントいちいち書かなくていいの最高!
  • strong paramerterでちょいはまり。特にネストしたモデルのを扱うなら、attributesの方のidを許可しないと、updateした時に、新規で作成されてしまうので注意。
  • find_byメソッドのほうが直感的でよい。というかなんでそうじゃなかったの?

結論。 新規でアプリ作る場合、特に躊躇する理由もないので、この組み合わせで積極的に使っていきたい。

2013年1月19日土曜日

railsでorder時に特定IDのデータだけ、前に持ってくる方法

例えば、IDが1〜10のデータがある時に、IDの降順にしようとした時には
  1. Model.order("id desc").all  
などとするが、時々この中の一部(例えばID:3)は先頭に、それ以外はIDの降順にしたいときなどがある。
そんなときは、
  1. Model.order("'id' = CASE WHEN id = 3 THEN 0 ELSE 'id' END").order("id desc").all  
などとすると、できる。

2013年1月10日木曜日

vanityとchankoを使ってRailsで簡単安全にABテストをする

vanityはRailsのABテスト用ライブラリ。導入が一番簡単っぽい。
 元々はテキストとか画像をのABテストを行うためのもののようだが、 chankoという限定公開用のライブラリを使って、機能単位でもABテストができるようにしてみる。

まずはGemfileに
  1. gem 'chanko':git => 'git://github.com/cookpad/chanko.git'  
  2. gem "vanity"  
を記述して、
# bundle install

それぞれに必要な初期設定をする。
# rails generate chanko:install
# rails generate vanity
# rake db:migrate

config/vanity.ymlを作成
  1. development:  
  2.   adapter: active_record  
  3.   active_record_adapter: mysql2  
  4.   host: localhost  
  5.   database: DBNAME  
  6.   user: USERNAME  
  7.   password: PASSWORD  

development.rbに以下を記述
  1. Vanity.playground.collecting = true  

vanityのDashboard用コントローラを作成
  1. class VanityController < ApplicationController  
  2.   include Vanity::Rails::Dashboard  
  3. end   

ルーティングを設定
  1. match '/vanity(/:action(/:id(.:format)))':controller=>:vanity  

測定用のユーザアイデンティティを設定。
  1. class ApplicationController < ActionController::Base  
  2.   use_vanity :current_user  
  3. end  

Railsのルートディレクトリ下にテストと測定用のファイルを作成
#mkdir -p experiments/metrics

postした回数測定用のファイルを作成
experiments/metrics/post.rb
  1. metric "Post" do  
  2.   description "Postした回数"  
  3. end  

コントローラの好きな場所に、 track! :post を入力すれば、その場所がよばれた回数を測定できるようになります。
  1. class PostController < ApplicationController  
  2.   def create  
  3.      track! :post  
  4.        # ...投稿する処理  
  5.      end  
  6.   end  
  7. end  

テスト用ファイルを作成
experiments/post_labels.rb
  1. ab_test "Post labels" do  
  2.   description "テスト"  
  3.   alternatives truefalse  
  4.   metrics :post  
  5. end  

次にchanko用設定
# rails generate chanko sample
  1. module Sample  
  2.   include Chanko::Unit  
  3.   
  4.   active_if do |context, options|  
  5.     ab_test(:price_options)   
  6.   end  
  7.   scope(:controllerdo  
  8.     function(:controller_showdo  
  9.       # controller code here  
  10.     end  
  11.   end  
  12.   scope(:viewdo  
  13.     function(:view_showdo  
  14.       render :partial => "/show"  
  15.     end  
  16.   end  
  17. end  
で、好きな場所にinvoke(:sample, :controller_show) をおいたり、
invoke(:sample, :show) を置けばOK。
chankoの詳しい使い方はこちらを参考に。

どちらが優位かなんてのは、Vanityが表示してくるので、 評価しやすいはず。

production環境でうまく動かなかったので、
そのときはredisによる接続をためしてみるといいかも。
  1. production:  
  2.   adapter: redis  
  3.   host: localhost  



 参考:
http://eccyan.hatenablog.com/entry/2011/12/08/223603
https://github.com/assaf/vanity
http://webandy.com/articles/a-b-testing-with-vanity

2012年12月5日水曜日

rubymotionとrailsの連携を試行錯誤した話

この記事はRubyMotion Advent Calendar 2012の5日目記事です。

rubymotionメリットのひとつに、サーバサイド(Rails)とクライアントサイドが同じ言語でかけることがあると思いますが、
思いの外Railsとどう連携していくかの情報が少ないような気がします。
なので他の人の参考になればと、個人的に試行錯誤したことを残しておこうと思います。

ちなみに、one minutesというアプリを、rubymotionで作りましたので、よければダウンロードしてください。

試行錯誤1、babble-wrapで都度処理を書く

先述のone minutesでは、表示させるニュース情報をサーバからjsonで取得するだけの単純作業なので、以下の様な感じで実装しました。

  1. BW::HTTP.get(SERVER_URL) do |response|  
  2.   if response.ok?  
  3.     @data = BW::JSON.parse(response.body.to_str)  
  4.   else  
  5.     App.alert(response.error_message)  
  6.   end  
  7. end  

実装はかなり楽でしたが、複数情報を取得したい先がある場合や、postを行うときには、かなり面倒なことになってしまいました。
それが↓です。

試行錯誤2、babble-wrapで都度処理を書く(その2)

ソーシャルアプリを作ろうとした際の実装です。
アプリ概要は、facebookみたいなものなので、記事の投稿、投稿に対するコメント、投稿に対するいいね、それぞれを表示させるタイムラインの実装が必要でした。
それが下記コード群です。

#記事読み込み
  1. BubbleWrap::HTTP.get("#{SERVER_URL}/entries.json?page=#{@page}"do |response|  
  2.   if response.ok?  
  3.     json = BubbleWrap::JSON.parse(response.body.to_str)  
  4.     unless json.count == 0  
  5.       @table_dates << json  
  6.       self.tableView.reloadData  
  7.       @page += 1  
  8.       @readMoreButton.enabled = true  
  9.       @readMoreButton.hidden = false if @page  
  10.     else  
  11.       @page = nil  
  12.       @readMoreButton.hidden = true  
  13.     end  
  14.   else  
  15.     App.alert(response.error_message)  
  16.    end  
  17. end  
#記事投稿
  1. BubbleWrap::HTTP.post("#{SERVER_URL}/entries.json", {payload: data})  
#コメント
  1. BubbleWrap::HTTP.post("#{SERVER_URL}/comments.json", {payload: data}) do |response|  
  2.    if response.ok?  
  3.      App.alert("コメントしました")  
  4.    elsif response.status_code.to_s =~ /40\d/  
  5.     App.alert("comment failed")  
  6.    else  
  7.     App.alert(response.error_message)  
  8.   end  
  9. end  
#いいね
  1. BubbleWrap::HTTP.post("#{SERVER_URL}/likes.json", {payload: data}) do |response|  
  2.    if response.ok?  
  3.       App.alert("likeしました")  
  4.     else  
  5.      App.alert(response.error_message)  
  6.    end  
  7.  end  

企画自体が没になったため、コレ以上コードは書いていないのですが、
重複が多く、メンテナンス性も非常に悪いものができてしまいました。

で、このあとECアプリを作ることになりました。
これまでの経験を踏まえ、もう少しRailsライクに実装したいと感じるように。

具体的には、
1.new、find、save、allなどで情報が取得や保存ができるように
2.バリデーションエラーは、その内容までも分かるように
3.ネットワークエラーなどがでたら、バリデーションエラーなどとは別に判別できるように

という理想を掲げ、作ってみた現実(ライブラリ)はこちら。
https://github.com/face-do/motion-rails-model

初めて作ったライブラリでもあり、非常にできはよくないのですが、それでも一応の理想は実現できました。
(といっても、babble-wrapのさらにwrapperライブラリだったりしますが。。。)

使い方としては、最初にアクセスしたいURLやbasic認証の情報を入力


  1. RM::Model.set_url("#{URL}/api/")  
  2. RM::Model.set_username("username")  
  3. RM::Model.set_password("password")  

その後モデル用のクラスを作り、ライブラリを継承。

  1. class Orders < RM::Model  
  2.   attr_accessor :name  
  3.    
  4.   def attributes_update(json)  
  5.     @name = json['name']  
  6.     super  
  7.   end  
  8. end  

これで、

  1. order = Orders.new  
  2. order.name = "hogehoge"  
  3. order.save do |x|  
  4.   if x.ok?  
  5.     App.alert("保存しました。")  
  6.   end  
  7. end  

とかすると、
railsに対して
/api/orders.json?name=hogehoge
のpostメソッドを実行するし、

  1. Orders.find(1) do |x|  
  2.   if x.ok?  
  3.     @order = x.body  
  4.   end  
  5. end  

で、
/api/orders/1.json
のgetをしたりします。

またgetしてきた、Objectに対してsaveをすると、
/api/orders/1.json
に対してputをするようになってます。

これを作った後、メタプログラミングrubyを読みまして、
もう少し抽象化ができそうな気がしているので、機会を見て修正していく予定です。

2012年10月29日月曜日

今ウェブサイトを作るなら必須のアイコン画像サイズ一覧


漏れがないようにまとめてみました。

サイト全体
favicon
16×16

facebook(OGP)対策
200x200

ウェブクリップアイコン(ios、android)対策
114×114(iPhone、iPod touchのRetina)
57×57(iPhone、iPod touchの非Retina)
144×144(iPadのRetina)
72×72(iPadの非Retina)

一括作成サービスができてくれるといいなあ。