Timed position close issue
Timed position close issue
03 May 2021, 10:37
Good day,
I added a timed position close loop into one of my trading bots, but it is not closing as expected every time.
For example:
With the settings for timed close set at 60 minutes, the profitable open positions in the first circle on the left should have closed at the circled segments to the right. The time that elapsed between open and the profitable peaks was approximately 3 days.
Code:
var CurrentTime = Server.TimeInUtc;
//Close expired profitable positions
foreach (var LongPosition in Positions.FindAll(robLabel, SymbolName, TradeType.Buy))
if ((IsPEtimer == true) && (LongPosition.EntryTime.AddMinutes(PEMinutes) > CurrentTime) && (LongPosition.NetProfit > revProfitClose))
{
ClosePosition(LongPosition);
}
The above works most of the time, but it fails a significant number of times so I need to fix this.
Ideas:
1. Server.TimeInUtc does not consider the date only time of day
2. The rest of the code runs into an exception so this loop does not get to execute every time step (OnBar), however in the code itself this is placed before the main trading logic loops.
V.
Replies
victor.major
03 May 2021, 12:33
RE:
This looks great! Thank you.
One question, why are we declaring the following as a user variable? Is there any benefit to making the timer not refresh every second for example?
[Parameter("Timer Interval (Seconds)", DefaultValue = 1, MinValue = 1)]
public int TimerIntervalInSeconds { get; set; }
V.
amusleh said:
Hi,
There are several issues with your code, first you should not put any time based logic inside OnBar method, instead you should use the OnTimer method and start timer on an interval that suits your specific needs.
You should not use TimeInUtc, the position EntryTime is set based on your robot time zone attribute, and you should use Server.Time not Server.TimeInUtc, it only works if your robot time zone is UTC.
Here is an example cBot:
using cAlgo.API; using System; namespace cAlgo.Robots { [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)] public class ClosePositionOnTime : Robot { [Parameter("Timer Interval (Seconds)", DefaultValue = 1, MinValue = 1)] public int TimerIntervalInSeconds { get; set; } [Parameter("Trade Type", DefaultValue = TradeType.Buy)] public TradeType TradeType { get; set; } [Parameter("Profit", DefaultValue = 100)] public double Profit { get; set; } [Parameter("Close Time (Minutes)", DefaultValue = 60)] public double CloseTimeInMinutes { get; set; } [Parameter("Label", DefaultValue = "My_cBot")] public string Label { get; set; } protected override void OnStart() { Timer.Start(TimerIntervalInSeconds); } protected override void OnTimer() { var currentTime = Server.Time; foreach (var position in Positions) { // Filter positions if (!string.Equals(position.Label, Label, StringComparison.OrdinalIgnoreCase) || !position.SymbolName.Equals(SymbolName, StringComparison.OrdinalIgnoreCase) || position.TradeType != TradeType) { continue; } // Close if position meet the condition if (position.EntryTime.AddMinutes(CloseTimeInMinutes) >= currentTime && position.NetProfit >= Profit) { ClosePosition(position); } } } } }
@victor.major
amusleh
03 May 2021, 12:53
RE: RE:
victor.major said:
This looks great! Thank you.
One question, why are we declaring the following as a user variable? Is there any benefit to making the timer not refresh every second for example?
[Parameter("Timer Interval (Seconds)", DefaultValue = 1, MinValue = 1)] public int TimerIntervalInSeconds { get; set; }
V.
amusleh said:
Hi,
There are several issues with your code, first you should not put any time based logic inside OnBar method, instead you should use the OnTimer method and start timer on an interval that suits your specific needs.
You should not use TimeInUtc, the position EntryTime is set based on your robot time zone attribute, and you should use Server.Time not Server.TimeInUtc, it only works if your robot time zone is UTC.
Here is an example cBot:
using cAlgo.API; using System; namespace cAlgo.Robots { [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)] public class ClosePositionOnTime : Robot { [Parameter("Timer Interval (Seconds)", DefaultValue = 1, MinValue = 1)] public int TimerIntervalInSeconds { get; set; } [Parameter("Trade Type", DefaultValue = TradeType.Buy)] public TradeType TradeType { get; set; } [Parameter("Profit", DefaultValue = 100)] public double Profit { get; set; } [Parameter("Close Time (Minutes)", DefaultValue = 60)] public double CloseTimeInMinutes { get; set; } [Parameter("Label", DefaultValue = "My_cBot")] public string Label { get; set; } protected override void OnStart() { Timer.Start(TimerIntervalInSeconds); } protected override void OnTimer() { var currentTime = Server.Time; foreach (var position in Positions) { // Filter positions if (!string.Equals(position.Label, Label, StringComparison.OrdinalIgnoreCase) || !position.SymbolName.Equals(SymbolName, StringComparison.OrdinalIgnoreCase) || position.TradeType != TradeType) { continue; } // Close if position meet the condition if (position.EntryTime.AddMinutes(CloseTimeInMinutes) >= currentTime && position.NetProfit >= Profit) { ClosePosition(position); } } } } }
Hi,
I did it for showing to you, you can set the timer interval to any value you want to fixed in code.
@amusleh
jani
23 Jan 2022, 23:40
Small correction to the the sample code
Thanks for all the good code.
I noticed a small logic error.
You should have:
if (position.EntryTime.AddMinutes(CloseTimeInMinutes) <= currentTime && position.NetProfit >= Profit)
Instead of:
if (position.EntryTime.AddMinutes(CloseTimeInMinutes) >= currentTime && position.NetProfit >= Profit)
This way position is closed when server time passes the position entry time + added minutes. and profit is greater than the set threshold.
@jani
amusleh
03 May 2021, 12:10
Hi,
There are several issues with your code, first you should not put any time based logic inside OnBar method, instead you should use the OnTimer method and start timer on an interval that suits your specific needs.
You should not use TimeInUtc, the position EntryTime is set based on your robot time zone attribute, and you should use Server.Time not Server.TimeInUtc, it only works if your robot time zone is UTC.
Here is an example cBot:
@amusleh