来週から、1週間ほど新潟に帰省します。
FXトレードの予定については、
- 裁量トレード: 基本的にお休み。これまでの反省等を予定、、、と言いつつ、多分しない
- EAによる自動売買: 通常通りトレード予定
ここで問題になるのが、自動売買は複利運用をしていて、日次の頻度でリスク計算をし直している点。
”リスク計算”の作業としては、
- MT4のトレード結果をCSVファイルに落とす
- 1のCSVファイルをAccessに取り込み、日単位で集計した単利成績のトレード明細を作成する
- 2を入力として、オプティマルfによる最適掛け率の再計算と、相関係数によるトレード間の関連性によるリスク調整の実施を行う
- 3の結果をAccessに取り込んで、新しく計算された掛け率と、これまでのトレード成績結果による資産増減を加味して、次回のトレードロットを決定する
- 次回トレードロットに増減が発生したEAについて、トレードロット調整をちまちま実施する(これはVPS上の作業)
帰省中は、Officeが稼働するPCが手配できないため、上記作業の2、3、4ができない見通し。
2と3の掛け率調整については、直近の数値を固定で使用すればいいかなと妥協できるのですが、4のトレードロット計算だけは何とかしなくては。
いろいろ悩んだ結果、4のロット調整作業については、iOSのExcelを駆使して何とか対応する予定です。
iOSのExcelにあって欲しい機能として、
- データの並べ替え機能 -> これはあった
- データをフィルタして、その単位で値を集計する機能 -> これもあった
- あるデータをキーとして、キー毎に値を集計する機能 -> 残念、なさそう
というわけで、”どの戦略が”、”いくらの結果を出したか”というCSVファイルを用意して、iPhoneと格闘しながら、電卓も使ってちまちまトレードロットを計算する方針になりそうです。
こんな、CSVファイルをMT4から取得するスクリプトを作成して、そのスクリプトをVPS上のMT4に仕込みました。
以前作成した、ステートメントCSV作成スクリプトを改造しました。
iPhone上のExcelでは、このような明細をソートして、戦略毎にフィルタリングしてトレード成績を集計する予定です。
もっと凝ったMT4スクリプトを作れればよかったのですが、これが今の精一杯。
コード的には、こんな感じ。
RDBのUpdate機能も強引に関数化して、各明細がどの戦略のトレードかをマジックナンバーをもとに見分けられるようにしました。
//+------------------------------------------------------------------+ //| StatementToCSV.mq4 | //| Copyright 2015, Life with FX | //| http://lifewithfx.jp | //+------------------------------------------------------------------+ #property copyright "Copyright 2015, Life with FX" #property link "http://lifewithfx.jp" #property version "1.40Z" #property strict #property show_inputs extern string CSVOutputFolder = "-- MT4 MQL4/Files folder --"; extern bool OutputRecordDescendingOrder = false; extern bool OutputHeaderRecord = true; extern string ReportPeriod = "-- PeriodFilter: Order close time base --"; extern bool UsePeriodFilter = true; extern int ReportFromDate = 20150801; extern int ReportToDate = 20159999; //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ int OnStart() { int hFile = -1; int historyTotal = OrdersHistoryTotal(); if(historyTotal <= 0) { Print("No History Data. Skip process..."); return(0); } int ticket[]; ArrayResize(ticket, historyTotal); ArrayInitialize(ticket, -1); for(int i=0; i<historyTotal; i++) { if(OrderSelect(i, SELECT_BY_POS, MODE_HISTORY)) { switch(OrderType()) { case OP_BUY: case OP_SELL: ticket[i] = OrderTicket(); break; default: ticket[i] = -1; } } } // output filename StatementCSV_YYYYMMDD_HHMM.csv string fileName = "StatementCSV_" + Year(); if(Month() < 10) { fileName = fileName + "0" + Month(); } else { fileName = fileName + Month(); } if(Day() < 10) { fileName = fileName + "0" + Day() + "_"; } else { fileName = fileName + Day() + "_"; } if(Hour() < 10) { fileName = fileName + "0" + Hour(); } else { fileName = fileName + Hour(); } if(Minute() < 10) { fileName = fileName + "0" + Minute(); } else { fileName = fileName + Minute(); } fileName = fileName + ".csv"; Print("output filename: " + fileName); //get handle hFile = FileOpen(fileName, FILE_BIN|FILE_WRITE, ","); if(hFile < 0) { Print("error abort: output file creation error!!"); return(-1); } // CSV Record Header string header = "ID,TradeProfit" + "\r\n"; if (OutputHeaderRecord) { FileWriteString(hFile, header, StringLen(header)); } const string ITEM_SEPARATOR = ","; int startIdx; int idxStep; int ordersLastIdx = historyTotal - 1; double pipScale; double pipScaleDigits; double takeprice; double takepips; if (!OutputRecordDescendingOrder) { startIdx = 0; idxStep = 1; } else { startIdx = ordersLastIdx; idxStep = -1; } for (int i = startIdx; !(i < 0 || ordersLastIdx < i) ; i += idxStep) { if(ticket[i] != -1) { if(OrderSelect(ticket[i], SELECT_BY_TICKET, MODE_HISTORY)) { // PeriodRangeFilter string closeDateStr = TimeToStr(OrderCloseTime(), TIME_DATE); int closeDateInt = StrToInteger(StringSubstr(closeDateStr, 0, 4) + StringSubstr(closeDateStr, 5, 2) + StringSubstr(closeDateStr, 8, 2)); if (!UsePeriodFilter) { // OK } else if (ReportFromDate <= closeDateInt && closeDateInt <= ReportToDate) { // OK } else { continue; } string output = getSID(OrderMagicNumber(), StringSubstr(OrderComment(), 0, 2)) + "_" + StringSubstr(OrderSymbol(), 0, 6) + ITEM_SEPARATOR; output = output + (NormalizeDouble(OrderSwap(), 2) + NormalizeDouble(OrderCommission(), 2) + OrderProfit()); output = output + "\n"; FileSeek(hFile, 0, SEEK_END); FileWriteString(hFile, output, StringLen(output)); } } } if(0 < hFile) { FileClose(hFile); } Print ("works fine: finished!!"); return(0); } string getSID(int magic, string comment) { if (magic == 62345678) { return "ince";} else if (magic == 39404940) { return "WZ";} else if (magic == 8301908) { return "sp";} else if (magic == 20142301) { return "Be";} else if (magic == 2328104) { return "BTGYA";} else if (magic == 4668) { return "REV";} else if (magic == 10101) { return "FDS1";} else if (magic == 4698523) { return "WALL";} else if (magic == 2328105) { return "BTJU";} else if (magic == 7730773) { return "WB3as1";} else if (magic == 728811) { return "IET";} else if (magic == 728822) { return "IET";} else if (magic == 728833) { return "IET";} else if (magic == 527411) { return "IMTL1";} else if (magic == 527422) { return "IMTL1";} else if (magic == 110101) { return "FDS1";} else if (magic == 310101) { return "FDS1";} else if (magic == 9930993) { return "WBV3";} else if (magic == 12780) { return "Kel2";} else if (magic == 8830883) { return "WBV3BB";} else if (magic == 20142302) { return "Be";} else if (magic == 987) { return "EW";} else if (magic == 213002) { return "GEKI";} else if (magic == 213001) { return "GEKI";} else if (magic == 8881908) { return "sp";} else if (magic == 2014061051) { return "Ri";} else if (magic == 2014061052) { return "Ri";} else if (magic == 2014061053) { return "Ri";} else if (magic == 2014061054) { return "Ri";} else if (magic == 2014061011) { return "Ri";} else if (magic == 2014061012) { return "Ri";} else if (magic == 2014061013) { return "Ri";} else if (magic == 2014061014) { return "Ri";} else if (magic == 527433) { return "IMTL2";} else if (magic == 78942) { return "Ven";} else if (magic == 514229) { return "Mone";} else if (magic == 213003) { return "GEKI";} else if (magic == 1987) { return "MEW";} else if (magic == 19202920) { return "WZ";} else if (magic == 11200) { return "Ra";} else if (magic == 753159) { return "Rac1";} else if (magic == 2014061095) { return "Ri";} else if (magic == 2014061093) { return "Ri";} else if (magic == 2014061094) { return "Ri";} else if (magic == 2014061096) { return "Ri";} else if (magic == 7703304) { return "duet";} else if (magic == 4565450) { return "WLAsia";} else if (magic == 4565451) { return "WLAsia";} else if (magic == 4565452) { return "WLAsia";} else if (magic == 4565453) { return "WLAsia";} else if (magic == 4565454) { return "WLAsia";} else if (magic == 4565455) { return "WLAsia";} else if (magic == 736211) { return "IW";} else if (magic == 7703303) { return "duet";} else if (magic == 5551101) { return "Union";} else if (magic == 7021013) { return "Legato";} else if (magic == 5551102) { return "Union";} else if (magic == 5551103) { return "Union";} else if (magic == 728711) { return "IETAX";} else if (magic == 728722) { return "IETAX";} else if (magic == 728733) { return "IETAX";} else if (magic == 4051220) { return "BC7";} else if (magic == 728511) { return "IETCM";} else if (magic == 728522) { return "IETCM";} else if (magic == 728533) { return "IETCM";} else if (magic == 286411) { return "STCM";} else if (magic == 813711) { return "IEGL";} else if (magic == 813722) { return "IEGL";} else if (magic == 813733) { return "IEGL";} else if (magic == 2328100) { return "BTR";} else if (magic == 20150601) { return "VBS";} else if (magic == 20150602) { return "VBS";} else if (magic == 20150603) { return "VBS";} else if (magic == 10006) { return "SILV";} else if (magic == 10007) { return "SILV";} else if (magic == 10008) { return "SILV";} else { return comment; } }