StopLoss Calculations/ Terminal freeze volatile market conditions/System Interrupts
StopLoss Calculations/ Terminal freeze volatile market conditions/System Interrupts
12 Feb 2022, 09:46
Hi
I run CBot in vps with 6 threads/16 GB RAM which has ample resources, normally the cpu utilization is about 30-40% and ram utilization is 30%. This CBot runs on 20-30 symbols on Range Bars, whenever there is high volatility CTrader freezes and in task manager "SystemInterrupts" cpu utilization goes up 80-90%.
When there is high volatility/Event CBot of different symbol opens trade. Cumulatively ~ 10 -20 positions with stoploss are present and at every bar based on logic new positions(orders) are opened or StopLoss is moved or Positions are scaled (new orders)
In the CBot logs errors
Failed to get symbol 'XAUUSD': symbol has no quotes.
Crashed in BarOpened with NullReferenceException: Object reference not set to an instance of an object.
The symbols are random and CBot stops.
In the attached code, I could point out to StopLoss calculation function.
If there is no high volatality/Event CBot works without any issue.
Please let me know what might be causing the issue.
Appreciate your insights
Regards
Ahmed
using System;
using System.Linq;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;
using cAlgo.Indicators;
namespace cAlgo.Robots
{
[Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
public class ForumCTraderSL : Robot
{
[Parameter(DefaultValue = 0.0)]
public double Parameter { get; set; }
double GlobalTotalSl;
public double CheckSLPositions()
{
//Print(Symbol.Name + "CheckSlPositions Executed");
var positionsCBS = Positions.FindAll("");
double TotalSl = 0;
//var positionsCBS = Positions.FindAll("");
if (positionsCBS.Length != 0)
{
foreach (var psnCBS in positionsCBS)
{
// psnCBS.StopLoss doesnt return 0 if there is no StopLoss for open position, so have to convert to string
if (psnCBS.StopLoss.ToString() != "")
{
var GetSymbolName = psnCBS.SymbolName;
var GetSymbolNameLotSize = Symbols.GetSymbol(GetSymbolName).LotSize;
var GetSymbolPipValueSize = Symbols.GetSymbol(GetSymbolName).PipValue / Symbols.GetSymbol(GetSymbolName).PipSize;
var GetSymbolNameQty = psnCBS.Quantity;
switch (psnCBS.TradeType)
{
case TradeType.Buy:
var Bpips = (double)(psnCBS.StopLoss - psnCBS.EntryPrice);
TotalSl = Bpips * GetSymbolNameLotSize * GetSymbolPipValueSize * GetSymbolNameQty;
break;
case TradeType.Sell:
var Spips = (double)(psnCBS.EntryPrice - psnCBS.StopLoss);
TotalSl = Spips * GetSymbolNameLotSize * GetSymbolPipValueSize * GetSymbolNameQty;
break;
}
}
}
Print("CheckSlPositions TotalStopLossPips: " + TotalSl.ToString("F6"));
}
return TotalSl;
}
private void Bars_BarOpened_CheckSLPositions(BarOpenedEventArgs obj)
{
GlobalTotalSl = 0;
GlobalTotalSl = CheckSLPositions();
}
private void Bars_BarOpened_StopLossMove(BarOpenedEventArgs obj)
{
//Logic to move stop loss
}
private void Bars_BarOpened_AutoOrder(BarOpenedEventArgs obj)
{
//Logic place order there are some calculations used
//When the condition GlobalTotalSl is executed, due to computations of above statements, sync of GlobalTotalSl should happen
//Condition Check GlobalTotalSl should be within limit
}
private void Bars_BarOpened_AutoScale(BarOpenedEventArgs obj)
{
//Logic scale up orders
}
protected override void OnStart()
{
GlobalTotalSl = 0;
Bars.BarOpened += Bars_BarOpened_CheckSLPositions;
Bars.BarOpened += Bars_BarOpened_StopLossMove;
Bars.BarOpened += Bars_BarOpened_AutoOrder;
Bars.BarOpened += Bars_BarOpened_AutoScale;
// Put your initialization logic here
}
protected override void OnTick()
{
// Put your core logic here
}
protected override void OnStop()
{
// Put your deinitialization logic here
}
}
}
Replies
firemyst
13 Feb 2022, 05:48
positionsCBS can be null, which is one reason you might be getting the null reference exception.
After all, when you start the bot, there might not be any positions open.
So you need to check if you have any positions:
if (positionsCBS != null && positionsCBS.Length != 0)
And if you want to check if a position has a stoploss or not, you need to use p.GetValueOrDefault()
That will return zero if there's no stop loss associated with the position.
So don't do this:
if (psnCBS.StopLoss.ToString() != "")
Do this instead:
if (psnCBS.StopLoss.GetValueOrDefault() != 0)
@firemyst
m4trader4
13 Feb 2022, 18:52
RE:
This is the second time i am writing as the first one after posting dint appear
Hi Firemyst
Thanks for pointers, will amend the code.
The issue i think is when there is high volatility CheckSLPositions() is unable to lock the postions list. The CBot running on other symbols is doing the same opening new trades/moving stoploss/checking Stoploss.
Its about the thread safe
Regards
Ahmed
@m4trader4
firemyst
14 Feb 2022, 04:47
RE: RE:
m4trader4 said:
This is the second time i am writing as the first one after posting dint appear
Hi Firemyst
Thanks for pointers, will amend the code.
The issue i think is when there is high volatility CheckSLPositions() is unable to lock the postions list. The CBot running on other symbols is doing the same opening new trades/moving stoploss/checking Stoploss.
Its about the thread safe
Regards
Ahmed
Why would you need to lock the Positions object? All you're doing is reading it; you can't set any values in it. So it's not your problem. :-)
I don't understand why you would want, or have, a cbot running under multiple symbols that would adjust the stoploss for _ALL_ open positions and not just the one the bot is running under?
To resolve the "thread safety", just have this cbot running once under 1 symbol and that's it since it updates every position that's open.
So change this statement to only find the symbol's the bot is running under:
Positions.FindAll("") //change this
change the above to something like:
Positions.Find("", Symbol.Name); //return only the positions under the current symbol the bot instance is running under
If you insist or really need multiple instances of this bot to be running and updating all positions across all symbols, then one approach is to create a global lock object and lock that bit of code. KEep in mind the performance implications - like it'll slow down your other bots as they wait to obtain a lock. This isn't the most elegant or possibly best way, but here goes:
public static object myGlobalLockObject = new object();
:
:
lock (myGlobalLockObject)
{
if (positionsCBS != null and positionsCBS.Length > 0)
{
foreach ( ... )
{
}
}
}
@firemyst
m4trader4
14 Feb 2022, 11:19
RE: RE: RE:
@ cAIgoBuddy, Yesterday i could not find your reply, have ammended code according to Firemyst suggestions, i had to repost my reply second time
@Firemyst, Bars.BarOpened += Bars_BarOpened_StopLossMove; does excatly the same as you said moves the stoploss according to symbol as the parameters are different for each symbol
Positions.Find("", Symbol.Name); //return only the positions under the current symbol the bot instance is running under
Only issue is checking the public double CheckSLPositions() of all the positions before placing new orders, when there is high volatility/Event, as bars print very fast.
As you said lock does not seems to be a good solution, not for it
@m4trader4
m4trader4
14 Feb 2022, 11:29
RE: RE: RE: RE:
@Firemyst
if (psnCBS.StopLoss.GetValueOrDefault() != 0) doesnt work, CBot crashes
@ cAlgoBuddy
psnCBS.StopLoss.HasValue is working CBot is not crashing.
Have to check when there is high volatility/Event
@m4trader4
firemyst
14 Feb 2022, 12:35
RE: RE: RE: RE: RE:
m4trader4 said:
@Firemyst
if (psnCBS.StopLoss.GetValueOrDefault() != 0) doesnt work, CBot crashes
@ cAlgoBuddy
psnCBS.StopLoss.HasValue is working CBot is not crashing.
Have to check when there is high volatility/Event
Define "doesn't work".
The only way it won't work is if psnCBS is null.
What's the error message thrown when the bot crashes?
@firemyst
m4trader4
14 Feb 2022, 13:02
RE: RE: RE: RE: RE:
m4trader4 said:
@Firemyst
if (psnCBS.StopLoss.GetValueOrDefault() != 0) doesnt work, CBot crashes
@ cAlgoBuddy
psnCBS.StopLoss.HasValue is working CBot is not crashing.
Have to check when there is high volatility/Event
cBot crashed: Error #90580554
cBot crashed: Error #65147970
@m4trader4
firemyst
14 Feb 2022, 14:41
RE: RE: RE: RE: RE: RE:
m4trader4 said:
cBot crashed: Error #90580554
cBot crashed: Error #65147970
If you check this thread:
according to @amusleh, this happens with high volatility. So again this probably comes back to your code trying to move/check a stop loss when the position could have been closed elsewhere.
This could happen either with ".HasValue" or ".Stoploss.GetValueOrDefault()".
It also says you need a flag in your code to see if the closing event has been fired. If it has, you can't go through, check positions, and modify stop losses because one of the positions in your foreach loop could have been closed between the time you check the length of the positions and go through the foreach loop.
@firemyst
cAIgoBuddy
12 Feb 2022, 10:52
RE:
m4trader4 said:
Hello,
For starters, change
psnCBS.StopLoss.ToString() != ""
to
psnCBS.StopLoss.HasValue
Since StopLoss is a nullable double, it can crash when invoking ToString() when it's null.
@cAIgoBuddy