2014/8/23更新
特定のブローカーで、通貨レートの桁数が取得できない場合に対応。
正常に取得できれば、ブローカーからの情報を利用するが、取得エラーの場合は、標準的な5桁レート対応のブローカーに準ずる情報で稼働するように改良。
2014/7/11更新
Lot数と、損益pipsの出力結果で、ときどき小数点以下の数値がおかしくなる問題に対処。
2014/6/8更新
主に自分の使用用途に合わせ、CSVファイルにヘッダーを出力しないようにするオプションと、期間選択機能を無効化するオプションを追加しました。
version1.2として、ソースコードを公開します。また、以前のバージョンのソースコードも残しています。
ご自由にご利用下さい。
MT4の出力するトレード記録がHTML形式オンリーであり、直近のEA性能の計算や損益集計する際にデータ加工が面倒したので、MT4からトレード結果をCSV出力するツールを作成しました。
前々からこんなツールが欲しくて、ネットをかけずり回りましたが、有料であったり、古くて動かなかったり、個人情報の登録が必要だったりでイマイチでしたので、自作しました。
:::このツールは、MT4のScriptプログラムとして動作し、下記イメージのようなCSVファイルを出力します。(解り易いように、CSVファイルをExcelで開いています)
それでは、例によってmq4のソースコードです。
※ソースのベースはこちらのサイト様のものを参考にしております。(http://eacreater.blog48.fc2.com)
MT4 Build600ではコンパイル不能で、挙動もちょっと、、、でしたので、構造的に再構成しています。
更新情報
- 2014/8/23 – version1.40][ 一部ブローカーで、通貨レートの桁数情報が取得できない場合に、エラーではなく代替情報にて稼働するよう調整
- 2014/7/11 – version1.30 ][ Lot数と、トレードpipsの小数点以下の数値がおかしくなる問題に対処
- 2014/6/8 – version1.20 ][ ヘッダー付与有無の選択オプションと、期間フィルター使用有無の選択オプションを追加
- 2014/4/18 – version1.10 ][ 項目追加(トレードのpipsを追加しました)
//+------------------------------------------------------------------+ //| StatementToCSV.mq4 | //| Copyright 2014, Life with FX | //| http://lifewithfx.jp | //+------------------------------------------------------------------+ #property copyright "Copyright 2014, Life with FX" #property link "http://lifewithfx.jp" #property version "1.40" #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 = false; extern int ReportFromDate = 20140331; 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 = "Ticket,OrderType,OrderSymbol,OrderLots,OrderOpenTime,OrderOpenPrice,OrderCloseTime,OrderClosePrice,OrderProfitInPips,OrderCommission,OrderSwap,OrderProfit,TradeProfit,OrderMagicNumber,OrderComment,OrderCommentShort" + "\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; } // scale setting if (MarketInfo(OrderSymbol(), MODE_DIGITS) != 0) { pipScale = MarketInfo(OrderSymbol(), MODE_POINT) * 10; pipScaleDigits = MarketInfo(OrderSymbol(), MODE_DIGITS); } else { pipScale = getPipScale(OrderSymbol()); pipScaleDigits =getPipScaleDigits(OrderSymbol()); } string output = ticket[i] + ITEM_SEPARATOR; switch(OrderType()) { case OP_BUY: output = output + "BUY" + ITEM_SEPARATOR; break; case OP_SELL: output = output + "SELL" + ITEM_SEPARATOR; break; default: output = output + "" + ITEM_SEPARATOR; } output = output + OrderSymbol() + ITEM_SEPARATOR; output = output + DoubleToStr(OrderLots(),2) + ITEM_SEPARATOR; output = output + TimeToStr(OrderOpenTime()) + ITEM_SEPARATOR; output = output + NormalizeDouble(OrderOpenPrice(), pipScaleDigits) + ITEM_SEPARATOR; output = output + TimeToStr(OrderCloseTime()) + ITEM_SEPARATOR; output = output + NormalizeDouble(OrderClosePrice(), pipScaleDigits) + ITEM_SEPARATOR; switch(OrderType()) { case OP_BUY: takeprice = (OrderClosePrice() / pipScale) - (OrderOpenPrice() / pipScale); takepips = NormalizeDouble(takeprice, pipScaleDigits); output = output + takepips + ITEM_SEPARATOR; break; case OP_SELL: takeprice = (OrderOpenPrice() / pipScale) - (OrderClosePrice() / pipScale); takepips = NormalizeDouble(takeprice, pipScaleDigits); output = output + takepips + ITEM_SEPARATOR; break; } output = output + NormalizeDouble(OrderCommission(), 2) + ITEM_SEPARATOR; output = output + NormalizeDouble(OrderSwap(), 2) + ITEM_SEPARATOR; output = output + OrderProfit() + ITEM_SEPARATOR; output = output + (NormalizeDouble(OrderSwap(), 2) + NormalizeDouble(OrderCommission(), 2) + OrderProfit()) + ITEM_SEPARATOR; output = output + OrderMagicNumber() + ITEM_SEPARATOR; output = output + OrderComment() + ITEM_SEPARATOR; output = output + StringSubstr(OrderComment(), 0, 2); output = output + "\n"; FileSeek(hFile, 0, SEEK_END); FileWriteString(hFile, output, StringLen(output)); } } } if(0 < hFile) { FileClose(hFile); } Print ("works fine: finished!!"); return(0); } double getPipScale(string symbol) { if (symbol == "EURUSD") { return 0.0001;} else if (symbol == "AUDCAD") { return 0.0001;} else if (symbol == "AUDCHF") { return 0.0001;} else if (symbol == "AUDJPY") { return 0.01;} else if (symbol == "AUDNZD") { return 0.0001;} else if (symbol == "AUDSGD") { return 0.0001;} else if (symbol == "AUDUSD") { return 0.0001;} else if (symbol == "CADCHF") { return 0.0001;} else if (symbol == "CADJPY") { return 0.01;} else if (symbol == "CHFJPY") { return 0.01;} else if (symbol == "EURAUD") { return 0.0001;} else if (symbol == "EURCAD") { return 0.0001;} else if (symbol == "EURCHF") { return 0.0001;} else if (symbol == "EURGBP") { return 0.0001;} else if (symbol == "EURJPY") { return 0.01;} else if (symbol == "EURNZD") { return 0.0001;} else if (symbol == "GBPAUD") { return 0.0001;} else if (symbol == "GBPCAD") { return 0.0001;} else if (symbol == "GBPCHF") { return 0.0001;} else if (symbol == "GBPJPY") { return 0.01;} else if (symbol == "GBPNZD") { return 0.0001;} else if (symbol == "GBPUSD") { return 0.0001;} else if (symbol == "NZDJPY") { return 0.01;} else if (symbol == "NZDUSD") { return 0.0001;} else if (symbol == "USDCAD") { return 0.0001;} else if (symbol == "USDCHF") { return 0.0001;} else if (symbol == "USDHKD") { return 0.0001;} else if (symbol == "USDJPY") { return 0.01;} else if (symbol == "USDMXN") { return 0.0001;} else if (symbol == "USDPLN") { return 0.0001;} else if (symbol == "USDSEK") { return 0.0001;} else if (symbol == "USDSGD") { return 0.0001;} else if (symbol == "USDZAR") { return 0.0001;} else if (symbol == "XAGEUR") { return 0.01;} else if (symbol == "XAGUSD") { return 0.01;} else if (symbol == "XAUEUR") { return 0.1;} else if (symbol == "XAUUSD") { return 0.1;} else if (symbol == "ZARJPY") { return 0.01;} else { return 0.0001; } } double getPipScaleDigits(string symbol) { if (symbol == "EURUSD") { return 5;} else if (symbol == "AUDCAD") { return 5;} else if (symbol == "AUDCHF") { return 5;} else if (symbol == "AUDJPY") { return 3;} else if (symbol == "AUDNZD") { return 5;} else if (symbol == "AUDSGD") { return 5;} else if (symbol == "AUDUSD") { return 5;} else if (symbol == "CADCHF") { return 5;} else if (symbol == "CADJPY") { return 3;} else if (symbol == "CHFJPY") { return 3;} else if (symbol == "EURAUD") { return 5;} else if (symbol == "EURCAD") { return 5;} else if (symbol == "EURCHF") { return 5;} else if (symbol == "EURGBP") { return 5;} else if (symbol == "EURJPY") { return 3;} else if (symbol == "EURNZD") { return 5;} else if (symbol == "GBPAUD") { return 5;} else if (symbol == "GBPCAD") { return 5;} else if (symbol == "GBPCHF") { return 5;} else if (symbol == "GBPJPY") { return 3;} else if (symbol == "GBPNZD") { return 5;} else if (symbol == "GBPUSD") { return 5;} else if (symbol == "NZDJPY") { return 3;} else if (symbol == "NZDUSD") { return 5;} else if (symbol == "USDCAD") { return 5;} else if (symbol == "USDCHF") { return 5;} else if (symbol == "USDHKD") { return 5;} else if (symbol == "USDJPY") { return 3;} else if (symbol == "USDMXN") { return 5;} else if (symbol == "USDPLN") { return 5;} else if (symbol == "USDSEK") { return 5;} else if (symbol == "USDSGD") { return 5;} else if (symbol == "USDZAR") { return 5;} else if (symbol == "XAGEUR") { return 3;} else if (symbol == "XAGUSD") { return 3;} else if (symbol == "XAUEUR") { return 2;} else if (symbol == "XAUUSD") { return 2;} else if (symbol == "ZARJPY") { return 3;} else { return 5; } }
//+------------------------------------------------------------------+ //| StatementToCSV.mq4 | //| Copyright 2014, Life with FX | //| http://lifewithfx.jp | //+------------------------------------------------------------------+ #property copyright "Copyright 2014, Life with FX" #property link "http://lifewithfx.jp" #property version "1.30" #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 = false; extern int ReportFromDate = 20140331; extern int ReportToDate = 20150830; //+------------------------------------------------------------------+ //| 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 = "Ticket,OrderType,OrderSymbol,OrderLots,OrderOpenTime,OrderOpenPrice,OrderCloseTime,OrderClosePrice,OrderProfitInPips,OrderCommission,OrderSwap,OrderProfit,TradeProfit,OrderMagicNumber,OrderComment,OrderCommentShort" + "\n"; if (OutputHeaderRecord) { FileWriteString(hFile, header, StringLen(header)); } const string ITEM_SEPARATOR = ","; int startIdx; int idxStep; int ordersLastIdx = historyTotal - 1; 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 = ticket[i] + ITEM_SEPARATOR; switch(OrderType()) { case OP_BUY: output = output + "BUY" + ITEM_SEPARATOR; break; case OP_SELL: output = output + "SELL" + ITEM_SEPARATOR; break; default: output = output + "" + ITEM_SEPARATOR; } output = output + OrderSymbol() + ITEM_SEPARATOR; output = output + DoubleToStr(OrderLots(),2) + ITEM_SEPARATOR; output = output + TimeToStr(OrderOpenTime()) + ITEM_SEPARATOR; output = output + NormalizeDouble(OrderOpenPrice(), MarketInfo(OrderSymbol(), MODE_DIGITS)) + ITEM_SEPARATOR; output = output + TimeToStr(OrderCloseTime()) + ITEM_SEPARATOR; output = output + NormalizeDouble(OrderClosePrice(), MarketInfo(OrderSymbol(), MODE_DIGITS)) + ITEM_SEPARATOR; switch(OrderType()) { case OP_BUY: takeprice = (OrderClosePrice() / (MarketInfo(OrderSymbol(), MODE_POINT) * 10)) - (OrderOpenPrice() / (MarketInfo(OrderSymbol(), MODE_POINT) * 10)); takepips = NormalizeDouble(takeprice, MarketInfo(OrderSymbol(), MODE_DIGITS)); output = output + takepips + ITEM_SEPARATOR; break; case OP_SELL: takeprice = (OrderOpenPrice() / (MarketInfo(OrderSymbol(), MODE_POINT) * 10)) - (OrderClosePrice() / (MarketInfo(OrderSymbol(), MODE_POINT) * 10)); takepips = NormalizeDouble(takeprice, MarketInfo(OrderSymbol(), MODE_DIGITS)); output = output + takepips + ITEM_SEPARATOR; break; } output = output + NormalizeDouble(OrderCommission(), 2) + ITEM_SEPARATOR; output = output + NormalizeDouble(OrderSwap(), 2) + ITEM_SEPARATOR; output = output + OrderProfit() + ITEM_SEPARATOR; output = output + (NormalizeDouble(OrderSwap(), 2) + NormalizeDouble(OrderCommission(), 2) + OrderProfit()) + ITEM_SEPARATOR; output = output + OrderMagicNumber() + ITEM_SEPARATOR; output = output + OrderComment() + ITEM_SEPARATOR; output = output + StringSubstr(OrderComment(), 0, 2); output = output + "\n"; FileSeek(hFile, 0, SEEK_END); FileWriteString(hFile, output, StringLen(output)); } } } if(0 < hFile) { FileClose(hFile); } Print ("works fine: finished!!"); return(0); }
//+------------------------------------------------------------------+ //| StatementToCSV.mq4 | //| Copyright 2014, Life with FX | //| http://lifewithfx.jp | //+------------------------------------------------------------------+ #property copyright "Copyright 2014, Life with FX" #property link "http://lifewithfx.jp" #property version "1.20" #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 = false; extern int ReportFromDate = 20140331; extern int ReportToDate = 20150331; //+------------------------------------------------------------------+ //| 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 = "Ticket,OrderType,OrderSymbol,OrderLots,OrderOpenTime,OrderOpenPrice,OrderCloseTime,OrderClosePrice,OrderProfitInPips,OrderCommission,OrderSwap,OrderProfit,TradeProfit,OrderMagicNumber,OrderComment,OrderCommentShort" + "\n"; if (OutputHeaderRecord) { FileWriteString(hFile, header, StringLen(header)); } const string ITEM_SEPARATOR = ","; int startIdx; int idxStep; int ordersLastIdx = historyTotal - 1; 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 = ticket[i] + ITEM_SEPARATOR; switch(OrderType()) { case OP_BUY: output = output + "BUY" + ITEM_SEPARATOR; break; case OP_SELL: output = output + "SELL" + ITEM_SEPARATOR; break; default: output = output + "" + ITEM_SEPARATOR; } output = output + OrderSymbol() + ITEM_SEPARATOR; output = output + OrderLots() + ITEM_SEPARATOR; output = output + TimeToStr(OrderOpenTime()) + ITEM_SEPARATOR; output = output + NormalizeDouble(OrderOpenPrice(), MarketInfo(OrderSymbol(), MODE_DIGITS)) + ITEM_SEPARATOR; output = output + TimeToStr(OrderCloseTime()) + ITEM_SEPARATOR; output = output + NormalizeDouble(OrderClosePrice(), MarketInfo(OrderSymbol(), MODE_DIGITS)) + ITEM_SEPARATOR; switch(OrderType()) { case OP_BUY: takeprice = NormalizeDouble(OrderClosePrice(), MarketInfo(OrderSymbol(), MODE_DIGITS)) - NormalizeDouble(OrderOpenPrice(), MarketInfo(OrderSymbol(), MODE_DIGITS)); takepips = takeprice / (MarketInfo(OrderSymbol(), MODE_POINT) * 10.0); output = output + takepips + ITEM_SEPARATOR; break; case OP_SELL: takeprice = NormalizeDouble(OrderOpenPrice(), MarketInfo(OrderSymbol(), MODE_DIGITS)) - NormalizeDouble(OrderClosePrice(), MarketInfo(OrderSymbol(), MODE_DIGITS)); takepips = takeprice / (MarketInfo(OrderSymbol(), MODE_POINT) * 10.0); output = output + takepips + ITEM_SEPARATOR; break; } output = output + NormalizeDouble(OrderCommission(), 2) + ITEM_SEPARATOR; output = output + NormalizeDouble(OrderSwap(), 2) + ITEM_SEPARATOR; output = output + OrderProfit() + ITEM_SEPARATOR; output = output + (NormalizeDouble(OrderSwap(), 2) + NormalizeDouble(OrderCommission(), 2) + OrderProfit()) + ITEM_SEPARATOR; output = output + OrderMagicNumber() + ITEM_SEPARATOR; output = output + OrderComment() + ITEM_SEPARATOR; output = output + StringSubstr(OrderComment(), 0, 2); output = output + "\n"; FileSeek(hFile, 0, SEEK_END); FileWriteString(hFile, output, StringLen(output)); } } } if(0 < hFile) { FileClose(hFile); } Print ("works fine: finished!!"); return(0); }
//+------------------------------------------------------------------+ //| StatementToCSV.mq4 | //| Copyright 2014, Life with FX | //| http://lifewithfx.jp | //+------------------------------------------------------------------+ #property copyright "Copyright 2014, Life with FX" #property link "http://lifewithfx.jp" #property version "1.10" #property strict #property show_inputs extern string CSVOutputFolder = "-- MT4 MQL4/Files folder --"; extern bool OutputRecordDescendingOrder = false; extern string ReportPeriod = "-- PeriodFilter: Order close time base --"; extern int ReportFromDate = 20140101; extern int ReportToDate = 20140331; //+------------------------------------------------------------------+ //| 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 = "Ticket,OrderType,OrderSymbol,OrderLots,OrderOpenTime,OrderOpenPrice,OrderCloseTime,OrderClosePrice,OrderProfitInPips,OrderCommission,OrderSwap,OrderProfit,TradeProfit,OrderMagicNumber,OrderComment,OrderCommentShort" + "\n"; FileWriteString(hFile, header, StringLen(header)); const string ITEM_SEPARATOR = ","; int startIdx; int idxStep; int ordersLastIdx = historyTotal - 1; 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 (ReportFromDate <= closeDateInt && closeDateInt <= ReportToDate) { // OK } else { continue; } string output = ticket[i] + ITEM_SEPARATOR; switch(OrderType()) { case OP_BUY: output = output + "BUY" + ITEM_SEPARATOR; break; case OP_SELL: output = output + "SELL" + ITEM_SEPARATOR; break; default: output = output + "" + ITEM_SEPARATOR; } output = output + OrderSymbol() + ITEM_SEPARATOR; output = output + OrderLots() + ITEM_SEPARATOR; output = output + TimeToStr(OrderOpenTime()) + ITEM_SEPARATOR; output = output + NormalizeDouble(OrderOpenPrice(), MarketInfo(OrderSymbol(), MODE_DIGITS)) + ITEM_SEPARATOR; output = output + TimeToStr(OrderCloseTime()) + ITEM_SEPARATOR; output = output + NormalizeDouble(OrderClosePrice(), MarketInfo(OrderSymbol(), MODE_DIGITS)) + ITEM_SEPARATOR; switch(OrderType()) { case OP_BUY: takeprice = NormalizeDouble(OrderClosePrice(), MarketInfo(OrderSymbol(), MODE_DIGITS)) - NormalizeDouble(OrderOpenPrice(), MarketInfo(OrderSymbol(), MODE_DIGITS)); takepips = takeprice / (MarketInfo(OrderSymbol(), MODE_POINT) * 10.0); output = output + takepips + ITEM_SEPARATOR; break; case OP_SELL: takeprice = NormalizeDouble(OrderOpenPrice(), MarketInfo(OrderSymbol(), MODE_DIGITS)) - NormalizeDouble(OrderClosePrice(), MarketInfo(OrderSymbol(), MODE_DIGITS)); takepips = takeprice / (MarketInfo(OrderSymbol(), MODE_POINT) * 10.0); output = output + takepips + ITEM_SEPARATOR; break; } output = output + NormalizeDouble(OrderCommission(), 2) + ITEM_SEPARATOR; output = output + NormalizeDouble(OrderSwap(), 2) + ITEM_SEPARATOR; output = output + OrderProfit() + ITEM_SEPARATOR; output = output + (NormalizeDouble(OrderSwap(), 2) + NormalizeDouble(OrderCommission(), 2) + OrderProfit()) + ITEM_SEPARATOR; output = output + OrderMagicNumber() + ITEM_SEPARATOR; output = output + OrderComment() + ITEM_SEPARATOR; output = output + StringSubstr(OrderComment(), 0, 2); output = output + "\n"; FileSeek(hFile, 0, SEEK_END); FileWriteString(hFile, output, StringLen(output)); } } } if(0 < hFile) { FileClose(hFile); } Print ("works fine: finished!!"); return(0); }
次に使い方の説明です。
MT4を起動して、ソースファイルをコンパイルしましょう。
メタエディタで、ソースファイルをコンパイルします。
Newをクリック後、スクリプトを選択して適当に進めます。
エディタが立ち上がったら、当サイトのStatementToCSV.mq4の内容を全て上書きして、ボタンを3つクリックします。
上記オペレーションを行えば、起動しているMT4のスクリプトに、StatementToCSVが現れます。
実際に、スクリプトを動かす前に、1つ準備が必要です。
MT4の”口座履歴タブ”から、データピックアップ期間分が表示されるように、調整します。(カスタム期間か、全履歴を選択して下さい)
表示期間の設定がおわりましたら、いよいよ稼働です。
こんな感じで良いです。
レコード出力順(チケットベース)が、昇順・降順の選択可能
また、オーダークローズ日ベースで、CSV出力期間の選択抽出が可能
3ヶ月程度でしたら、スクリプトの稼働は数秒で完了します。
CSVファイルの出力先は、MT4の更新データが存在するフォルダの、MQL4->Filesに出力されます。
CSVファイル名は、自動設定となりまして、実行前に任意設定できません。
出来上がり。
とても、素晴らしいスクリプトですね。
確定申告に必要な、取引履歴作成に利用しています。
あつかましい要望ですが、取引履歴以外のデータも出力出来れば、尚、有用と思います。
具体的には、入金と出金の履歴も出力出来れば、取引の全てのデータを取得する事ができます。
”直近のEA性能の計算や損益集計する際にデータ加工が面倒なので” と言う、当該スクリプトの
作成コンセプトからは外れますが、入金、出金のデータも、重要な情報です。
このスクリプトを利用するレベルの人であれば、excelで、必要なデータ選択は出来ると思いますので、是非とも、MT4のターミナルで取得出来るデータ全てを、出力出来るように、機能を追加して戴けないでしょうか。
お忙しい中で、時間が取れましたら、御一考戴ければ幸いです。
大変有用なスクリプトを、無償で提供いただきまして、誠に有難う御座います。
CSVファイルに出力する方法を教えて頂き、ありがとうございました。便利に使わさせて頂いてます。MT4でDDE出力したEXCELファイルだとpipsは無いわ、pipsを計算しようにも価格の3桁区切りの部分にスペースが入ってしまい、計算も出来ないわでほとほと困ってました。