OANDA fx Trade API を使って、リアルタイムな為替レートを取得してみる
今さらですが、OANDA Japan から FXトレードAPI が提供されているのを発見。
- レート情報の取得から、取引、建玉情報の取得などのFX 取引に必要なAPI一式が提供されています。
- 初期費用、月額利用料金は無料。ただし、口座残高が25万円以上必要です。
- 本物の口座を使うLive環境のほか、デモ口座のアカウントで使える Practice、アカウントなしで試せるSandbox環境も提供。
- REST APIの他、Java/FIX版のAPIも有り。
機能もかなり充実してます。本格的なトレードアプリも作れるんじゃないかな。
- REST APIだけど、ストリーミングでのレートデータ配信に対応
- Transfer-Encoding: chunked で配信する仕組みで、ポーリングなしでリアルタイムなレートデータを取得できます。
- OAuth 2.0での認証に対応
- すべてのGET APIが ETag に対応しているなど、細かいところの完成度も高い。
ということで、Rubyを使ってREST APIにアクセスし、リアルタイムな為替レートを取得してみるサンプルを書いてみました。(といっても、公開されているアクセスライブラリのサンプルを動かしてみただけですが・・・)
アクセスライブラリのインストール
RubyだとREST APIのアクセスライブラリが公開されているので、これを利用します。 gemでインストール。
$ gem install oanda_api
デモ口座のアカウントを使って、現在価格を得るサンプルコードです。 「<アクセストークン>」のところには、OANDAのサイトから取得したアクセストークンを指定します。取得方法はこちら。
require 'oanda_api' client = OandaAPI::Client::TokenClient.new(:practice, <アクセストークン>) prices = client.prices(instruments: ['EUR_USD','USD_JPY']).get prices.each do |p| puts "#{p.instrument} #{p.ask} #{p.bid} #{p.time}" end
実行結果です。
$ retrieve_price.rb EUR_USD 1.1201 1.11994 2015-05-11 00:22:16 UTC USD_JPY 119.744 119.728 2015-05-11 00:21:43 UTC
せっかくなので、ストリーミングAPIでリアルタイムなレート情報の取得もやってみます。
require 'oanda_api' access_token = <アクセストークン> # アカウントのIDが必要なので取得しておく。 client = OandaAPI::Client::TokenClient.new(:practice, access_token ) account = client.accounts.get.first # ストリーミングAPI用のクライアントを別途作成し、実行 streaming_client = OandaAPI::Streaming::Client.new(:practice, access_token ) prices = streaming_client.prices(account_id: account.account_id, instruments: ["USD_JPY"]) prices.stream do |p| # ※無限ループするので Ctrl+Cで停止すること。 puts "#{p.instrument} #{p.ask} #{p.bid} #{p.time}" end
実行してみます。放置するとずっと更新を続けるので、Ctrl+Cで停止すること。
$ ruby retrieve_price_uses_streaming_api.rb USD_JPY 119.747 119.743 2015-05-11 00:37:52 UTC USD_JPY 119.748 119.744 2015-05-11 00:38:12 UTC USD_JPY 119.749 119.745 2015-05-11 00:38:12 UTC USD_JPY 119.75 119.746 2015-05-11 00:38:12 UTC ...
Jiji2のバックエンドもこれに移行かな
Jiji2絶賛開発中ですが、
バックエンドは OANDA fx trade API に変更かな、と考えています。 旧バージョンと同じくスクレイピングを使う方向で考えていましたが、次のようなリスクはどうしても残るので。
- (アクセス頻度はもちろん抑えるにしても)やはり証券会社のサービスに多少は負荷がかかるので、利用禁止になる可能性がある。
- サイトの仕様変更で突然動作しなくなるリスクがある。
アプリ開発者としては、特定の証券会社にロックオンしてしまうのは避けたいところではあるので、このようなAPIを提供してくれる証券会社がもっと増えてくるといいな。(クリック証券、何でやめたんや・・・。)
追記(2015-12-01)
OANDA FX trade APIを利用した、無料のFXシステムトレードフレームワーク「Jiji」をリリースしました!
使ってみて、ご意見など頂けるとうれしいです。
JavaScript Dateのタイムゾーン指定できない問題とその対策
JavaScriptのDate型では、タイムゾーンを外部から指定できない
- JavaScriptのDate型は、タイムゾーンの情報を持ってはいますが、APIで外から変更することはできません。
- getTimezoneOffset() はあるけど、setTimezoneOffset(timezone) はありません。
- getTimezoneOffset() の値は実行環境のタイムゾーンになります。
- getHours()やgetMinutes()はローカルのタイムゾーンにおける時刻表現を返すので、実行環境によって結果が異なり、問題になる場合があります。
const date = new Date( '2015-05-10T12:00:00.000Z' ); expect( date.getHours() ).toEqual(21); // ローカルタイムゾーンがJSTの場合は動作するが、他の環境では違う結果になる。
対策
以下のようにしてみました。
- Dateの代わりに、 date-with-offset を使う。
- DateWithOffsetをnewするときに、static変数からタイムゾーンを読み込んで使う。
具体的にはこんなユーティリティを作成。
import DateWithOffset from "date-with-offset" const defaultTimezoneOffset = new Date().getTimezoneOffset()*-1; export default class Dates { static date(iso8601String) { return new DateWithOffset( iso8601String, this.getTimezoneOffset() ); } static getTimezoneOffset() { return this.timezoneOffset != null ? this.timezoneOffset : defaultTimezoneOffset; } static setTimezoneOffset(timezoneOffset) { this.timezoneOffset = timezoneOffset; } static resetTimezoneOffset() { this.timezoneOffset = null; } }
ローカルタイムゾーンに依存するテストが動作するところは、以下のようにすることで、どの環境でも同じ結果が返るようになります。
beforeEach( ()=> Dates.setTimezoneOffset(540) ); afterEach( ()=> Dates.resetTimezoneOffset() ); it("ローカルタイムゾーンに依存するテスト", () => { // このテスト内では、ローカルタイムゾーンがJSTになる。 expect( Dates.date("2015-05-10T12:00:00.000Z").getHours() ).toEqual(21); });
jiji2の画面スケッチを3つほど。
追記(2015-12-01):
FXシステムトレードフレームワーク「Jiji」、リリースしました!
使ってみて、ご意見など頂けるとうれしいです。
jiji2の画面スケッチを少し作ったので、公開します。
- ホーム画面、ナビを開いたところ、チャートの3つ。
- 表示するデータや機能をざっくりと並べてみました。
- アイコンなど、細かいデザインの詰めはまだです。
フィードバックとかいただけるとうれしいです。
ホーム
アプリ起動直後に表示する画面。
- 損益状況、エージェントからの通知を、ファーストビューでさっと確認。
- ミニチャートで、現在のレートと直近の値動きを確認できる。
- 「取引」ボタンから、取引を行うことも可能。
- ミニチャートの下には、建玉一覧、バックテスト一覧のサマリを表示。
- 各カードをタップすると、詳細が見える
- 例) ミニチャートをタップすると、チャート画面に移動して詳しいチャートが確認できるイメージ
ナビ
ナビを開いたところ。
- バックテスト一覧やエージェントエディタなどの機能は、ナビからアクセスする。
チャート
ローソク足チャート。
- レートの動きと、エージェントが出力したグラフ(移動平均, RSI ..etc..)を表示。
- 移動平均はチャートと重ねて表示。RSIはレートの下の部分に別枠で表示。
- 通貨ペア、集計期間(10分足,1時間足 ,,et,,)は、上部のメニューから変更できる。
- レートの下部には、売り買いした建玉の情報も表示。
- 値動きに対して、売り買いのタイミングが妥当かどうか確認できる。
- 緑が買、赤が売。●のタイミンクでエントリーして、〇で決済したことを示す。
- 値動き/現在価格をみながら、右下の「+」ボタンから、売り買いもできる。
- 下のスライダーで、表示する期間を変更できる。
- チャート部分を左右にドラッグしてもOK
作っていく過程で変わるところも多々あるとは思いますが、とりあえずはこれをゴールに実装進めます。 他の画面の絵も作っておきたいところだけど、現状の3枚で「ほんまこれ実装できんの」感が半端ない・・・。絵に描いた餅にならないよう、実装も並行して進める方がいいかなと思ってます。まずはチャートかな。
Cordova + React.js + Material UI で、 Material Design な Android アプリのプロトタイプを作ってみた
Cordova のお試しということで、 Cordova + React.js + Material UI で Material Design な Android アプリのサンプルを作ってみました。
- HTML+CSS+JavaScript でネイティブアプリが作れるCordova ですが、やはり遅いという話をよく耳にするので、実際どうなのか確認してみるのが目的。
- 使えそうなら、フロントはJavaScriptで書いて、せめてモデル層だけでも共通化したい。
- UIは Material Designにしたいので、 Material UI フレームワークを使ってみました。
- Material UI は、Material Design を実装したフレームワークです。
- Navigation Drawer や Action Bar といったUIパーツを、React コンポーネント + LESS で提供しています。
- React Nativeも気になるところですが、Android版はまだらしいのでとりあえずスルー。Macも持ってないし。
プロトタイプの機能
- メイン画面には、Action Bar と Card を表示。
- Cardは以下の3種類を用意。
- テキストを流し込んだもの
- 画像を張り付けたもの
- 簡単なグラフを描画したキャンバスを張り付けたもの
- 少しスクロールするよう、複数個貼り付けています。
- Cardは以下の3種類を用意。
- Action Bar の左上のボタンをタップすると、Navigation Drawerが表示される。
- メニュー選択時の処理は実装していないので、表示だけです。
- パネルをタップすると、パネルが回転するアニメーションが走る
- CSS transitionのパフォーマンスも見てみたいので。
コードと実行手順
コードは こちら で公開しています。 Node.js とAndroidのビルドツール一式(JDK, Android SDK, Ant) をインストールして、以下のコマンドを実行すれば動かせるはずです。
$ git clone https://github.com/unageanu/sandbox.git $ cd sandbox/cordova/sample-app $ npm install $ npm run-script init $ npm run-script build $ npm run-script run-browser # ブラウザで実行 $ npm run-script run-android # Android(実機)で実行
所感
ややもっさり感はあるものの、シンプルなアプリであれば十分使えそう。
- 画面のスクロールや、LeftNavi表示時のアニメーションは少しもたつく。
- transition を使ったアニメーションは速い。
- レンダリングも、特に汚いといったことはなさそう。
- 起動は5~6秒といったところ。スプラッシュスクリーンを出しておけば大丈夫なレベルかな。
確認は手持ちの端末(Xperia Z)で行いました。2年前の端末なので、これで使えれば最近の端末でも大丈夫でしょう。さすがにゲームとかは厳しそうですが、とりあえず、jiji2で必要な機能なら十分実用に耐えるのではないかと。
jiji2の画面一覧(案)をまとめてみた
追記(2015-12-01):
FXシステムトレードフレームワーク「Jiji」、リリースしました!
使ってみて、ご意見など頂けるとうれしいです。
検討段階ですが、jiji2の画面と機能概要をざっくりとまとめてみました。
- 基本的な機能は、PCとスマホで同じに。
- メイン画面は、「ホーム」「バックテスト」「エージェント」「設定」の4つ
- これらをナビで切り替えながら使う形。
旧バージョンとの違いは次の2つ。
ホーム画面を新設。
- 最初に表示されるビュー。
- ダッシュボート的な感じで、資産状況などが最初の一画面でざっくり把握できるようにする。
- ダッシュボートのパネルをタップすると、詳細を確認できる。
プライスボード && 価格一覧からの裁量取引もできるようにする
エージェントを作る → バックテストで検証 → 運用 あたりの画面フローは旧バージョンと同じでいいかな。
ユースケース
1.完全自動でのシステムトレード
エージェントエディタからエージェントを作る。
- PCからの作成がメイン(画面が広くてキーボードが使えるので)
- ひな形のエージェントがあり、コピペして編集する形で簡単にロジックを組める。
- 移動平均線など主要な指標も組み込みのライブラリとし提供されていて、簡単に組み込める。
エージェントができたら、バックテストで検証。
- 期間を指定して、本番と同様のデータ(tick)で動作を確認できる。
- テストが完了したら、収益や勝率、プロフィトァクターなどがレポートされ、成績を評価できる。
- 取引や約定のタイミングがチャート上に表示され、タイミングが妥当だったか確認できる。
- 移動平均線など、エージェントが使用した指標をチャート上に出力して確認できる。
満足な結果が出たら、実際に運用してみる。
- デモ取引での利用に対応しているので、まずはデモ取引口座で気軽にお試しできる。
- 約定や決済は、随時スマホにPush通知される。
- 通知をタップするとjijiが起動し、ホーム画面から現在の損益やチャート、ポジジョン一覧を確認できる。
2.指標のPush通知で裁量トレード
- エージェントプログラムがレートを監視。
- 移動平均線のゴールデンクロスなど、取引のチャンスが来たら、通知がスマホに届く。
- 通知をタップすると、アプリが起動。
- ホーム画面で、チャートと現在価格をチェック。
- 価格を確認し、取引するか判断。OKならプライスボードから取引を実行する。
- 取引が成立したら、ポジション一覧に反映される。
- 以降の損益推移はここから確認できる。
- 決済も可能。
3.ロスカットをシステム化して徹底
- チャートやレートを見ながら、裁量で取引する。
- エージェントのポジションを監視。プログラムされたルールに従って、 一定の損失となった時点で自動で決済される。
- 決済が行われると、結果がスマホに通知される。
- 通知をタップすると、ポジションの詳細な情報(損益、通貨ペア、約定日時、決済日時 ..etc..)を確認できる。
4.承認制システムトレード
- エージェント追加時に、「承認制にする」をチェックすると、承認制モードになる。
- 実運用のほか、バックテストでも同様に選べて試せる。
- 承認制エージェントが取引を行うと、スマホにPush通知が届く。
- 通知を確認して、OKなら「承認」を実行。
- 承認を受けて、エージェントが取引を実行する。
5. トレンドにあわせて、複数のシステムを用意して切り替え
- 上昇トレンド・ボックスなどのトレンドごとに、エージェントの成績を確認しておく。
- バックテストを利用して把握しておく。成績はレポートで残しておける。
- 取引するエージェントのほかに、トレンドの変化をチェックするエージェントも作る。
- 取引は行わず、好みの指標を監視してトレンドの変化を追う。
- 変化があったら、通知のみ行う。
- 取引用エージェントとトレンドチェックエージェントの両方を実行。
- トレンドチェックエージェントからの通知をチェックしてエージェントを切り替えて運用する。
- 運用するエージェントの切り替えも、スマホからリアルタイムにできる。
設定値管理ライブラリ Figaroを使う
Figaro は Rubyアプリ用のシンプルな設定値管理ライブラリ です。
- 設定ファイル(YAML)の値を読み込んで、アプリから参照できるようにします。
- 設定ファイルは1つ。その中に、環境(development,production,test)ごとの設定も書く形。
- アクセス時のインターフェイスに ENV を使うのが特徴。
同様の機能を提供するライブラリに、 Dotenv もあります。違いはざっくり以下の3つ。
違い | Figaro | Dotenv |
---|---|---|
設定ファイルの形式 | YAML | 独自のKey-Value形式 |
環境ごとの設定の切り分け | 1つのYAMLの中に書く形 | ファイルを別ける |
Rails | Railsでの利用にフォーカス | 非Rails環境もサポート |
設定ファイルはYAMLのほうがいいかな・・・、と思ってFigaroにしました。参照使えるしね。ただし、Rails向けに作られているところがあるので、非Rails環境で使うには一工夫必要です。
使い方
インストール:
$ gem install figaro
設定ファイル( ./config/application.yml )を用意ます。
# デフォルトの設定 KEY1: 'key1' KEY2: 'key2-default' # ERBで処理されるので、rubyコードも利用可 ERB : <%= 'abc' * 3 %> # 特定環境での設定 test: KEY2: 'key2-test' development: KEY2: 'key2-development'
- ルートに、キーと値を書きます。
- アクセス時のインターフェイスはENVなので、階層を作ったりはできません。
- test や development のようなエントリーを用意して、特定環境下でのみ有効な設定を記載できます。
- 値の優先順位は、以下の通りです。
- 1.環境変数の値
- 2.特定環境下向けの設定
- 3.デフォルトの設定
- 値の優先順位は、以下の通りです。
- ERBで処理されるので、rubyコードも書けます。
設定ファイルを使うサンプルです。
require 'figaro' class Application < Figaro::Application private # 設定ファイルのパス。 ./config/application.yml から読み込む def default_path File.join( File.dirname(__FILE__), 'config', 'application.yml') end # 環境(development,test..)の取得先。環境変数RACK_ENVを使う def default_environment ENV['RACK_ENV'] end end Figaro.adapter = Application Figaro.load puts ENV['KEY1'] puts ENV['KEY2'] puts ENV['ERB_VALUE']
- Figaro::Application を継承した Application を用意して、設定ファイルのパスと環境の取得先を指定します。
- あとは、 Figaro.load すれば ENV で値を参照できるようになります。
実行してみます。 まずは素で実行。デフォルトの設定が使われます。
$ ruby test.rb key1 key2-default abcabcabc
RACK_ENVを指定すると、特定環境用の設定がアクティブになります。
$ RACK_ENV=test ruby test.rb key1 key2-test abcabcabc $ RACK_ENV=development ruby test.rb key1 key2-development abcabcabc
さらに、環境変数で値を上書きすることも可能です。
$ KEY1=foo KEY2=var RACK_ENV=test ruby test.rb WARNING: Skipping key "KEY1". Already set in ENV. WARNING: Skipping key "KEY2". Already set in ENV. foo var abcabcabc
警告出ますけど。
Code Climate + Circle CI でRubyプロジェクトのコードカバレッジを計測する手順
Code Climate + Circle CI でRubyプロジェクトのコードカバレッジを計測する手順です。 試したのはCircle CIですが、テストが実行できる環境であればTravis CIやJenkinsでも同じ仕組みでできるはず。
概要
- テストに SimpleCov を仕込み、コードカバレッジを計測
SimpleCov のレポーターに codeclimate-test-reporter を追加して、結果を Code Climate に送信
→ Code Climate でカバレッジが集計されるようになります。あとは、Circle CIなりTravis CIなりでテストを実行すればOK
簡単ですね。
1.テストに SimpleCov を仕込んでカバレッジを計測する
SimpleCov をbundlerでインストールします。
Gemfileに以下を追加して、
gem 'simplecov', :require => false, :group => :test
インストール。
$ bundle install
テストの先頭に、SimpleCovの設定を行うコードを追加します。
require 'simplecov' # カバレッジレポートの出力先を指定 # Circle CIで実行する場合は、ビルド成果物置き場に、 # ローカルで実行する場合は、 ./build/coverage に作成します。 dir = File.join(ENV['CIRCLE_ARTIFACTS'] || 'build', 'coverage') SimpleCov.coverage_dir(dir) SimpleCov.start do # /vendor/,/spec/ を集計対象から除外 add_filter '/vendor/' add_filter '/spec/' end
テストを実行すれば、 ./build/coverage/index.html にカバレッジレポートが作成されるはず。
2. SimpleCov に codeclimate-test-reporter を追加する
Gemfileに一行追加して、bundler でインストール
gem 'codeclimate-test-reporter', :require => false, :group => :test
$ bundle install
SimpleCov の設定部分を以下のように変更。レポーターを追加します。
require 'simplecov' require 'codeclimate-test-reporter' # ★追加 dir = File.join(ENV['CIRCLE_ARTIFACTS'] || 'build', 'coverage') SimpleCov.coverage_dir(dir) SimpleCov.start do add_filter '/vendor/' add_filter '/spec/' # ★追加 formatter SimpleCov::Formatter::MultiFormatter[ SimpleCov::Formatter::HTMLFormatter, CodeClimate::TestReporter::Formatter ] end
3. Circle CIに 環境変数を追加
最後に、環境変数 CODECLIMATE_REPO_TOKEN を設定します。 これをしないと、レポーターを追加しても 結果の送信はされません。
まず、CODECLIMATE_REPO_TOKEN の値を Code Climate の Settings ページから取得します。(プロジェクトごとに異なります。)
Circle CIのページの右上にある、Project Settingsをクリック。
Enviroment variables に移動し、
CODECLIMATE_REPO_TOKEN を設定します。
あとは、Circle CIでテストを実行すると、Code Climate のページでコードカバレッジが見られるようになるはず。
参考: バッジを貼る
Code Climate の Settings ページに各種形式のURLがあるので、コピペして貼り付ければOK