Closing one position seems to close them all with same Symbol
Closing one position seems to close them all with same Symbol
01 Nov 2019, 10:15
I've encountered an issue with cTrader where closing a position with a specific label seems to close all positions.
Example code below which reproduces the issue.
Why is every position closed when we explicitly look for positions with the specific label and trade type?
using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.IO; using System.Linq; using System.Net; using System.Runtime.InteropServices; using System.Text; using System.Text.RegularExpressions; using System.Threading; using System.Threading.Tasks; using System.Timers; using cAlgo.API; using cAlgo.API.Indicators; using cAlgo.API.Internals; using cAlgo.Indicators; /// <summary> /// Add 2 instances of this bot in cTrader with the Ger30 symbol. Put both instances in the M1 time frame. /// In one instance, select "Sell" for the parameter; for the other instance, select "Buy". /// Start both instances. /// Look at the log. Two different position labels. /// Now in the TradeWatch window, click the close "X" button next to the bottom-most listed position. /// Both positions get closed! /// This is NOT expected behaviour since we only close one position and expecially search for historical trades on the specific trade type and label. /// </summary> namespace cAlgo.Robots { [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)] public class BugBot : Robot { [Parameter("Trade Type", Group = "Trade Settings", DefaultValue = TradeType.Sell)] public TradeType TradeTypeForBot { get; set; } private string _positionLabel = "Bug bot"; protected override void OnStart() { Positions.Closed += Positions_Closed; _positionLabel += TradeTypeForBot; Print("OnStart: Starting \"{0}\"", _positionLabel); TradeResult r = ExecuteMarketOrder(TradeTypeForBot, Symbol.Name, 0.1, _positionLabel, 10, null, null, false); } /// <summary> /// Runs when a position is closed. /// </summary> /// <param name="args"></param> private void Positions_Closed(PositionClosedEventArgs args) { Position p1 = args.Position; //Search for the specific label and trade type of this position so we don't close similar ones. HistoricalTrade ht = History.FindLast(p1.Label, Symbol.Name, p1.TradeType); if (!String.IsNullOrEmpty(p1.Label) && ht != null) { double cp = ht.ClosingPrice; Print("Closed: Position \"{0} {1}\" closed for reason {2} with {3} profit. Entry Price {4}, Closing Price {5}, StopLoss {6}", p1.Id, p1.Label, args.Reason, String.Format("{0:$#,###.00}", p1.GrossProfit), p1.EntryPrice, cp, p1.StopLoss); //Close off all open positions. //Make sure to only close those positions for the current Label/Symbol. foreach (Position p in Positions.FindAll(_positionLabel, Symbol.Name)) { ClosePositionAsync(p, (TradeResult r) => { if (r.IsSuccessful) { Print("Closed: Closed position \"{0} {1}\".", p.Id, p.Label); } else if (!r.IsSuccessful) { Print("Closed: ### WARNING! Could not close position \"{0} {1}\"!", p.Id, p.Label); Print("Closed: Error message: {0}", r.Error.Value); } }); } Stop(); return; } } } }
.
Replies
firemyst
01 Nov 2019, 14:14
RE:
Panagiotis Charalampous said:
Hi FireMyst,
You should add a condition in Positions_Closed to be executed only when the closed position has the same same label as _positionLabel. Else the method will be executed when positions from other instances are closed, eventually closing all positions of the account.
Best Regards,
Panagiotis
Hi @Panagiotis:
I do that don't I?
Line 56.
I only get the historical position that has the same label, symbol, and tradetype as the position that was closed.
I then check to make sure it's found (eg, the historical trade isn't null).
The next if statement on line #58 will only evaluate to true if the exact matching historical trade is found.
So to me it looks like it's finding everything under the symbol, regardless of the label. Otherwise, HT would be null.
?
@firemyst
PanagiotisCharalampous
01 Nov 2019, 14:45
Hi FireMyst,
You do not check anywhere if the closed position was actually created by this instance. So if it has been created by another instance on the same symbol then the positions of this instance will be closed as well.
Best Regards,
Panagiotis
@PanagiotisCharalampous
firemyst
01 Nov 2019, 15:48
RE:
Panagiotis Charalampous said:
Hi FireMyst,
You do not check anywhere if the closed position was actually created by this instance. So if it has been created by another instance on the same symbol then the positions of this instance will be closed as well.
Best Regards,
Panagiotis
Thanks!
I found the bug thanks to your feedback. I had to change the foreach loop to the following, replacing _positionLabel with p1.Label:
foreach (Position p in Positions.FindAll(p1.Label, Symbol.Name)) { /... }
@firemyst
PanagiotisCharalampous
01 Nov 2019, 15:54
Hi FireMyst,
Indeed that solves the issue but in a weird way :) What I would have done would be to exit the method if the closed position was not created by this instance. See below
private void Positions_Closed(PositionClosedEventArgs args) { Position p1 = args.Position; if(p1.Label != _positionLabel) return;
Best Regards,
Panagiotis
@PanagiotisCharalampous
firemyst
01 Nov 2019, 16:03
RE:
Panagiotis Charalampous said:
Hi FireMyst,
Indeed that solves the issue but in a weird way :) What I would havedone would be to exit the method if the closed position was not created by this instance. See below
private void Positions_Closed(PositionClosedEventArgs args) { Position p1 = args.Position; if(p1.Label != _positionLabel) return;Best Regards,
Panagiotis
Nice one. I like it. I'm going to use it. Thanks! :-)
@firemyst
J.Lo
22 Oct 2024, 19:47
( Updated at: 22 Oct 2024, 20:03 )
position_closed looping for all bot instances
Still happening in 2024. i have multiple instances running. when a position closes and the position_closed event fires, it triggers this method for all instances (although it does just close the actual trade)
I can tell because i receive the SMS's *freaked me out
In fact, i noticed this behaviour in Positions_Modified and Positions_Opened aswell
My fix
private void Positions_Closed(PositionClosedEventArgs obj){ //step: weird bug - do not fire for symbols that are not the same - picked this up in my sms's if(obj.Position.Symbol.Name.ToUpper() != Symbol.Name.ToUpper()) return;
@J.Lo
firemyst
23 Oct 2024, 00:39
( Updated at: 23 Oct 2024, 04:59 )
RE: position_closed looping for all bot instances
J.Lo said:
Still happening in 2024. i have multiple instances running. when a position closes and the position_closed event fires, it triggers this method for all instances (although it does just close the actual trade)
I can tell because i receive the SMS's *freaked me out
In fact, i noticed this behaviour in Positions_Modified and Positions_Opened aswell
My fix
private void Positions_Closed(PositionClosedEventArgs obj){ //step: weird bug - do not fire for symbols that are not the same - picked this up in my sms's if(obj.Position.Symbol.Name.ToUpper() != Symbol.Name.ToUpper()) return;
It appears this is intended behavior because of the way the event is wired. It's wired this way because it's on the “Positions” collection, not the individual “Position”. The “positions” is all the positions, not just a singular one.
https://help.ctrader.com/ctrader-algo/references/Trading/Positions/Positions/#closed
It occurs every time a position is closed. So it doesn't matter if a position is closed from a bot, a stop loss, a take profit, or someone manually closing it. That's why there's the “args” parameter is supplied so you can filter the event based on the symbol from the “positions” collection.
@firemyst
PanagiotisCharalampous
01 Nov 2019, 11:46
Hi FireMyst,
You should add a condition in Positions_Closed to be executed only when the closed position has the same same label as _positionLabel. Else the method will be executed when positions from other instances are closed, eventually closing all positions of the account.
Best Regards,
Panagiotis
@PanagiotisCharalampous