無料で使えるシステムトレードフレームワーク「Jiji」 をリリースしました!

・OANDA Trade APIを利用した、オープンソースのシステムトレードフレームワークです。
・自分だけの取引アルゴリズムで、誰でも、いますぐ、かんたんに、自動取引を開始できます。

メソッド実行結果をキャッシュする

Rubyオブジェクトのメソッド実行結果をキャッシュするユーティリティを書きました。

  • メソッドインターセプタで実装しています。任意のクラスのメソッド実行結果を透過的にキャッシュ可能にします。
  • キャッシュはYAMLファイルに記録されます。
require "fileutils"
require 'file-lock'
require 'kconv'
require 'yaml'

module Cache

  #
  # メソッドの実行結果をYAMLファイルにキャッシュする
  #   delegate 実行結果をキャッシュするオブジェクト
  #   enable キャッシュを利用するかどうか。
  #   range キャッシュの有効期限。秒で指定
  #   cache_file キャッシュファイル
  #   regex キャッシュ対象メソッド
  #
  class YAMLCache
    def initialize(delegate, enable, range, cache_file, regex=".*")
      @delegate = delegate
      @range = range
      @cache_file = cache_file
      @regex = regex
      @enable = enable
    end

    def method_missing(name, *args )

      return @delegate.send( name, *args ) if ( !name.to_s.match(@regex) )

      flock = FileLock.new(@cache_file + ".lock")
      current = Time.new

      res = nil
      flock.writelock(){
        # キャッシュがあればキャッシュから読む
        if ( @enable && File.exist?(@cache_file) && current.to_i < (File.mtime(@cache_file).to_i + @range) )
          res = YAML.load_file @cache_file
        elsif
          res =  @delegate.send( name, *args )
          File.open( @cache_file, "w" ) { |f|
            f.write( YAML.dump(res) )
          }
          File.utime(current, current, @cache_file)
        end
      }
      return res
    end
  end
end

動作確認。

#動作確認
service = Cache::YAMLCache.new(Test.new, true, 3, "../test-cache.yaml", "search")

puts service.search("b", "xxxx1")  # 初回。結果がキャッシュされる
sleep(1)
puts service.search("b", "xxxx2") # キャッシュが有効期間内なのでキャッシュから結果が返される。
sleep(5)
puts service.search("b", "xxxx3") # 有効期限が過ぎたのでキャッシュは無効

# 正規表現にマッチしないメソッドの戻り値はキャッシュされない
puts service.hoge("c", "xxxx1") 
puts service.hoge("c", "xxxx2") 

実行結果です。

search_bxxxx1
search_bxxxx1
search_bxxxx3
hoge_cxxxx1
hoge_cxxxx2