『Rubyではじめるシステムトレード』第15章~第16章 学習記録

Rubyではじめるシステムトレード (現代の錬金術師シリーズ)

Rubyではじめるシステムトレード (現代の錬金術師シリーズ)

序文

Rubyではじめるシステムトレード』6日目。

もうGW1週間なんですねぇ。
例年以上に代わり映えない毎日ですがなんとなく充実してる気もするぞ。

進捗

  • 第3部 シミュレーション編
    • 第15章 Tickモジュール
    • 第16章 Ruleとその子クラス

(学習時間:6時間)

GitHub

github.com

コード実装部分(一部)

RubySystemTrade\trade_simulator\check\rule_check.rb

#coding: Windows-31J

require "pp"
require "./lib/stock"
require "./lib/base"
require "./lib/tick"

# Entryから仕掛けクラスを作るテスト
class MyEntry < Entry
    def check_long(index)
        enter_long(index, 100, :close) if index % 2 == 0
    end

    def check_short(index)
        enter_short(index,100, :close) if index % 2 == 1
    end
end

puts '=== ENTRY ==='
stock = Stock.new(1000, :t, 100)

entry = MyEntry.new

entry.stock = stock

# indexが偶数なら買いでインする
pp entry.check_long_entry(0)
# indexが奇数なら買いでインしない
pp entry.check_long_entry(1)

# indexが偶数なら売りでインしない
pp entry.check_short_entry(0)
# indexが奇数なら売りでインする
pp entry.check_short_entry(1)

# Exitから手仕舞いクラスを作るテスト
class MyExit < Exit
    def check_long(trade, index)
        exit(trade, index, 105, :close) if index % 2 == 1
    end

    def check_short(trade, index)        
        exit(trade, index, 95, :close) if index % 2 == 0
    end
end

puts '=== EXIT ==='
my_exit = MyExit.new
my_exit.stock = stock
# 買いでインする
trade1 = entry.check_long_entry(0)
# indexが偶数なら買いを手仕舞わない
my_exit.check_exit(trade1, 0)
puts trade1.entry_price
puts trade1.exit_price
# indexが奇数なら買いを手仕舞い
my_exit.check_exit(trade1, 3)
puts trade1.entry_price
puts trade1.exit_price

# 売りでインする
trade2 = entry.check_short_entry(1)
# indexが奇数なら売りを手仕舞わない
my_exit.check_exit(trade2, 55)
puts trade2.entry_price
puts trade2.exit_price
# indexが奇数なら売りを手仕舞う
my_exit.check_exit(trade2, 2)
puts trade2.entry_price
puts trade2.exit_price

class MyStop < Stop
    def stop_price_long(position, index)
        # 5Tick下に損切りラインを置く
        Tick.down(position.entry_price, 5)
    end
    def stop_price_short(position, index)
        # 5Tick上に損切りラインを置く
        Tick.up(position.entry_price, 5)
    end
end

puts '=== STOP ==='
stop = MyStop.new
# 買いでインする
trade3 = entry.check_long_entry(0)
puts stop.get_stop(trade3, 0)

# 売りでインする
trade4 = entry.check_short_entry(1)
puts stop.get_stop(trade4, 1)

class MyFilter < Filter
    def filter(index)
        case index % 4
        when 0
            :long_only
        when 1
            :short_only
        when 2
            :no_entry
        when 3
            :long_and_short
        end
    end
end

filter = MyFilter.new

puts '=== FILTER ==='
p filter.get_filter(0)
p filter.get_filter(1)
p filter.get_filter(2)
p filter.get_filter(3)

実行結果

f:id:yjkym:20190503183434p:plain:w200

感想

15章では株価の呼値単位に対応するTickクラスを実装。概ね問題なし。

16章ではトレードに使用するルールを規定するRuleクラスを作成していく。
ルールには「仕掛け(株を買うこと)」「手仕舞い(買った株を売ること)」「ストップ(損失が拡大しないように設定するルールのこと)」「フィルター(仕掛ける条件)」が含まれ、それぞれRuleの子クラスとして、Entryクラス、Exitクラス、Stopクラス、Filterクラスとして実装する。

ストップ(損切りライン)を指定しながら、利益確定ラインを作らなかったり、「仕掛け」クラスでもチェックを行うのにさらに「フィルター」クラスで二重のチェックを行ったりしているのは作者の(プログラミングではなく株取引の)思想が色濃く出ている。

そして「仕掛け」「手仕舞い」という"振る舞い"と「ストップ」「フィルター」という"条件"を同じクラスから派生させる、つまりis-aの関係で実装するのはやはりトリッキーだと思うのだが、作者の中ではしっかり抽象化できているのだろうか。羨ましい。
私ならやはりhas-aのイメージで実装していくような気がする。

驚いたのはEntryクラスからMyEntryクラスのように、すなわち親クラスから子クラスのメソッドをいきなり呼び出している部分。
親クラスに抽象メソッドを書くのを省略しているだけと言われれば納得してしまいそうだが、Rubyはこんなフレキシブルな書き方もできるのかと驚いた。
すごいなとは思うが、さすがに混乱のもとになりそうだ。
Rubyつらいなー。

カロリーメイトください。

参考サイト

www.matsui.co.jp