forked from nique_372/FullMt5McpByLeo
535 lines
20 KiB
MQL5
535 lines
20 KiB
MQL5
//+------------------------------------------------------------------+
|
|
//| Run.mqh |
|
|
//| Copyright 2026, Niquel Mendoza. |
|
|
//| https://www.mql5.com/es/users/nique_372 |
|
|
//+------------------------------------------------------------------+
|
|
#property copyright "Copyright 2026, Niquel Mendoza."
|
|
#property link "https://www.mql5.com/es/users/nique_372"
|
|
#property strict
|
|
|
|
#ifndef FULLMT5MCPBYLEO_SRC_COMPLEX_COMPLEX_MQH
|
|
#define FULLMT5MCPBYLEO_SRC_COMPLEX_COMPLEX_MQH
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| Include |
|
|
//+------------------------------------------------------------------+
|
|
#include "..\\Def\\Def.mqh"
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
namespace TSN
|
|
{
|
|
class CMcpFunctionRunBacktest : public CMcpFunction
|
|
{
|
|
private:
|
|
long m_chart_id_runner;
|
|
const long m_current_chart_id;
|
|
public:
|
|
CMcpFunctionRunBacktest(void) : CMcpFunction(0, false, "run_mt5_tester"),
|
|
m_current_chart_id(ChartID()), m_chart_id_runner(0)
|
|
{
|
|
m_chart_id_runner = DEFMTTesterGetChartId();
|
|
}
|
|
~CMcpFunctionRunBacktest(void) {}
|
|
void Run(CJsonNode& param, string& res) override final;
|
|
};
|
|
//+------------------------------------------------------------------+
|
|
void CMcpFunctionRunBacktest::Run(CJsonNode ¶m, string &res)
|
|
{
|
|
//---
|
|
if(m_chart_id_runner == 0)
|
|
{
|
|
m_chart_id_runner = DEFMTTesterGetChartId();
|
|
}
|
|
|
|
//---
|
|
static MTTesterTask task;
|
|
task.symbol = param["symbol"].ToString("");
|
|
task.set_file = param["set_file_name"].ToString("");
|
|
task.expert_path = param["expert_path"].ToString("");
|
|
task.chart_id_from = m_current_chart_id; // Viene de aqui.. (auqneu igual no recibiremos el evento..)
|
|
task.start_date = StringToTime(param["start_date"].ToString("0"));
|
|
task.end_date = StringToTime(param["end_date"].ToString("0"));
|
|
task.timeframe = CEnumRegBasis::GetValNoRef<ENUM_TIMEFRAMES>(param["timeframe"].ToString(), _Period);
|
|
task.leverage = (uint16_t)param["leverage"].ToInt(0);
|
|
task.visual_mode = param["visual_mode"].ToBool(false);
|
|
task.modelado = CEnumRegFullMt5Mcp::GetValNoRef<int8_t>(param["modelado"].ToString(),
|
|
-1); // usar el que viene por defecto..
|
|
task.opt_mode = CEnumRegFullMt5Mcp::GetValNoRef<int8_t>(param["opt_mode"].ToString(),
|
|
-1); // usar el que viene por defecto..
|
|
task.criterio_opt = CEnumRegFullMt5Mcp::GetValNoRef<int8_t>(param["optimization_criterion"].ToString(),
|
|
-1); // usar el que viene por defecto..
|
|
task.forward_mode = CEnumRegFullMt5Mcp::GetValNoRef<int8_t>(param["forward_mode"].ToString(),
|
|
-1); // usar el que viene por defecto..
|
|
task.delay_ms = (int)param["delay_ms"].ToInt(-2); // usar el que viene por defecto
|
|
task.forward_date = (datetime)param["forward_date"].ToInt(0);
|
|
|
|
//---
|
|
const bool common = param["file_in_common"].ToBool(true);
|
|
const string fn = param["data_file_name"].ToString("tester_instruction.bin");
|
|
::ResetLastError();
|
|
const int fh = FileOpen(fn, FILE_WRITE | FILE_BIN | (common ? FILE_COMMON : 0));
|
|
if(fh == INVALID_HANDLE)
|
|
{
|
|
res = StringFormat("{\"ok\":false,\"error\":\"Error write data in file[%s], last mt5 error = %d\"}", fn, ::GetLastError());
|
|
return;
|
|
}
|
|
|
|
task.Save(fh);
|
|
FileClose(fh);
|
|
|
|
//---
|
|
::ResetLastError();
|
|
if(!::EventChartCustom(m_chart_id_runner, DEFMTTESTER_E_ON_TASK, m_current_chart_id, DEFMTTESTER_TO_DBL_ON_TASK(true), fn))
|
|
{
|
|
res = StringFormat("{\"ok\":false,\"error\":\"Error to send event to run backtest, last err = %d, Ask the user if they have the Runner.ex5 bot running in their terminal, since this bot launches the tester itself; it only gives the command\"}",
|
|
::GetLastError());
|
|
}
|
|
else
|
|
{
|
|
res = "{\"ok\":true,\"result\":\"Execution command sent to Runner.ex5, this should launch the MT5 strategy tester\"}";
|
|
}
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
class CMcpFunctionRunEA : public CMcpFunction
|
|
{
|
|
public:
|
|
CMcpFunctionRunEA(void) : CMcpFunction(0, false, "run_ea") {}
|
|
~CMcpFunctionRunEA(void) {}
|
|
void Run(CJsonNode& param, string& res) override final;
|
|
};
|
|
|
|
/*
|
|
{
|
|
"symbol" : "XAUUSD",
|
|
"timeframe" : "PERIOD_M1",
|
|
"ms_espera" : 1500,
|
|
"expert_path" : "Experts\\MiEA.ex5",
|
|
"run_flags" : "DLL|AutoTrading"
|
|
"params" : [
|
|
{
|
|
"data_type" : "TYPE_STRING",
|
|
"value" : "10.0"
|
|
}
|
|
]
|
|
}
|
|
*/
|
|
//+------------------------------------------------------------------+
|
|
void CMcpFunctionRunEA::Run(CJsonNode ¶m, string &res)
|
|
{
|
|
::ResetLastError();
|
|
const long chart_id = OpenChartAndDevoler(ChartID(), param["symbol"].ToString(_Symbol), CEnumRegBasis::GetValNoRef<ENUM_TIMEFRAMES>(param["timeframe"].ToString(), _Period), int(param["ms_espera"].ToInt(750)));
|
|
if(chart_id == -1)
|
|
{
|
|
res = StringFormat("{\"ok\":false,\"error\":\"Error open chart, last mt5 err = %d\"}", ::GetLastError());
|
|
return;
|
|
}
|
|
|
|
//---
|
|
const int t = param["params"].Size();
|
|
|
|
//---
|
|
MqlParam exp_param[];
|
|
ArrayResize(exp_param, t + 1);
|
|
exp_param[0].type = TYPE_STRING;
|
|
exp_param[0].string_value = param["expert_path"].ToString();
|
|
|
|
//---
|
|
if(t > 0)
|
|
{
|
|
CJsonIteratorArray it = param["params"].BeginArr();
|
|
int k = 1;
|
|
while(it.IsValid())
|
|
{
|
|
//---
|
|
CJsonNode parametro = it.Val();
|
|
exp_param[k].type = CEnumRegBasis::GetValNoRef<ENUM_DATATYPE>(parametro["data_type"].ToString(), TYPE_STRING);
|
|
|
|
//---
|
|
switch(exp_param[k].type)
|
|
{
|
|
case TYPE_BOOL:
|
|
exp_param[k].integer_value = parametro["value"].ToInt(0);
|
|
break;
|
|
case TYPE_CHAR:
|
|
exp_param[k].integer_value = parametro["value"].ToInt(0);
|
|
break;
|
|
case TYPE_UCHAR:
|
|
exp_param[k].integer_value = parametro["value"].ToInt(0);
|
|
break;
|
|
case TYPE_SHORT:
|
|
exp_param[k].integer_value = parametro["value"].ToInt(0);
|
|
break;
|
|
case TYPE_USHORT:
|
|
exp_param[k].integer_value = parametro["value"].ToInt(0);
|
|
break;
|
|
case TYPE_COLOR:
|
|
exp_param[k].integer_value = long(color(parametro["value"].ToString("")));
|
|
break;
|
|
case TYPE_INT:
|
|
exp_param[k].integer_value = parametro["value"].ToInt(0);
|
|
break;
|
|
case TYPE_UINT:
|
|
exp_param[k].integer_value = parametro["value"].ToInt(0);
|
|
break;
|
|
case TYPE_DATETIME:
|
|
exp_param[k].integer_value = long(datetime(parametro["value"].ToString("0")));
|
|
break;
|
|
case TYPE_LONG:
|
|
case TYPE_ULONG:
|
|
exp_param[k].integer_value = parametro["value"].ToInt(0);
|
|
break;
|
|
case TYPE_FLOAT:
|
|
exp_param[k].double_value = parametro["value"].ToDouble(0.00);
|
|
break;
|
|
case TYPE_DOUBLE:
|
|
exp_param[k].double_value = parametro["value"].ToDouble(0.00);
|
|
break;
|
|
case TYPE_STRING:
|
|
exp_param[k].string_value = parametro["value"].ToString("");
|
|
break;
|
|
default:
|
|
exp_param[k].string_value = parametro["value"].ToString("");
|
|
break;
|
|
}
|
|
k++;
|
|
//---
|
|
it.Next();
|
|
}
|
|
}
|
|
|
|
//---
|
|
if(!EXPERT::Run(chart_id, exp_param, EXPERT::FlagsPermisosStrToFlags(param["run_flags"].ToString(), '|')))
|
|
{
|
|
res = "{\"ok\":false,\"error\":\"Error run EA, view logs..\"}";
|
|
}
|
|
else
|
|
{
|
|
res = StringFormat("{\"ok\":true,\"result\":\"EA successfully launched on chart with chart id = %I64d\"}", chart_id);
|
|
}
|
|
}
|
|
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
class CMcpFunctionCompile : public CMcpFunction
|
|
{
|
|
public:
|
|
CMcpFunctionCompile(void): CMcpFunction(0, false, "compile_mql5") {}
|
|
~CMcpFunctionCompile(void) {}
|
|
// instruction = [avx, avx2, avx512]
|
|
void Run(CJsonNode& param, string& res) override final;
|
|
};
|
|
//+------------------------------------------------------------------+
|
|
void CMcpFunctionCompile::Run(CJsonNode ¶m, string &res)
|
|
{
|
|
string out_log_path = "";
|
|
if(!CompileFileWithLogFile(param["full_path_code"].ToString(""), out_log_path, (int)param["timeout_ms"].ToInt(60000), param["instruction"].ToString(""), param["optimize"].ToBool(true)))
|
|
{
|
|
res = StringFormat("{\"ok\":false,\"error\":\"Error compile file, view experts logs, and compile log file = %s\"}", out_log_path);
|
|
}
|
|
else
|
|
{
|
|
res = StringFormat("{\"ok\":true,\"result\":\"Success compiling file, log file=(%s)\"}", out_log_path);
|
|
}
|
|
}
|
|
|
|
//+------------------------------------------------------------------+
|
|
//| |
|
|
//+------------------------------------------------------------------+
|
|
class CMcpFuncTesterRep : public CMcpFunction
|
|
{
|
|
private:
|
|
SINGLETESTERCACHE m_tst;
|
|
CJsonBuilder m_builder;
|
|
bool m_cached;
|
|
|
|
public:
|
|
CMcpFuncTesterRep(void) : CMcpFunction(0, false, "tester_reports") {}
|
|
~CMcpFuncTesterRep(void) {}
|
|
void Run(CJsonNode& param, string& res) override final;
|
|
};
|
|
|
|
//+------------------------------------------------------------------+
|
|
void CMcpFuncTesterRep::Run(CJsonNode& param, string& res)
|
|
{
|
|
// En caso no se haya caechado esto se ginora ahora en caso si este checado reivsamos si hay qeu forzar el load
|
|
if(m_cached && param["forze_reload"].ToBool(false))
|
|
m_cached = false;
|
|
|
|
// Solo recargamos si no esta cacheado..
|
|
if(!m_cached)
|
|
{
|
|
uchar data[];
|
|
if(!MTTESTER::GetLastTstCache(data))
|
|
{
|
|
res = "{\"ok\":false,\"error\":\"Error getting last tester cache\"}";
|
|
return;
|
|
}
|
|
if(!m_tst.Load(data))
|
|
{
|
|
res = "{\"ok\":false,\"error\":\"Error loading tester cache\"}";
|
|
return;
|
|
}
|
|
m_cached = true;
|
|
}
|
|
|
|
const ENUM_MCPFUNC_TESTER_GET mode = CEnumRegFullMt5Mcp::GetValNoRef<ENUM_MCPFUNC_TESTER_GET>(
|
|
param["mode"].ToString(""), WRONG_VALUE);
|
|
m_builder.Clear();
|
|
switch(mode)
|
|
{
|
|
case MCPFUNC_TESTER_GET_SUMMARY:
|
|
{
|
|
m_builder.Obj();
|
|
m_builder.Key("ok").Val(true);
|
|
m_builder.Key("result").Obj();
|
|
|
|
//--- Header
|
|
m_builder.Key("tst_file_name").ValSNoRef(m_tst.Header.name[]);
|
|
m_builder.Key("expert_name").ValSNoRef(m_tst.Header.expert_name[]);
|
|
m_builder.Key("expert_path").ValSNoRef(m_tst.Header.expert_path[]);
|
|
m_builder.Key("server").ValSNoRef(m_tst.Header.server[]);
|
|
m_builder.Key("version").Val((int)m_tst.Header.version);
|
|
m_builder.Key("copyright").ValSNoRef(m_tst.Header.copyright[]);
|
|
m_builder.Key("msc_execution_time").Val((int)m_tst.Header.msc_last);
|
|
m_builder.Key("symbol").ValSNoRef(m_tst.Header.symbol[]);
|
|
|
|
// --- ExpTradeSummarySingle ---
|
|
m_builder.Key("bars").Val(m_tst.Summary.bars);
|
|
m_builder.Key("ticks").Val(m_tst.Summary.ticks);
|
|
m_builder.Key("symbol").ValSNoRef(m_tst.Summary.symbol[]);
|
|
m_builder.Key("initial_deposit").Val(m_tst.Summary.initial_deposit);
|
|
m_builder.Key("withdrawal").Val(m_tst.Summary.withdrawal);
|
|
m_builder.Key("profit").Val(m_tst.Summary.profit);
|
|
m_builder.Key("grossprofit").Val(m_tst.Summary.grossprofit);
|
|
m_builder.Key("grossloss").Val(m_tst.Summary.grossloss);
|
|
m_builder.Key("maxprofit").Val(m_tst.Summary.maxprofit);
|
|
m_builder.Key("minprofit").Val(m_tst.Summary.minprofit);
|
|
m_builder.Key("conprofitmax").Val(m_tst.Summary.conprofitmax);
|
|
m_builder.Key("maxconprofit").Val(m_tst.Summary.maxconprofit);
|
|
m_builder.Key("conlossmax").Val(m_tst.Summary.conlossmax);
|
|
m_builder.Key("maxconloss").Val(m_tst.Summary.maxconloss);
|
|
m_builder.Key("balance_min").Val(m_tst.Summary.balance_min);
|
|
m_builder.Key("maxdrawdown").Val(m_tst.Summary.maxdrawdown);
|
|
m_builder.Key("drawdownpercent").Val(m_tst.Summary.drawdownpercent);
|
|
m_builder.Key("reldrawdown").Val(m_tst.Summary.reldrawdown);
|
|
m_builder.Key("reldrawdownpercent").Val(m_tst.Summary.reldrawdownpercent);
|
|
m_builder.Key("equity_min").Val(m_tst.Summary.equity_min);
|
|
m_builder.Key("maxdrawdown_e").Val(m_tst.Summary.maxdrawdown_e);
|
|
m_builder.Key("drawdownpercent_e").Val(m_tst.Summary.drawdownpercent_e);
|
|
m_builder.Key("reldrawdown_e").Val(m_tst.Summary.reldrawdown_e);
|
|
m_builder.Key("reldrawdownpercnt_e").Val(m_tst.Summary.reldrawdownpercnt_e);
|
|
m_builder.Key("expected_payoff").Val(m_tst.Summary.expected_payoff);
|
|
m_builder.Key("profit_factor").Val(m_tst.Summary.profit_factor);
|
|
m_builder.Key("recovery_factor").Val(m_tst.Summary.recovery_factor);
|
|
m_builder.Key("sharpe_ratio").Val(m_tst.Summary.sharpe_ratio);
|
|
m_builder.Key("margin_level").Val(m_tst.Summary.margin_level);
|
|
m_builder.Key("custom_fitness").Val(m_tst.Summary.custom_fitness);
|
|
m_builder.Key("deals").Val(m_tst.Summary.deals);
|
|
m_builder.Key("trades").Val(m_tst.Summary.trades);
|
|
m_builder.Key("profittrades").Val(m_tst.Summary.profittrades);
|
|
m_builder.Key("losstrades").Val(m_tst.Summary.losstrades);
|
|
m_builder.Key("shorttrades").Val(m_tst.Summary.shorttrades);
|
|
m_builder.Key("longtrades").Val(m_tst.Summary.longtrades);
|
|
m_builder.Key("winshorttrades").Val(m_tst.Summary.winshorttrades);
|
|
m_builder.Key("winlongtrades").Val(m_tst.Summary.winlongtrades);
|
|
m_builder.Key("conprofitmax_trades").Val(m_tst.Summary.conprofitmax_trades);
|
|
m_builder.Key("maxconprofit_trades").Val(m_tst.Summary.maxconprofit_trades);
|
|
m_builder.Key("conlossmax_trades").Val(m_tst.Summary.conlossmax_trades);
|
|
m_builder.Key("maxconloss_trades").Val(m_tst.Summary.maxconloss_trades);
|
|
m_builder.Key("avgconwinners").Val(m_tst.Summary.avgconwinners);
|
|
m_builder.Key("avgconloosers").Val(m_tst.Summary.avgconloosers);
|
|
|
|
// --- ExpTradeSummaryExt ---
|
|
m_builder.Key("ghpr").Val(m_tst.Summary.ghpr);
|
|
m_builder.Key("ghprpercent").Val(m_tst.Summary.ghprpercent);
|
|
m_builder.Key("ahpr").Val(m_tst.Summary.ahpr);
|
|
m_builder.Key("ahprpercent").Val(m_tst.Summary.ahprpercent);
|
|
m_builder.Key("zscore").Val(m_tst.Summary.zscore);
|
|
m_builder.Key("zscorepercent").Val(m_tst.Summary.zscorepercent);
|
|
m_builder.Key("lrcorr").Val(m_tst.Summary.lrcorr);
|
|
m_builder.Key("lrstderror").Val(m_tst.Summary.lrstderror);
|
|
m_builder.Key("symbols").Val((int)m_tst.Summary.symbols);
|
|
m_builder.Key("corr_prf_mfe").Val(m_tst.Summary.corr_prf_mfe);
|
|
m_builder.Key("corr_prf_mae").Val(m_tst.Summary.corr_prf_mae);
|
|
m_builder.Key("corr_mfe_mae").Val(m_tst.Summary.corr_mfe_mae);
|
|
m_builder.Key("mfe_a").Val(m_tst.Summary.mfe_a);
|
|
m_builder.Key("mfe_b").Val(m_tst.Summary.mfe_b);
|
|
m_builder.Key("mae_a").Val(m_tst.Summary.mae_a);
|
|
m_builder.Key("mae_b").Val(m_tst.Summary.mae_b);
|
|
m_builder.Key("holding_time_min").Val((long)m_tst.Summary.holding_time_min);
|
|
m_builder.Key("holding_time_max").Val((long)m_tst.Summary.holding_time_max);
|
|
m_builder.Key("holding_time_avr").Val((long)m_tst.Summary.holding_time_avr);
|
|
m_builder.Key("in_commission").Val(m_tst.Summary.in_commission);
|
|
|
|
//--- Tiempo
|
|
|
|
|
|
|
|
// --- Arrays de distribucion ---
|
|
m_builder.Key("in_per_hours").Arr();
|
|
for(int i = 0; i < 24; i++)
|
|
m_builder.Val((int)m_tst.Summary.in_per_hours[i]);
|
|
m_builder.EndArr();
|
|
|
|
m_builder.Key("in_per_week_days").Arr();
|
|
for(int i = 0; i < 7; i++)
|
|
m_builder.Val((int)m_tst.Summary.in_per_week_days[i]);
|
|
m_builder.EndArr();
|
|
|
|
m_builder.Key("in_per_months").Arr();
|
|
for(int i = 0; i < 12; i++)
|
|
m_builder.Val((int)m_tst.Summary.in_per_months[i]);
|
|
m_builder.EndArr();
|
|
|
|
m_builder.Key("out_per_hours").Arr();
|
|
for(int i = 0; i < 24; i++)
|
|
{
|
|
m_builder.Arr();
|
|
m_builder.Val(m_tst.Summary.out_per_hours[i][0]);
|
|
m_builder.Val(m_tst.Summary.out_per_hours[i][1]);
|
|
m_builder.EndArr();
|
|
}
|
|
m_builder.EndArr();
|
|
|
|
m_builder.Key("out_per_week_days").Arr();
|
|
for(int i = 0; i < 7; i++)
|
|
{
|
|
m_builder.Arr();
|
|
m_builder.Val(m_tst.Summary.out_per_week_days[i][0]);
|
|
m_builder.Val(m_tst.Summary.out_per_week_days[i][1]);
|
|
m_builder.EndArr();
|
|
}
|
|
m_builder.EndArr();
|
|
|
|
m_builder.Key("out_per_months").Arr();
|
|
for(int i = 0; i < 12; i++)
|
|
{
|
|
m_builder.Arr();
|
|
m_builder.Val(m_tst.Summary.out_per_months[i][0]);
|
|
m_builder.Val(m_tst.Summary.out_per_months[i][1]);
|
|
m_builder.EndArr();
|
|
}
|
|
m_builder.EndArr();
|
|
|
|
m_builder.EndObj();
|
|
m_builder.EndObj();
|
|
break;
|
|
}
|
|
|
|
case MCPFUNC_TESTER_GET_BALANCE_HISTORY:
|
|
{
|
|
double balance[];
|
|
const int s = (int)param["start"].ToInt(0);
|
|
const int k = m_tst.GetBalance(balance, param["date_start"].ToInt(0),
|
|
param["date_end"].ToInt(0),
|
|
param["incluyed_deposit"].ToBool(true));
|
|
const int t = fmin((int)param["count"].ToInt(1), k);
|
|
|
|
if(t != -1)
|
|
{
|
|
m_builder.Obj();
|
|
m_builder.Key("ok").Val(true);
|
|
m_builder.Key("result").Arr();
|
|
for(int i = s; i < t; i++)
|
|
{
|
|
m_builder.Val(balance[i]);
|
|
}
|
|
m_builder.EndArr().EndObj();
|
|
}
|
|
else
|
|
{
|
|
m_builder.Obj();
|
|
m_builder.Key("ok").Val(false);
|
|
m_builder.Key("result").ValS("Failure to obtain balance history.");
|
|
m_builder.EndObj();
|
|
}
|
|
break;
|
|
}
|
|
|
|
case MCPFUNC_TESTER_GET_EQUITY_HISTORY:
|
|
{
|
|
double eq[];
|
|
const int s = (int)param["start"].ToInt(0);
|
|
const int k = m_tst.GetEquity(eq, param["date_start"].ToInt(0),
|
|
param["date_end"].ToInt(0),
|
|
param["incluyed_deposit"].ToBool(true));
|
|
const int t = fmin((int)param["count"].ToInt(1), k);
|
|
|
|
if(t != -1)
|
|
{
|
|
m_builder.Obj();
|
|
m_builder.Key("ok").Val(true);
|
|
m_builder.Key("result").Arr();
|
|
for(int i = s; i < t; i++)
|
|
{
|
|
m_builder.Val(eq[i]);
|
|
}
|
|
m_builder.EndArr().EndObj();
|
|
}
|
|
else
|
|
{
|
|
m_builder.Obj();
|
|
m_builder.Key("ok").Val(false);
|
|
m_builder.Key("result").ValS("Failure to obtain equity history.");
|
|
m_builder.EndObj();
|
|
}
|
|
break;
|
|
}
|
|
|
|
case MCPFUNC_TESTER_GET_DEALS_HISTORY:
|
|
{
|
|
|
|
const int s = (int)param["start"].ToInt(0);
|
|
const int t = fmin((int)param["count"].ToInt(1), ArraySize(m_tst.Deals));
|
|
|
|
m_builder.Obj();
|
|
m_builder.Key("ok").Val(true);
|
|
m_builder.Key("result").Arr();
|
|
for(int i = s; i < t; i++)
|
|
{
|
|
m_builder.Obj();
|
|
m_builder.Key("deal").Val((long)m_tst.Deals[i].deal);
|
|
m_builder.Key("order").Val((long)m_tst.Deals[i].order);
|
|
m_builder.Key("position_id").Val((long)m_tst.Deals[i].position_id);
|
|
m_builder.Key("time").Val((long)m_tst.Deals[i].time_create);
|
|
m_builder.Key("symbol").Val((int)m_tst.Deals[i].symbol[]);
|
|
m_builder.Key("action").Val((int)m_tst.Deals[i].action);
|
|
m_builder.Key("entry").Val((int)m_tst.Deals[i].entry);
|
|
m_builder.Key("price_open").Val(m_tst.Deals[i].price_open);
|
|
m_builder.Key("price_close").Val(m_tst.Deals[i].price_close);
|
|
m_builder.Key("sl").Val(m_tst.Deals[i].sl);
|
|
m_builder.Key("tp").Val(m_tst.Deals[i].tp);
|
|
m_builder.Key("volume").Val((double)m_tst.Deals[i].volume / (m_tst.Deals[i].contract_size > 0 ? m_tst.Deals[i].contract_size * 1000 : 1e8));
|
|
m_builder.Key("profit").Val(m_tst.Deals[i].profit);
|
|
m_builder.Key("commission").Val(m_tst.Deals[i].commission);
|
|
m_builder.Key("storage").Val(m_tst.Deals[i].storage);
|
|
m_builder.Key("comment").ValSNoRef(m_tst.Deals[i].comment[]);
|
|
m_builder.EndObj();
|
|
}
|
|
m_builder.EndArr().EndObj();
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
m_builder.Obj();
|
|
m_builder.Key("ok").Val(false);
|
|
m_builder.Key("result").ValS("Invalid mode");
|
|
m_builder.EndObj();
|
|
break;
|
|
}
|
|
}
|
|
res = m_builder.Build();
|
|
}
|
|
} // namespace TSN
|
|
|
|
#endif // FULLMT5MCPBYLEO_SRC_COMPLEX_COMPLEX_MQH
|