#Tickとは?
MQL4ではOnTick()という関数がTick情報が更新されるたびコールバックされるみたい。
Tickとは金融商品の値動き変化の最小単位、これを収集することでどんな足でも作れる。
色々探してみたが、TickをダウンロードできるサイトがなかったためMT4でTick情報を
サーバにひたすらアップロードするプログラムを作成した。
#システム構成
基本的にMT4からWebサーバにTickの更新があるたびにGETメソットでリクエストを行う。
MT4は常時動かさないといけないので、お名前.comのWindows VPSを導入。合わせてWebサーバ用のVPSも導入。
(合計3000円/月、しかしWindows VPSは全然性能出ないな)
#MT4側
BiD,ASK,時間情報をWebRequest関数を用いてひたすらGETリクエスト。
しかしMQL4は書きにくい(C++がベース、ポインタとか記憶の外)。
時間周りがMT4のシステム上GMT+2になっている(日本時間ではない)。
今までGMT+9(日本時間)しか考慮したことなかったので、冬時間→夏時間とかどう処理すればいいんだろう。
(サーバ時間 - ローカル時間)でGMTが演算できるので、それもGETパラメータに加えることにした。
その他時間処理がめんどくさいので、クラス化。
TimeObject *time_object = new TimeObject(last_tick.time); // 時間情報を保持する自作関数
SymbolInfoTick(Symbol(),last_tick)
string currencyPair = _Symbol;
string bid = (string)last_tick.bid;
string ask = (string)last_tick.ask;
string last = (string)last_tick.last;
string volume = (string)last_tick.volume;
string flags = (string)last_tick.flags;
string mt4DateTime = (string)time_object.getMT4DateTimeString();
string mt4UnixTime = (string)time_object.getMT4UnixTime();
string mt4Offset = (string)time_object.getMT4Offset();
string localDateTime = (string)time_object.getLocalDateTimeString();
string localUnixTime = (string)time_object.getLocalUnixtTime();
string localOffset = (string)time_object.getLocalOffset();
string tickCount = (string)GetTickCount();
###WebRequest関数について
WebRequestで引っかかったことは二つ。
- ツール > オプション > エキスパートアドバーザの許可するURLにWebサーバのアドレスを追加
- 80 or 443のみ利用できる。
1は許そう。2は駄目だ。
サーバ側を機能(収集、オーダ)でポートを分けてSimpleServerで済まそうと思っていたが、
全て80で行う必要がある。そのため、サーバサイドをそれなりにしっかりしないといけなくなった。
###GetTickCountについて
これはローカルでのMT4起動時からのカウンタ値らしい。
ミリセックオーダでも連続してTick更新があるときがあり、
順序把握のために高精度のカウンタとしてGetTickCountが利用できる。
しかし50日位でオーバーフローするらしい。
まあ1週間に1度は再起動するか。
#サーバ側
全て80で行う必要があり、しかりとしたものを作るためPlayFramework 2.6(Scala)を導入
どうやらactivatorのサポートが終了したらしいので、seedからインストール
(brewが死んでいたのでアップデート、sbtも1系に、sbt1系に対応できないためIntelliJも最新に)
sbt new playframework/play-scala-seed.g8
##uploadフォルダ
MT4からの情報収集するフォルダとして、uploadフォルダを作成。
保存するTick情報は下記のcase classとなっている。
case class MqlTick(mt4_id : String,
currencyPair : String,
bid : String,
ask : String,
last : String,
volume : String,
flags : String,
mt4DateTime : String,
mt4UnixTime : String,
mt4Offset : String,
localDateTime : String,
localUnixTime : String,
localOffset : String,
tickCount : String,
createdDateTime : String,
createdUnixTime : String)
val csvHeader = classOf[MqlTick].getDeclaredFields.map(_.getName).mkString(",")
特に、localDateTimeはMT4側のローカル時間となるため、
アップロードにかかった時間やローカル時間が間違っている時の補正のためにサーバ側のローカル時間も保存する。
しかしscalaは書きやすいな。
#今後について
とりあえずTickデータが集まってきた。
今後はランダムウォークでの機械学習を試してみよう。
QRNNでカオス時系列データ予測を試してみたい・