Issues with ExecuteMarketOrderAsync
Issues with ExecuteMarketOrderAsync
17 Jun 2019, 05:40
I see the entry points and stoplosses appear in cTrader.
However, in Visual Studio debugger, none of the lines after the while loop are executed.
The "OnTick" method never gets executed either -- I have a Visual Studio breakpoint on the opening curly brace of the method, and it's never hit.
Why is this?
So I thought maybe it's the way I have it coded.
Here is one way I coded the OnStart method:
protected override void OnStart() { //Place the long order TradeOperation toLong = ExecuteMarketOrderAsync(TradeType.Buy, Symbol, MaxPositionSize, _positionLabelLong, DefaultStopLossPips, null); //Place the short order TradeOperation toShort = ExecuteMarketOrderAsync(TradeType.Sell, Symbol, MaxPositionSize, _positionLabelShort, DefaultStopLossPips, null); //Wait for everything so we don't get to the OnTick method int whileLoopIndex = 0; while (toLong.IsExecuting && toShort.IsExecuting) { if (DebugLogMode && whileLoopIndex % 10 == 0) Print("While loop still waiting. _isLongEntrySuccessful {0}, _isShortEntrySuccessful {1}", _isLongEntrySuccessful, _isShortEntrySuccessful); Thread.Sleep(100); whileLoopIndex += 1; } //NOTHING from here down gets executed in VS debugger TradeResult r = toLong.TradeResult; Position p; if (r.IsSuccessful) { p = Positions.Find(_positionLabelLong, Symbol); _entryPriceLong = p.EntryPrice; _stopLossLongPrice = p.StopLoss.GetValueOrDefault(); _isLongEntrySuccessful = true; Print("Long order successful. Entry Price {0}, SL {1}", _entryPriceLong, _stopLossLongPrice); } else { Print("Error! Long entry NOT successful!"); }; r = toShort.TradeResult; if (r.IsSuccessful) { p = Positions.Find(_positionLabelShort, Symbol); _entryPriceShort = p.EntryPrice; _stopLossShortPrice = p.StopLoss.GetValueOrDefault(); _isShortEntrySuccessful = true; Print("Short order successful. Entry Price {0}, SL {1}", _entryPriceShort, _stopLossShortPrice); } else { Print("Error! Short entry NOT successful!"); }; }
I see the entry points and stoplosses appear in cTrader.
However, in Visual Studio debugger, none of the lines after the while loop are executed.
The "OnTick" method never gets executed either -- I have a Visual Studio breakpoint on the opening curly brace of the method, and it's never hit.
Why is this?
So I thought maybe it's the way I have it coded.
So then I tried the OnStart code to following:
protected override void OnStart() { //Place the long order ExecuteMarketOrderAsync(TradeType.Buy, Symbol, MaxPositionSize, _positionLabelLong, DefaultStopLossPips, null, (TradeResult r) => { if (r.IsSuccessful) { Position p = Positions.Find(_positionLabelLong, Symbol); _entryPriceLong = p.EntryPrice; _stopLossLongPrice = p.StopLoss.GetValueOrDefault(); _isLongEntrySuccessful = true; Print("Long order successful. Entry Price {0}, SL {1}", _entryPriceLong, _stopLossLongPrice); } else { Print("Error! Long entry NOT successful!"); }; }); //Place the short order ExecuteMarketOrderAsync(TradeType.Sell, Symbol, MaxPositionSize, _positionLabelShort, DefaultStopLossPips, null, (TradeResult r) => { if (r.IsSuccessful) { Position p = Positions.Find(_positionLabelShort, Symbol); _entryPriceShort = p.EntryPrice; _stopLossShortPrice = p.StopLoss.GetValueOrDefault(); _isShortEntrySuccessful = true; Print("Short order successful. Entry Price {0}, SL {1}", _entryPriceShort, _stopLossShortPrice); } else { Print("Error! Short entry NOT successful!"); }; }); int whileLoopIndex = 0; while (!_isLongEntrySuccessful && !_isShortEntrySuccessful) { if (DebugLogMode && whileLoopIndex % 10 == 0) Print("While loop still waiting. _isLongEntrySuccessful {0}, _isShortEntrySuccessful {1}", _isLongEntrySuccessful, _isShortEntrySuccessful); Thread.Sleep(100); whileLoopIndex += 1; } }
In this example, not only does the while-loop never exit, but if I place breakpoints on the "if (r.IsSuccessful)" lines in either Action that's supposed to execute after the order, they are never hit either.
However, in cTrader I again see the price entry points and the associated stoploss lines.
To compound the issue, again the "OnTick" method is never hit either.
Why is this?
What am I doing wrong or not understanding?
Thank you!
Replies
firemyst
19 Jun 2019, 02:48
RE:
Panagiotis Charalampous said:
Hi FireMyst,
Can you please share a complete cBot code that reproduces the issue?
Best Regards,
Panagiotis
Sorry. I should have known better and done so. :-)
I'll post two versions of the code below. Neither way works as expected.
@firemyst
firemyst
19 Jun 2019, 02:48
RE:
Panagiotis Charalampous said:
Hi FireMyst,
Can you please share a complete cBot code that reproduces the issue?
Best Regards,
Panagiotis
Sorry. I should have known better and done so. :-)
I'll post two versions of the code below. Neither way works as expected.
@firemyst
firemyst
19 Jun 2019, 02:55
Version 1
Here is Version 1 of the code. Run against 5 minute chart of EURUSD on Pepperstone using cTrader V3.3.
When running this code in debug mode, I have a break point on line 65:
TradeResult r = toLong.TradeResult;
which is never hit.
Also, line 99 in OnTick:
Print("-------------------- Starting OnTick --------------------");
never runs.
However, the orders are placed and I can adjust the stop losses on the cTrader chart.
The bot permissions has "full access" because I removed some code that reads/writes info to the local drive.
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading; using cAlgo.API; using cAlgo.API.Indicators; using cAlgo.API.Internals; using cAlgo.Indicators; using Microsoft.Win32; namespace cAlgo.Robots { [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)] public class Entrapment : Robot { //Specific to this robot [Parameter("Default Stop Loss (pips)", DefaultValue = 5, MinValue = 1)] public int DefaultStopLossPips { get; set; } [Parameter("Max Position Size (pips forex; units indicies)", DefaultValue = 1, MinValue = 0, Step = 1)] public double MaxPositionSize { get; set; } [Parameter("Use Trailing Stop Loss", DefaultValue = true)] public bool UseTrailingStopLoss { get; set; } [Parameter("Debug Log Mode", DefaultValue = false)] public bool DebugLogMode { get; set; } private string _positionLabelLong = string.Empty; private string _positionLabelShort = string.Empty; private double _stopLossLongPosition = 0; private double _stopLossShortPosition = 0; private double _entryPriceLong = 0; private double _entryPriceShort = 0; private double _stopLossLongPrice = 0; private double _stopLossShortPrice = 0; private bool _isLongEntrySuccessful = false; private bool _isShortEntrySuccessful = false; //for measuring the speed of methods private Stopwatch _sw = new Stopwatch(); protected override void OnStart() { //Start the robot. _positionLabelLong = SimplyfyTimeFrame(MarketSeries.TimeFrame) + " Long " + Symbol.Code + " DLEntrapment Bot"; _positionLabelShort = SimplyfyTimeFrame(MarketSeries.TimeFrame) + " Short " + Symbol.Code + " DLEntrapment Bot"; Print("OnStart: Starting DLEntrapment Bot."); //Place the long order TradeOperation toLong = ExecuteMarketOrderAsync(TradeType.Buy, Symbol, MaxPositionSize, _positionLabelLong, DefaultStopLossPips, null); //Place the short order TradeOperation toShort = ExecuteMarketOrderAsync(TradeType.Sell, Symbol, MaxPositionSize, _positionLabelShort, DefaultStopLossPips, null); //Wait for everything so we don't get to the OnTick method int whileLoopIndex = 0; while (toLong.IsExecuting && toShort.IsExecuting) { if (DebugLogMode && whileLoopIndex % 10 == 0) Print("While loop still waiting. "); Thread.Sleep(100); whileLoopIndex += 1; } TradeResult r = toLong.TradeResult; Position p; if (r.IsSuccessful) { p = Positions.Find(_positionLabelLong, Symbol); _entryPriceLong = p.EntryPrice; _stopLossLongPrice = p.StopLoss.GetValueOrDefault(); _isLongEntrySuccessful = true; Print("Long order successful. Entry Price {0}, SL {1}", _entryPriceLong, _stopLossLongPrice); } else { Print("Error! Long entry NOT successful!"); }; r = toShort.TradeResult; if (r.IsSuccessful) { p = Positions.Find(_positionLabelShort, Symbol); _entryPriceShort = p.EntryPrice; _stopLossShortPrice = p.StopLoss.GetValueOrDefault(); _isShortEntrySuccessful = true; Print("Short order successful. Entry Price {0}, SL {1}", _entryPriceShort, _stopLossShortPrice); } else { Print("Error! Short entry NOT successful!"); }; } protected override void OnTick() { _sw.Reset(); Print("-------------------- Starting OnTick --------------------"); _sw.Start(); if (_isLongEntrySuccessful && _isShortEntrySuccessful) { double symbolBid = Symbol.Bid; double symbolAsk = Symbol.Ask; //Checking long position. If bid gets higher than the short position SL, then it's moving up //Move long SL to entry price plus a pip and turn into TSL in case it takes off if (symbolBid >= _stopLossShortPosition) { Position p = Positions.Find(_positionLabelLong, Symbol); double newSL = _entryPriceLong + Symbol.PipSize; if (newSL >= symbolBid) newSL = _entryPriceLong; TradeResult r = ModifyPosition(p, newSL, null, UseTrailingStopLoss); if (r.IsSuccessful) { Print("OT01: Successfully modified position \"{0} {1}\". Entry Price {2}, Old SL {3}, New SL {4}, Has TSL {5}.", p.Id, p.Label, _entryPriceLong, _stopLossLongPrice, newSL, UseTrailingStopLoss); Stop(); return; } else { Print("OT01: WARNING! Could not modify position \"{0} {1}\"! SymbolBid {2}, SymbolAsk {3}, Entry Price {4}, Old SL {5}, New SL {6}, Has TSL {7}.", p.Id, p.Label, symbolBid, symbolAsk, _entryPriceLong, _stopLossLongPrice, newSL, UseTrailingStopLoss); } } //Checking short position. If bid gets lower than the long position SL, then it's moving down //Move short SL to entry price plus a pip and turn into TSL in case it takes off else if (symbolAsk <= _stopLossLongPosition) { Position p = Positions.Find(_positionLabelShort, Symbol); double newSL = _entryPriceShort - Symbol.PipSize; if (newSL <= symbolAsk) newSL = _entryPriceShort; TradeResult r = ModifyPosition(p, newSL, null, UseTrailingStopLoss); if (r.IsSuccessful) { Print("OT02: Successfully modified position \"{0} {1}\". Entry Price {2}, Old SL {3}, New SL {4}, Has TSL {5}.", p.Id, p.Label, _entryPriceShort, _stopLossShortPrice, newSL, UseTrailingStopLoss); Stop(); return; } else { Print("OT02: WARNING! Could not modify position \"{0} {1}\"! SymbolBid {2}, SymbolAsk {3}, Entry Price {4}, Old SL {5}, New SL {6}, Has TSL {7}.", p.Id, p.Label, symbolBid, symbolAsk, _entryPriceLong, _stopLossLongPrice, newSL, UseTrailingStopLoss); } } else { if (DebugLogMode) Print("OT03: No conditions met to move SL for either long or short position."); } } else { if (DebugLogMode) Print("OT04: Waiting for Long and Short orders to be successful. _isLongEntrySuccessful {0}, _isShortEntrySuccessful {1}", _isLongEntrySuccessful, _isShortEntrySuccessful); } _sw.Stop(); Print("-------------------- End OnTick {0} --------------------", _sw.Elapsed.ToString("ss\\.fffffff")); } protected override void OnStop() { // Put your deinitialization logic here } /// <summary> /// Created to replace the long winded time frames with simplified versions more common on charts. /// Ex: "Hour" -> "H1"; "Minute5" ->"M5", etc /// </summary> /// <param name="tf">The TimeFrame period</param> /// <returns>Simplified string. "Hour" -> "H1"; "Minute5" -> "M5", etc</returns> private string SimplyfyTimeFrame(TimeFrame tf) { if (tf == TimeFrame.Hour) return "H1"; if (tf == TimeFrame.Minute) return "M1"; if (tf == TimeFrame.Daily) return "D1"; if (tf == TimeFrame.Weekly) return "W1"; if (tf.ToString().Contains("Hour")) return tf.ToString().Replace("Hour", "H"); if (tf.ToString().Contains("Minute")) return tf.ToString().Replace("Minute", "M"); if (tf.ToString().Contains("Day")) return tf.ToString().Replace("Day", "D"); return tf.ToString(); } } }
@firemyst
firemyst
19 Jun 2019, 03:06
Version 2
Here's version 2 of the code. Run with same environment as stated above and same results. Orders placed, I can adjust stop losses on chart. However, the Print statement in OnTick:
Print("-------------------- Starting OnTick --------------------");
is never printed nor hit in the debugger.
A breakpoint I have on line 53:
if (r.IsSuccessful)
is never hit. As a result, the While loop never exits because the bool variables are never set to true, which they should be since the position is opened and should provide a TradeResult.
using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading; using cAlgo.API; using cAlgo.API.Indicators; using cAlgo.API.Internals; using cAlgo.Indicators; using Microsoft.Win32; namespace cAlgo.Robots { [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)] public class Entrapment : Robot { //Specific to this robot [Parameter("Default Stop Loss (pips)", DefaultValue = 5, MinValue = 1)] public int DefaultStopLossPips { get; set; } [Parameter("Max Position Size (pips forex; units indicies)", DefaultValue = 1, MinValue = 0, Step = 1)] public double MaxPositionSize { get; set; } [Parameter("Use Trailing Stop Loss", DefaultValue = true)] public bool UseTrailingStopLoss { get; set; } [Parameter("Debug Log Mode", DefaultValue = true)] public bool DebugLogMode { get; set; } private string _positionLabelLong = string.Empty; private string _positionLabelShort = string.Empty; private double _stopLossLongPosition = 0; private double _stopLossShortPosition = 0; private double _entryPriceLong = 0; private double _entryPriceShort = 0; private double _stopLossLongPrice = 0; private double _stopLossShortPrice = 0; private bool _isLongEntrySuccessful = false; private bool _isShortEntrySuccessful = false; //for measuring the speed of methods private Stopwatch _sw = new Stopwatch(); protected override void OnStart() { //Start the robot. _positionLabelLong = SimplyfyTimeFrame(MarketSeries.TimeFrame) + " Long " + Symbol.Code + " DLEntrapment Bot"; _positionLabelShort = SimplyfyTimeFrame(MarketSeries.TimeFrame) + " Short " + Symbol.Code + " DLEntrapment Bot"; Print("OnStart: Starting DLEntrapment Bot."); //Place the long order ExecuteMarketOrderAsync(TradeType.Buy, Symbol, MaxPositionSize, _positionLabelLong, DefaultStopLossPips, null, (TradeResult r) => { if (r.IsSuccessful) { Position p = Positions.Find(_positionLabelLong, Symbol); _entryPriceLong = p.EntryPrice; _stopLossLongPrice = p.StopLoss.GetValueOrDefault(); //Set last so the while blocking loop won't complete until all variables are assigned _isLongEntrySuccessful = true; Print("Long order successful. Entry Price {0}, SL {1}", _entryPriceLong, _stopLossLongPrice); } else { Print("Error! Long entry NOT successful!"); }; }); //Place the short order ExecuteMarketOrderAsync(TradeType.Sell, Symbol, MaxPositionSize, _positionLabelShort, DefaultStopLossPips, null, (TradeResult r) => { if (r.IsSuccessful) { Position p = Positions.Find(_positionLabelShort, Symbol); _entryPriceShort = p.EntryPrice; _stopLossShortPrice = p.StopLoss.GetValueOrDefault(); //Set last so the while blocking loop won't complete until all variables are assigned _isShortEntrySuccessful = true; Print("Short order successful. Entry Price {0}, SL {1}", _entryPriceShort, _stopLossShortPrice); } else { Print("Error! Short entry NOT successful!"); }; }); //Wait for everything so we don't get to the OnTick method int whileLoopIndex = 0; while (!_isLongEntrySuccessful && !_isShortEntrySuccessful) { if (DebugLogMode && whileLoopIndex % 10 == 0) Print("While loop still waiting. _isLongEntrySuccessful {0}, _isShortEntrySuccessful {1}", _isLongEntrySuccessful, _isShortEntrySuccessful); Thread.Sleep(100); whileLoopIndex += 1; } } protected override void OnTick() { _sw.Reset(); Print("-------------------- Starting OnTick --------------------"); _sw.Start(); if (_isLongEntrySuccessful && _isShortEntrySuccessful) { double symbolBid = Symbol.Bid; double symbolAsk = Symbol.Ask; //Checking long position. If bid gets higher than the short position SL, then it's moving up //Move long SL to entry price plus a pip and turn into TSL in case it takes off if (symbolBid >= _stopLossShortPosition) { Position p = Positions.Find(_positionLabelLong, Symbol); double newSL = _entryPriceLong + Symbol.PipSize; if (newSL >= symbolBid) newSL = _entryPriceLong; TradeResult r = ModifyPosition(p, newSL, null, UseTrailingStopLoss); if (r.IsSuccessful) { Print("OT01: Successfully modified position \"{0} {1}\". Entry Price {2}, Old SL {3}, New SL {4}, Has TSL {5}.", p.Id, p.Label, _entryPriceLong, _stopLossLongPrice, newSL, UseTrailingStopLoss); Stop(); return; } else { Print("OT01: WARNING! Could not modify position \"{0} {1}\"! SymbolBid {2}, SymbolAsk {3}, Entry Price {4}, Old SL {5}, New SL {6}, Has TSL {7}.", p.Id, p.Label, symbolBid, symbolAsk, _entryPriceLong, _stopLossLongPrice, newSL, UseTrailingStopLoss); } } //Checking short position. If bid gets lower than the long position SL, then it's moving down //Move short SL to entry price plus a pip and turn into TSL in case it takes off else if (symbolAsk <= _stopLossLongPosition) { Position p = Positions.Find(_positionLabelShort, Symbol); double newSL = _entryPriceShort - Symbol.PipSize; if (newSL <= symbolAsk) newSL = _entryPriceShort; TradeResult r = ModifyPosition(p, newSL, null, UseTrailingStopLoss); if (r.IsSuccessful) { Print("OT02: Successfully modified position \"{0} {1}\". Entry Price {2}, Old SL {3}, New SL {4}, Has TSL {5}.", p.Id, p.Label, _entryPriceShort, _stopLossShortPrice, newSL, UseTrailingStopLoss); Stop(); return; } else { Print("OT02: WARNING! Could not modify position \"{0} {1}\"! SymbolBid {2}, SymbolAsk {3}, Entry Price {4}, Old SL {5}, New SL {6}, Has TSL {7}.", p.Id, p.Label, symbolBid, symbolAsk, _entryPriceLong, _stopLossLongPrice, newSL, UseTrailingStopLoss); } } else { if (DebugLogMode) Print("OT03: No conditions met to move SL for either long or short position."); } } else { if (DebugLogMode) Print("OT04: Waiting for Long and Short orders to be successful. _isLongEntrySuccessful {0}, _isShortEntrySuccessful {1}", _isLongEntrySuccessful, _isShortEntrySuccessful); } _sw.Stop(); Print("-------------------- End OnTick {0} --------------------", _sw.Elapsed.ToString("ss\\.fffffff")); } protected override void OnStop() { // Put your deinitialization logic here } /// <summary> /// Created to replace the long winded time frames with simplified versions more common on charts. /// Ex: "Hour" -> "H1"; "Minute5" ->"M5", etc /// </summary> /// <param name="tf">The TimeFrame period</param> /// <returns>Simplified string. "Hour" -> "H1"; "Minute5" -> "M5", etc</returns> private string SimplyfyTimeFrame(TimeFrame tf) { if (tf == TimeFrame.Hour) return "H1"; if (tf == TimeFrame.Minute) return "M1"; if (tf == TimeFrame.Daily) return "D1"; if (tf == TimeFrame.Weekly) return "W1"; if (tf.ToString().Contains("Hour")) return tf.ToString().Replace("Hour", "H"); if (tf.ToString().Contains("Minute")) return tf.ToString().Replace("Minute", "M"); if (tf.ToString().Contains("Day")) return tf.ToString().Replace("Day", "D"); return tf.ToString(); } } }
@firemyst
PanagiotisCharalampous
19 Jun 2019, 10:49
Hi FireMyst,
The problem is with the while loops. They block the execution of the thread. If you want to execute operations after a successful position opening I suggess to use the asynchronous callback event raised by this function.
Best Regards,
Panagiotis
@PanagiotisCharalampous
firemyst
19 Jun 2019, 10:53
RE:
Panagiotis Charalampous said:
Hi FireMyst,
The problem is with the while loops. They block the execution of the thread. If you want to execute operations after a successful position opening I suggess to use the asynchronous callback event raised by this function.
Best Regards,
Panagiotis
HI @Panagiotis
I tried that in example #2. As per what I stated there, the callback Action even never gets called, so I'm confused.
Those callback events should set the boolean variables, which allow the While loop to exit. Otherwise, what's the suggested approach to ensure no other code gets executed until both callback events have completed?
Thank you.
@firemyst
PanagiotisCharalampous
19 Jun 2019, 11:04
Hi FireMyst,
You have a while loop on example 2 as well. This is why the callback action is not called. The while loop blocks the execution. Since you have flags in the callback actions, why do you need that loop?
Best Regards,
Panagiotis
@PanagiotisCharalampous
firemyst
19 Jun 2019, 11:07
RE:
Panagiotis Charalampous said:
Hi FireMyst,
The problem is with the while loops. They block the execution of the thread. If you want to execute operations after a successful position opening I suggess to use the asynchronous callback event raised by this function.
Best Regards,
Panagiotis
Also, even more confusing, in the first example, the while loop runs until both async callbacks return a non "InExecuting" value. See this line:
while (toLong.IsExecuting && toShort.IsExecuting)
While running in debug mode, both async callbacks complete, because the positions are opened with the stoplosses on the chart, so at least one of those values should be set to false, and thus while loop should exit.
Am I wrong?
@firemyst
firemyst
19 Jun 2019, 11:07
RE:
Panagiotis Charalampous said:
Hi FireMyst,
The problem is with the while loops. They block the execution of the thread. If you want to execute operations after a successful position opening I suggess to use the asynchronous callback event raised by this function.
Best Regards,
Panagiotis
Also, even more confusing, in the first example, the while loop runs until both async callbacks return a non "InExecuting" value. See this line:
while (toLong.IsExecuting && toShort.IsExecuting)
While running in debug mode, both async callbacks complete, because the positions are opened with the stoplosses on the chart, so at least one of those values should be set to false, and thus while loop should exit.
Am I wrong?
@firemyst
PanagiotisCharalampous
19 Jun 2019, 11:13
Hi Firemyst,
It's simple. It is a sequential single threaded execution. If the while loop is reached before the callbacks are executed or the IsExecuting is set to true then you will have a deadlock. As long as the while loop is executed, nothing else can be executed until the loop is finished. So if the code enters that loop there is no way out. As is the loop is actually useless.
Best Regards,
Panagiotis
@PanagiotisCharalampous
firemyst
19 Jun 2019, 11:31
RE:
Panagiotis Charalampous said:
Hi FireMyst,
You have a while loop on example 2 as well. This is why the callback action is not called. The while loop blocks the execution. Since you have flags in the callback actions, why do you need that loop?
Best Regards,
Panagiotis
Given my limited programming experience, maybe I'm wrong here, but when an async method is called, the callback is async as well, no? It has to be given that the system never knows when the async operation is going to finish.
The reason I have the while loop is I don't want any other code to execute until both callback actions have completed.
@firemyst
firemyst
19 Jun 2019, 11:35
RE:
Panagiotis Charalampous said:
Hi Firemyst,
It's simple. It is a sequential single threaded execution. If the while loop is reached before the callbacks are executed or the IsExecuting is set to true then you will have a deadlock. As long as the while loop is executed, nothing else can be executed until the loop is finished. So if the code enters that loop there is no way out. As is the loop is actually useless.
Best Regards,
Panagiotis
Ok. Thank you for that clarification.
I guess what that means then is I'll have to move the boolean flags into the beginning of the "OnTick" method, and only execute code there when both results are returned.
Eg, remove the while loop as you suggested and keep the following:
protected override void OnTick() { if (_isLongEntrySuccessful && _isShortEntrySuccessful) { : : : } }
Thank you Panagiotis.
@firemyst
PanagiotisCharalampous
19 Jun 2019, 11:40
Hi FireMyst,
It is async, meaning that it will be executed at a later point of time, when the event is received. It is not multi-threaded thought, it is still a single thread running and when the event is received, the handler will wait for its turn to be executed. So if the while loop is blocking the thread, then no events can be received and no handlers can executed.
You say
I have the while loop is I don't want any other code to execute until both callback actions have completed.
and indeed this is what happens. No other code is execured, including callback actions, therefore you are stuck there forever :).
Best Regards,
Panagiotis
@PanagiotisCharalampous
PanagiotisCharalampous
18 Jun 2019, 12:45
Hi FireMyst,
Can you please share a complete cBot code that reproduces the issue?
Best Regards,
Panagiotis
@PanagiotisCharalampous