I have been working on some code that was initially generated by the strategy builder. I'm currently working on building it out to a basic boilerplate template for future use.
Currently the entry is filtered by user input (entering LONG or SHORT), and when a bar closes up or down (based on the user's input for LONG/SHORT) it enters a trade as expected, and places the initial stop loss as expected.
For the couple of hours I've been trying to get the stop loss to trail behind bars that close in favor of the position. For example if long then wait for an up bar. Once an up bar closes, update the price of the stop loss to a new price below the recently close up bar. There is a user input called stopBufferTicks that controls how far below the recently closed up bar the new stop is to be placed.
I've done this in a couple of other platforms with very similar logic, but I am definitely missing something. Please help, I'm spinning my wheels on this.
I'm going to paste the code for the strategy in this post. I did so recently and was asked to re-paste a portion of the code (on another question) so if you would like me to do that feel free to let me know which parts you want me to cut out. I am including more code than the logic in question in the event that my error is not where I expect it to be.
Edit: Including screenshot of testing showing that the code is getting to the print statement, along with a ten tick ruler showing an unmoved initial stop
Code:
public class GRAYBOXv3 : Strategy
{
protected override void OnStateChange()
{
if (State == State.SetDefaults)
{
Description = @"dont know yet";
Name = "GRAYBOXv3";
Calculate = Calculate.OnBarClose;
EntriesPerDirection = 1;
EntryHandling = EntryHandling.AllEntries;
IsExitOnSessionCloseStrategy = true;
ExitOnSessionCloseSeconds = 30;
IsFillLimitOnTouch = false;
MaximumBarsLookBack = MaximumBarsLookBack.TwoHundredFiftySix;
OrderFillResolution = OrderFillResolution.Standard;
Slippage = 0;
StartBehavior = StartBehavior.WaitUntilFlat;
TimeInForce = TimeInForce.Gtc;
TraceOrders = false;
RealtimeErrorHandling = RealtimeErrorHandling.StopCancelClose;
StopTargetHandling = StopTargetHandling.PerEntryExecution;
BarsRequiredToTrade = 20;
// Disable this property for performance gains in Strategy Analyzer optimizations
// See the Help Guide for additional informationasdf
IsInstantiatedOnEachOptimizationIteration = true;
LongShort = @"Neither";
StopSize =10;
//stopBufferTicks =10;
}
else if (State == State.Configure)
{
//int sl = StopSize;
SetStopLoss(@"short entry", CalculationMode.Ticks, StopSize, false);
SetStopLoss(@"long entry", CalculationMode.Ticks, StopSize, false);
}
}
double origStopPrice;
protected override void OnOrderUpdate(Order order, double limitPrice, double stopPrice, int quantity, int filled, double averageFillPrice, OrderState orderState, DateTime time, ErrorCode error, string nativeError)
{
origStopPrice = stopPrice;
}
protected override void OnBarUpdate()
{
bool _oktolong = LongShort == "LONG";
bool _oktoshort = LongShort == "SHORT";
if (BarsInProgress != 0)
return;
if (CurrentBars[0] < 1)
return;
if(State==State.Historical) return;
// Long
if (Close[0] > Open[0] && _oktolong)
{
EnterLong(Convert.ToInt32(DefaultQuantity), @"long entry");
}
// Short
if (Close[0] < Open[0] && _oktoshort)
{
EnterShort(Convert.ToInt32(DefaultQuantity), @"short entry");
}
//If current position is long and the previous bar was an up bar
if(Position.MarketPosition == MarketPosition.Long && Close[1] > Open[1])
{
if((Low[1]-stopBufferTicks) > origStopPrice) //check that new stop location is greater than original stop (to avoid widening stop)
{
SetStopLoss(CalculationMode.Price,(Low[1]-stopBufferTicks));//update stop price to below prior bar's low by "stopBufferTicks"
Print("it's at least getting here");
}
//once the logic to trail long stops works, copy/paste/modify it for shorts below:
}else if (Position.MarketPosition == MarketPosition.Short && Close[0] < Open[0])
{
if((High[1]+stopBufferTicks) < origStopPrice)
{
SetStopLoss(CalculationMode.Price, High[1]+stopBufferTicks);
}
}
}
#region Properties
[NinjaScriptProperty]
[Display(Name="LongShort", Order=1, GroupName="Parameters")]
public string LongShort
{ get; set; }
[NinjaScriptProperty]
[Display(Name="Enter Stop in Ticks", Order=1, GroupName="Parameters")]
public int StopSize
{ get; set; }
[NinjaScriptProperty]
[Display(Name="Enter Stop Buffer in Ticks", Order=1, GroupName="Parameters")]
public int stopBufferTicks
{ get; set; }
#endregion
}
Comment