diff --git a/mq4/MtApi.mq4 b/mq4/MtApi.mq4 index e721df62..13635742 100755 --- a/mq4/MtApi.mq4 +++ b/mq4/MtApi.mq4 @@ -79,10 +79,7 @@ public: jo.put("ClosePrice", new JSONNumber(_closePrice)); jo.put("Lots", new JSONNumber(_lots)); jo.put("Profit", new JSONNumber(_profit)); - if (_comment != "") - { - jo.put("Comment", new JSONString(_comment)); - } + jo.put("Comment", new JSONString(_comment)); jo.put("Commission", new JSONNumber(_commission)); jo.put("MagicNumber", new JSONNumber(_magicNumber)); jo.put("MtOpenTime", new JSONNumber(_openTime)); @@ -186,9 +183,10 @@ private: class MtTimeBar: public MtObject { public: - MtTimeBar(string symbol, datetime openTime, datetime closeTime, double open, double close, double high, double low) + MtTimeBar(string symbol, int period, datetime openTime, datetime closeTime, double open, double close, double high, double low) { _symbol = symbol; + _period = period; _openTime = openTime; _closeTime = closeTime; _open = open; @@ -196,11 +194,12 @@ public: _high = high; _low = low; } - + virtual JSONObject* CreateJson() { - JSONObject *jo = new JSONObject(); + JSONObject *jo = new JSONObject(); jo.put("Symbol", new JSONString(_symbol)); + jo.put("Period", new JSONNumber(_period)); jo.put("MtOpenTime", new JSONNumber(_openTime)); jo.put("MtCloseTime", new JSONNumber(_closeTime)); jo.put("Open", new JSONNumber(_open)); @@ -210,8 +209,9 @@ public: return jo; } -private: +private: string _symbol; + int _period; datetime _openTime; datetime _closeTime; double _open; @@ -381,33 +381,40 @@ int OnInit() //--- Backtesting mode if (IsTesting()) - { + { Print("Waiting on remote client..."); //wait for command (BacktestingReady) from remote side to be ready for work while(!IsRemoteReadyForTesting) { ExecuteCommand(); - + //This section uses a while loop to simulate Sleep() during Backtest. unsigned int viSleepUntilTick = GetTickCount() + 100; //100 milliseconds - while(GetTickCount() < viSleepUntilTick) + while(GetTickCount() < viSleepUntilTick) { //Do absolutely nothing. Just loop until the desired tick is reached. } } } - //--- - + else + { + //--- Live trading: poll command queue via timer + EventSetMillisecondTimer(100); + } + //--- + _lastBarOpenTime = Time[0]; - + return (INIT_SUCCEEDED); } void OnDeinit(const int reason) { - if (isCrashed == 0) + EventKillTimer(); + + if (isCrashed == 0) { - if (!deinitExpert(ExpertHandle, _error)) + if (!deinitExpert(ExpertHandle, _error)) { MessageBox(_error, "MtApi", MB_OK); isCrashed = TRUE; @@ -437,7 +444,7 @@ void OnTick() double high = High[1]; double low = Low[1]; - MtTimeBar timeBar(Symbol(), _lastBarOpenTime, Time[0], open, close, high, low); + MtTimeBar timeBar(Symbol(), Period(), _lastBarOpenTime, Time[0], open, close, high, low); SendMtEvent(LAST_TIME_BAR_EVENT, timeBar); _lastBarOpenTime = Time[0]; @@ -452,25 +459,29 @@ void OnTick() (BacktestingLockTicks == LOCK_EVERY_CANDLE && lastbar_time_changed)) { _is_ticks_locked = true; - + MtLockTickEvent lock_tick_event(Symbol()); SendMtEvent(ON_LOCK_TICKS_EVENT, lock_tick_event); } - + while(true) { if (IsStopped()) break; - + int executedCommand = ExecuteCommand(); - + if (_is_ticks_locked) continue; - - if (executedCommand == 0) + + if (executedCommand == 0) break; } } + else + { + OnTimer(); + } } void OnTimer() diff --git a/mq4/json.mqh b/mq4/json.mqh index 8c391c72..bd3446fb 100644 --- a/mq4/json.mqh +++ b/mq4/json.mqh @@ -782,7 +782,7 @@ private: // number int i=_pos; - if(_in[_pos]=='-') + if(_in[_pos]=='-') { sign=-1; _pos++; @@ -793,6 +793,7 @@ private: sign=1; } + i=_pos; while(i<_len && isDigit(_in[i])) { l=l*10+(_in[i]-'0'); diff --git a/mq5/MtApi5.mq5 b/mq5/MtApi5.mq5 index d4cd9ac9..72d005b3 100644 --- a/mq5/MtApi5.mq5 +++ b/mq5/MtApi5.mq5 @@ -82,7 +82,7 @@ void OnTick() MqlRates rates_array[]; CopyRates(symbol, Period(), 1, 1, rates_array); - MtTimeBarEvent time_bar(symbol, rates_array[0]); + MtTimeBarEvent time_bar(symbol, (int)Period(), rates_array[0]); SendMtEvent(ON_LAST_TIME_BAR_EVENT, time_bar); } lastbar_time_changed = true; @@ -106,13 +106,13 @@ void OnTick() (BacktestingLockTicks == LOCK_EVERY_CANDLE && lastbar_time_changed)) { _is_ticks_locked = true; - + MtLockTickEvent lock_tick_event(symbol); SendMtEvent(ON_LOCK_TICKS_EVENT, lock_tick_event); } - - OnTimer(); } + + OnTimer(); } void OnTradeTransaction( @@ -446,29 +446,36 @@ int init() //--- Backtesting mode if (IsTesting()) - { + { Print("Waiting on remote client..."); //wait for command (BacktestingReady) from remote side to be ready for work while(!IsRemoteReadyForTesting) { executeCommand(); - + //This section uses a while loop to simulate Sleep() during Backtest. unsigned int viSleepUntilTick = GetTickCount() + 100; //100 milliseconds - while(GetTickCount() < viSleepUntilTick) + while(GetTickCount() < viSleepUntilTick) { //Do absolutely nothing. Just loop until the desired tick is reached. } } } - //--- + else + { + //--- Live trading: poll command queue via timer + EventSetMillisecondTimer(100); + } + //--- return (0); } -int deinit() +int deinit() { - if (isCrashed == 0) + EventKillTimer(); + + if (isCrashed == 0) { if (!deinitExpert(ExpertHandle, _error)) { @@ -2959,7 +2966,8 @@ string Execute_UnlockTicks() Print("WARNING: function UnlockTicks can be used only for backtesting"); return CreateErrorResponse(-1, "UnlockTicks can be used only for backtesting"); } - + + _is_ticks_locked = false; return CreateSuccessResponse(); } @@ -3073,9 +3081,9 @@ string Execute_iCustom() case 1: //Double { double doubleParams[]; + ArrayResize(doubleParams, size); for (int i = 0; i < size; i++) doubleParams[i] = jaParams.getDouble(i); - ArrayResize(doubleParams, size); result = iCustomT(symbol, (ENUM_TIMEFRAMES)timeframe, name, doubleParams, size); } break; @@ -3662,23 +3670,26 @@ private: class MtTimeBarEvent: public MtObject { public: - MtTimeBarEvent(string symbol, const MqlRates& rates) + MtTimeBarEvent(string symbol, int period, const MqlRates& rates) { _symbol = symbol; + _period = period; _rates = rates; } - + virtual JSONObject* CreateJson() const { JSONObject *jo = new JSONObject(); jo.put("Rates", MqlRatesToJson(_rates)); jo.put("Instrument", new JSONString(_symbol)); + jo.put("Period", new JSONNumber(_period)); jo.put("ExpertHandle", new JSONNumber(ExpertHandle)); return jo; } -private: +private: string _symbol; + int _period; MqlRates _rates; }; diff --git a/mq5/json.mqh b/mq5/json.mqh index 1236b878..d754e79b 100755 --- a/mq5/json.mqh +++ b/mq5/json.mqh @@ -171,11 +171,17 @@ public: } string getString() { return _string; } void setString(string v) { _string=v; } - string toString() + string toString() { - string string_var; - StringConcatenate(string_var, "\"",_string,"\""); - return string_var; + string escaped = _string; + StringReplace(escaped, "\\", "\\\\"); + StringReplace(escaped, "\"", "\\\""); + StringReplace(escaped, "\n", "\\n"); + StringReplace(escaped, "\r", "\\r"); + StringReplace(escaped, "\t", "\\t"); + string string_var; + StringConcatenate(string_var, "\"",escaped,"\""); + return string_var; } }; // ----------------------------------------- @@ -798,7 +804,7 @@ private: // number int i=_pos; - if(_in[_pos]=='-') + if(_in[_pos]=='-') { sign=-1; _pos++; @@ -809,6 +815,7 @@ private: sign=1; } + i=_pos; while(i<_len && isDigit(_in[i])) { l=l*10+(_in[i]-'0');