Topics
Replies
firemyst
12 Mar 2025, 11:59
RE: RE: RE: RE: RE: RE: RE: RE: RE: RE: Help needed with Asynchronous Close of positions
kadronsa said:
Thanks for confirming my suspicions, as I knew I had to introduce some kind of delay after the async command but didn't know how to do it for the cBot. I've resolved this in MQL by “sleeping” a little while but when I replicate it here the sleep command doesn't work the same. I'll try your suggestion of the flag now that I'm sure what to look for. Thanks again.
I posted sample code to help get you started in case you haven't seen it yet.
@firemyst
firemyst
12 Mar 2025, 11:50
RE: RE: RE: RE: RE: RE: RE: RE: Help needed with Asynchronous Close of positions
Here's sample code you can run which avoids the issue. It's not perfect since I'm not in front of a compiler, but should work:
bool closingPositions;
int positionsClosed = 0;
protected override void OnStart()
{
ExecuteMarketOrder(TradeType.Buy, SymbolName, 1000);
ExecuteMarketOrder(TradeType.Sell, SymbolName, 1000);
ExecuteMarketOrder(TradeType.Buy, SymbolName, 1000);
ExecuteMarketOrder(TradeType.Sell, SymbolName, 1000);
ExecuteMarketOrder(TradeType.Buy, SymbolName, 1000);
ExecuteMarketOrder(TradeType.Sell, SymbolName, 1000);
closingPositions = false;
positionsClosed = 0;
}
protected override void OnTick()
{
if (!closingPositions)
{
CheckOpenOrders();
BasketControl();
}
}
protected override void OnStop()
{
CloseAll();
}
protected void CheckOpenOrders()
{
BuyLots = 0;
SellLots = 0;
MyTrades = 0;
foreach (var position in Positions)
{
if (position.SymbolName == Symbol.Name)
{
MyTrades++;
if (position.TradeType == TradeType.Buy)
{
BuyLots += position.VolumeInUnits;
}
if (position.TradeType == TradeType.Sell)
{
SellLots += position.VolumeInUnits;
}
}
}
}
protected void BasketControl()
{
if (MyTrades > 5)
CloseAll();
}
protected void CloseAll()
{
double BookedProfit = 0;
var positionsCOLLECTED = Positions.ToArray();
closingPositions = true;
foreach (var psnsCLTD in positionsCOLLECTED.Where(p => p.SymbolName == SymbolName))
{
double ClosedP = psnsCLTD.NetProfit;
ClosePositionAsync(psnsCLTD, (TradeResult r) =>
{
if (r.IsSuccessful)
{
BookedProfit += ClosedP;
positionsClosed += 1;
}
else if (!r.IsSuccessful)
Print(" >> Failed to close Order! Encountered Error - ", r.Error);
if (positionsClosed == positionsCOLLECTED.Length)
{
closingPositions = false;
positionsClosed = 0;
}
}
);
}
}
@firemyst
firemyst
12 Mar 2025, 11:40
( Updated at: 12 Mar 2025, 11:43 )
RE: RE: RE: RE: RE: RE: RE: RE: Help needed with Asynchronous Close of positions
I don't have to try your code. I can see right away you're doing what I said you would be doing, and you shouldn't be doing it.
You're running code in the OnTick event handler that still access the Positions object while you're in the process of closing the positions async. What makes you think all the positions are going to be closed by the time the next tick comes in?
In your OnTick you call CheckOpenOrders, which loops over the Positions.
So the code hits that loop, and is iterating over the objects, when suddenly some of the position objects have finally been closed by the server async. Thus, in the middle of the foreach loop, it expects to have positions it started iterating over, but they are no longer there, hence your errors.
So as I said in a previous response, you need to set a flag to indicate when you are closing positions. while the flag is true, you DO NOT iterate over the foreach loop (and any other part of code) that operates on the “Positions” object.
When all the positions have been closed async (which could take multiple ticks), then you set the “closingPositions” flag back to false, and now the bot can iterate your code as usual.
@firemyst
firemyst
12 Mar 2025, 05:52
RE: RE: RE: RE: RE: RE: Help needed with Asynchronous Close of positions
The same code I provided you doesn't throw “EntityNotFound” errors when I just ran it.
Are you able to modify the sample code I gave you to reproduce the issue?
I use ClosePositionAsync in all my bots and haven't had any problems.
@firemyst
firemyst
12 Mar 2025, 02:29
RE: RE: RE: RE: Help needed with Asynchronous Close of positions
kadronsa said:
firemyst said:
kadronsa said:
firemyst said:
Why are you using “LastResult.Error” and not “closeResult.Error” in the “BulkOrderClose” method?
No particular reason. I just reused what I had working before trying out Async close. I have however modified the closing code and replaced “lastresult.error” with the following code but the problem still persists:
protected void CloseMyTrades() { var positionsCOLLECTED = Positions.ToArray(); foreach (var psnsCLTD in positionsCOLLECTED.Where(p => p.SymbolName == SymbolName)) { ClosePositionAsync(psnsCLTD, (TradeResult r) => { if (r.IsSuccessful) BookedProfit += psnsCLTD.NetProfit; else if (!r.IsSuccessful) Print(" >> Failed to close " + psnsCLTD.TradeType + " Order! Encountered Error - ", r.Error); } ); } }
I still get the following in the output after successfully closing all trades:
11-03-2025 06:39:05.624 | Trade | → Closing position PID665350 (Volume: 18) SUCCEEDED 11-03-2025 06:39:05.702 | Trade | → Closing position PID665351 (Volume: 54) SUCCEEDED 11-03-2025 06:39:05.796 | Trade | → Closing position PID665352 (Volume: 90) SUCCEEDED 11-03-2025 06:39:05.889 | Trade | → Closing position PID665353 (Volume: 126) SUCCEEDED 11-03-2025 06:39:05.983 | Trade | → Closing position PID665350 (Volume: 18) FAILED with error "EntityNotFound" 11-03-2025 06:39:05.983 | Trade | → Closing position PID665351 (Volume: 54) FAILED with error "EntityNotFound" 11-03-2025 06:39:05.983 | Trade | → Closing position PID665352 (Volume: 90) FAILED with error "EntityNotFound" 11-03-2025 06:39:05.983 | Trade | → Closing position PID665353 (Volume: 126) FAILED with error "EntityNotFound" 11-03-2025 06:39:05.983 | Trade | → Closing position PID665350 (Volume: 18) FAILED with error "EntityNotFound" 11-03-2025 06:39:05.983 | Trade | → Closing position PID665351 (Volume: 54) FAILED with error "EntityNotFound" 11-03-2025 06:39:05.983 | Trade | → Closing position PID665352 (Volume: 90) FAILED with error "EntityNotFound" 11-03-2025 06:39:05.983 | Trade | → Closing position PID665353 (Volume: 126) FAILED with error "EntityNotFound" 11-03-2025 06:39:05.983 | Trade | → Closing position PID665350 (Volume: 18) FAILED with error "EntityNotFound" 11-03-2025 06:39:05.983 | Trade | → Closing position PID665351 (Volume: 54) FAILED with error "EntityNotFound" 11-03-2025 06:39:05.983 | Trade | → Closing position PID665352 (Volume: 90) FAILED with error "EntityNotFound" 11-03-2025 06:39:05.983 | Trade | → Closing position PID665353 (Volume: 126) FAILED with error "EntityNotFound"
What am I missing?
Thanks.
You're trying to read the profit of a closed position:
BookedProfit += psnsCLTD.NetProfit;
How can you read the profit of a position that no longer exists?
Thanks for pointing that out, but it doesn't seem to be the root cause for the error. I've modified code accordingly but still get the “EntityNotFound” errors:
protected void CloseMyTrades() { var positionsCOLLECTED = Positions.ToArray(); foreach (var psnsCLTD in positionsCOLLECTED.Where(p => p.SymbolName == SymbolName)) { double ClosedP = psnsCLTD.NetProfit; ClosePositionAsync(psnsCLTD, (TradeResult r) => { if (r.IsSuccessful) BookedProfit += ClosedP; else if (!r.IsSuccessful) Print(" >> Failed to close Order! Encountered Error - ", r.Error); } ); } }
There's nothing wrong with that code as is unless “BookedProfit” isn't a double.
You haven't posted your entire code, so I suspect you have an event listener or something else happening elsewhere. If you want proof of this, create a test bot and just put in the code I have below.
For instance, in your “OnTick” or “OnBar” methods, do you actually check if the position exists before doing anything?
After all, when you tell the system to close the position async, the position might still be open when the next tick comes through, and your bot will then try to perform operations on it. But then the position gets closed halfway through, and it can no longer be found. Closing a position async doesn't guarantee an immediate close, or closure before the method exits.
//create a new bot. And just add these two methods. I bet you'll see your closing code works fine.
protected override void OnStart()
{
ExecuteMarketOrder(TradeType.Buy, SymbolName, 1000);
ExecuteMarketOrder(TradeType.Sell, SymbolName, 1000);
}
protected override void OnStop()
{
double BookedProfit = 0;
var positionsCOLLECTED = Positions.ToArray();
foreach (var psnsCLTD in positionsCOLLECTED.Where(p => p.SymbolName == SymbolName))
{
double ClosedP = psnsCLTD.NetProfit;
ClosePositionAsync(psnsCLTD, (TradeResult r) =>
{
if (r.IsSuccessful)
BookedProfit += ClosedP;
else if (!r.IsSuccessful)
Print(" >> Failed to close Order! Encountered Error - ", r.Error);
}
);
}
}
//When the above works fine for you too, that's evidence you are still trying to do things elsewhere in code you haven't shared that's operating on positions as you're closing them off.
@firemyst
firemyst
11 Mar 2025, 13:20
RE: RE: Help needed with Asynchronous Close of positions
kadronsa said:
firemyst said:
Why are you using “LastResult.Error” and not “closeResult.Error” in the “BulkOrderClose” method?
No particular reason. I just reused what I had working before trying out Async close. I have however modified the closing code and replaced “lastresult.error” with the following code but the problem still persists:
protected void CloseMyTrades() { var positionsCOLLECTED = Positions.ToArray(); foreach (var psnsCLTD in positionsCOLLECTED.Where(p => p.SymbolName == SymbolName)) { ClosePositionAsync(psnsCLTD, (TradeResult r) => { if (r.IsSuccessful) BookedProfit += psnsCLTD.NetProfit; else if (!r.IsSuccessful) Print(" >> Failed to close " + psnsCLTD.TradeType + " Order! Encountered Error - ", r.Error); } ); } }
I still get the following in the output after successfully closing all trades:
11-03-2025 06:39:05.624 | Trade | → Closing position PID665350 (Volume: 18) SUCCEEDED 11-03-2025 06:39:05.702 | Trade | → Closing position PID665351 (Volume: 54) SUCCEEDED 11-03-2025 06:39:05.796 | Trade | → Closing position PID665352 (Volume: 90) SUCCEEDED 11-03-2025 06:39:05.889 | Trade | → Closing position PID665353 (Volume: 126) SUCCEEDED 11-03-2025 06:39:05.983 | Trade | → Closing position PID665350 (Volume: 18) FAILED with error "EntityNotFound" 11-03-2025 06:39:05.983 | Trade | → Closing position PID665351 (Volume: 54) FAILED with error "EntityNotFound" 11-03-2025 06:39:05.983 | Trade | → Closing position PID665352 (Volume: 90) FAILED with error "EntityNotFound" 11-03-2025 06:39:05.983 | Trade | → Closing position PID665353 (Volume: 126) FAILED with error "EntityNotFound" 11-03-2025 06:39:05.983 | Trade | → Closing position PID665350 (Volume: 18) FAILED with error "EntityNotFound" 11-03-2025 06:39:05.983 | Trade | → Closing position PID665351 (Volume: 54) FAILED with error "EntityNotFound" 11-03-2025 06:39:05.983 | Trade | → Closing position PID665352 (Volume: 90) FAILED with error "EntityNotFound" 11-03-2025 06:39:05.983 | Trade | → Closing position PID665353 (Volume: 126) FAILED with error "EntityNotFound" 11-03-2025 06:39:05.983 | Trade | → Closing position PID665350 (Volume: 18) FAILED with error "EntityNotFound" 11-03-2025 06:39:05.983 | Trade | → Closing position PID665351 (Volume: 54) FAILED with error "EntityNotFound" 11-03-2025 06:39:05.983 | Trade | → Closing position PID665352 (Volume: 90) FAILED with error "EntityNotFound" 11-03-2025 06:39:05.983 | Trade | → Closing position PID665353 (Volume: 126) FAILED with error "EntityNotFound"
What am I missing?
Thanks.
You're trying to read the profit of a closed position:
BookedProfit += psnsCLTD.NetProfit;
How can you read the profit of a position that no longer exists?
@firemyst
firemyst
11 Mar 2025, 01:31
You have what appears to be quite a few logic errors in your code.
The first is the obvious:
position.ModifyStopLossPips(newStopLossPrice);
You're calling the method that expects “pips” as a parameter, and you're passing in a “price”.
Second is within the loop:
if (distance < TrailingStopTrigger * Symbol.PipSize)
continue;
Do you mean “break;” and not “continue;” ?
If not, what's the point of having the statement since the code logic will allow it to continue anyway regardless if the statement is true or not?
@firemyst
firemyst
11 Mar 2025, 00:49
RE: RE: RE: RE: RE: RE: RE: Stop Loss/ Take Profit being set at wrong distance by algo
thanks for sharing your code.
For starters, you have “ExecuteMarketOrder” in 3 places, so you need to put those print statements in the 3 places.
You might want to add a 3rd print statement that indicates which branch of code it's printing. For example:
Print ("Hello from area 1");
Be sure to adjust their output to how you calculate the SL and TP in each location.
For instance, in one place, you have:
Symbol.Bid + TakeProfitInPips * Symbol.PipSize;
and in another:
Symbol.Ask - TakeProfitInPips * Symbol.PipSize;
@firemyst
firemyst
13 Mar 2025, 07:16
You probably have to contact the developer(s). They can build the algo files to include or not include the source code with their distributions.
@firemyst