証券会社アクセスプラグイン作成ガイド
jiji 1.1.0をリリースしました。本バージョンより、証券会社へのアクセスロジックをプラグインで後から追加できるようになっています。
→オープン・フリーのFX自動取引システム「jiji (ジジ) 」
→Github - unageanu/jiji
アクセスプラグイン自体は、まだ「クリック証券デモトレード」用のものしかありませんが、差し替えの仕組みは実装済みです。ということで、証券会社アクセスプラグインの作り方について解説します。
作成手順の概要
- 必要な機能を提供するクラスを書く。
- jiji_plugin.rb を用意し、プラグインをjijiに登録するコードを書く。
- 作成したファイルを含むgemを作成し、配布する。
1.必要な機能を提供するクラスを書く
証券会社アクセスプラグインが必要とする機能を提供するプラグインクラスを作成します。
- 必要な機能は以下の4つです。
- ↑とは別に「jiji setting」で入力が必要な情報(ユーザー名/パスワード)を返すAPIなども実装する必要があります。
APIの詳細は、以下のモジュールの説明を参照ください。プラグインクラスを作成する場合、このモジュールをincludeして必要なAPIをオーバーライドするのが簡単です。
module JIJI module Plugin # #===証券会社アクセスプラグイン # #証券会社へのアクセスを提供するプラグインのインターフェイスを示すモジュール。 #証券会社アクセスプラグインはこのモジュールが示すメソッドを実装する必要があります。 # module SecuritiesPlugin #プラグイン識別子 FUTURE_NAME = :securities #プラグインの識別子を返します。 def plugin_id end #プラグインの表示名を返します。 #「jiji setting」での証券会社選択時に使用します。 def display_name end #「jiji setting」でユーザーに入力を要求するデータの情報を返します。 #return:: JIJI::Plugin::Securities::Inputの配列 def input_infos end #プラグインを初期化します。プラグインの利用が開始される前に1度だけ呼び出されます。 #引数として、ユーザーが入力したパラメータが渡されます。 #props:: ユーザーが入力したパラメータ(JIJI::Plugin::Securities::Inputのkeyをキーとする設定値の配列) #logger:: ロガー def init_plugin( props, logger ) end #プラグインを破棄します。jijiの停止時に1度だけ呼び出されます。 def destroy_plugin end #利用可能な通貨ペア一覧を取得します。 #return:: JIJI::Plugin::Securities::Pairの配列 def list_pairs end #現在のレートを取得します。 #return:: 通貨ペア名をキーとするJIJI::Plugin::Securities::Rateのハッシュ def list_rates end #成り行きで発注を行います。 #pair:: 通貨ペア名 #sell_or_buy:: 売(:sell)または買い(:buy) #count:: 取引数量 #return:: JIJI::Plugin::Securities::Position def order( pair, sell_or_buy, count ) end #建玉を決済します。 #position_id:: 建玉ID #count:: 取引数量 def commit( position_id, count ) end #===ユーザーに入力を要求するデータの情報 #key:: データのキー #description:: 入力時に表示する説明 #secure:: UIでの入力値の表示を行うかどうか。trueにするとUI上では「*」で表示されます。 #validator:: UIでの入力値のチェックを行うProc。引数として文字列を受け取り、 # エラーがあった場合はエラーメッセージ、問題ない場合はnilを返すこと。 # nilを指定すると、入力値のチェックを行わない。 Input = Struct.new( :key, :description, :secure, :validator ) #===取引可能な通貨ペア #name:: 通貨ペア名 例) :EURJPY #tade_unit:: 取引単位 Pair = Struct.new( :name, :trade_unit ) #===レート #bid:: bidレート #ask:: askレート #sell_swap:: 売りスワップ #buy_swap:: 買いスワップ Rate = Struct.new( :bid, :ask, :sell_swap, :buy_swap ) #===建玉 #position_id:: 建玉の識別子 Position = Struct.new( :position_id ) end end
参考までに、jiji添付の「クリック証券デモトレードアクセスプラグイン」のコードも載せておきます。依存しているクラスなどはGithub - unageanu/jiji を参照ください。
require 'jiji/plugin/securities_plugin' require 'jiji/plugin/embedded/single_click_client' module JIJI module Plugin # クリック証券デモトレードアクセスプラグイン class ClickSecuritiesDemoPlugin include JIJI::Plugin::SecuritiesPlugin #プラグインの識別子を返します。 def plugin_id :click_securities_demo end #プラグインの表示名を返します。 def display_name "CLICK Securities DEMO Trade" end #「jiji setting」でユーザーに入力を要求するデータの情報を返します。 def input_infos [ Input.new( :user, "Please input a user name of CLICK Securities DEMO Trade.", false, nil ), Input.new( :password, "Please input a password of CLICK Securities DEMO Trade.", true, nil )] end #プラグインを初期化します。 def init_plugin( props, logger ) @client = JIJI::Plugin::SingleClickClient.new( props, logger ) end #プラグインを破棄します。 def destroy_plugin @client.close if @client end #利用可能な通貨ペア一覧を取得します。 def list_pairs pairs = @client.request {|fx| fx.list_currency_pairs } return pairs.map {|i| name = convert_currency_pair_code(i[0]) Pair.new( name, i[1].trade_unit ) } end #現在のレートを取得します。 def list_rates @client.request {|fx| fx.list_rates.inject({}) {|r,p| code = convert_currency_pair_code(p[0]) r[code] = Rate.new( p[1].bid, p[1].ask, p[1].sell_swap, p[1].buy_swap ) r } } end #成り行きで発注を行います。 def order( pair, sell_or_buy, count ) result = @client.request{ |fx| fx.order( convert_currency_pair_code_r(pair), sell_or_buy == :buy ? ClickClient::FX::BUY : ClickClient::FX::SELL, count ) } return JIJI::Plugin::SecuritiesPlugin::Position.new( result.open_interest_no ) end #建玉を決済します。 def commit( position_id, count ) @client.request {|fx| fx.settle( position_id, count ) } end # 通貨ペアコードをシンボルに変換する def convert_currency_pair_code(code) case code when ClickClient::FX::USDJPY return :USDJPY when ClickClient::FX::EURJPY return :EURJPY when ClickClient::FX::GBPJPY return :GBPJPY when ClickClient::FX::AUDJPY return :AUDJPY when ClickClient::FX::NZDJPY return :NZDJPY when ClickClient::FX::CADJPY return :CADJPY when ClickClient::FX::CHFJPY return :CHFJPY when ClickClient::FX::ZARJPY return :ZARJPY when ClickClient::FX::EURUSD return :EURUSD when ClickClient::FX::GBPUSD return :GBPUSD when ClickClient::FX::AUDUSD return :AUDUSD when ClickClient::FX::EURCHF return :EURCHF when ClickClient::FX::GBPCHF return :GBPCHF when ClickClient::FX::USDCHF return :USDCHF end end # シンボルを通貨ペアコードに変換する def convert_currency_pair_code_r(code) case code when :USDJPY return ClickClient::FX::USDJPY when :EURJPY return ClickClient::FX::EURJPY when :GBPJPY return ClickClient::FX::GBPJPY when :AUDJPY return ClickClient::FX::AUDJPY when :NZDJPY return ClickClient::FX::NZDJPY when :CADJPY return ClickClient::FX::CADJPY when :CHFJPY return ClickClient::FX::CHFJPY when :ZARJPY return ClickClient::FX::ZARJPY when :EURUSD return ClickClient::FX::EURUSD when :GBPUSD return ClickClient::FX::GBPUSD when :AUDUSD return ClickClient::FX::AUDUSD when :EURCHF return ClickClient::FX::EURCHF when :GBPCHF return ClickClient::FX::GBPCHF when :USDCHF return ClickClient::FX::USDCHF end end end end end
2. jiji_plugin.rb を用意し、プラグインをjijiに登録するコードを書く。
プラグインクラスができたら、jijiにプラグインを認識させるためのRubyスクリプト「jiji_plugin.rb」を書きます。
- jijiは、起動時にすべてのgemに含まれる「lib/jiji_plugin.rb」ファイルを探索し、ロードします。(詳細はプラグインローダーの解説を参照ください。)
- 「jiji_plugin.rb」内にプラグイン登録コードを書いておくことで、プラグインがjijiに認識されるようになります。
詳細は以下のコードを参照ください。
# 必要なモジュール(プラグインクラスなど)を読み込む require 'jiji/plugin/embedded/click_securities_demo_plugin' # 「JIJI::Plugin.register( <機能名>, <プラグインインスタンス>)」でjijiに機能を登録する。 # 以下は、証券会社アクセスプラグインとして、「JIJI::Plugin::ClickSecuritiesDemoPlugin」を登録する例 JIJI::Plugin.register( JIJI::Plugin::SecuritiesPlugin::FUTURE_NAME, JIJI::Plugin::ClickSecuritiesDemoPlugin.new )
3.作成したファイルを含むgemを作成し、配布する。
プラグインクラス、および「jiji_plugin.rb」を含むgemを作成します。
- プラグインクラスは任意の場所に、
- 「jiji_plugin.rb」は「lib」直下に配置する必要があります。
あとは、gemをインストールしてjijiを再起動すれば、プラグインが認識されるはずです。正しく認識されていれば、「jiji setting」で利用可能な証券会社の選択肢が追加されます。プラグインを公開したい場合は、gemを公開すればOK。rubyforgeやgithubでの配布ももちろん可能です。
解説は以上。不具合などありましたら、blogのコメントなりGithubのissuesなりでご報告下さい。