I have a strategy that seems to be working for the most part: it will trade on a historical playback. However, if I try to run it in the strategy analyzer it throws out the error, "Error on calling 'OnBarUpdate' method on bar 2: Object reference not set to an instance of an object."
1. I have searched high and low on the support forum for a similar error. The advice is usually that there is a BarsAgo called somewhere that does not exist yet. However, I am not using this method so I'm hoping with your experience you'll be able to spot my mistake.
2. I also am using EnterLongLimit() in my code which of course opens the order object can of worms. I don't think I'm doing my orders correctly. I find that the order, if not triggered, will close on the next bar. Also, if I scale in with another order by hand I will get closed out of both orders. I have read the docs and while right up front it states this is advanced, I have to humbly say that I wish there were more examples of how the methods work together holistically. The documentation is on a very atomic level. This method does this. It has potentially 4 arguments. Here is one cold line of code that is totally unassociated with the other methods you would most likely be used in conjunction. Good luck! lol. As the developer switches gears into the unmanaged orders it would be so helpful to see the most popular examples of how the methods work together. I would think that most people want to replicate an ATM order programmatically so one of two "full" strategies that focus on the order methods would be gold!
The support here is thankfully wonderful. Again, just some humble and friendly questions and feedback from a new user who's getting his sea legs.
Code below. I'm dropping the entire thing for clarity.
#region Using declarations using System; using System.Collections.Generic; using System.ComponentModel; using System.ComponentModel.DataAnnotations; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Input; using System.Windows.Media; using System.Xml.Serialization; using NinjaTrader.Cbi; using NinjaTrader.Gui; using NinjaTrader.Gui.Chart; using NinjaTrader.Gui.SuperDom; using NinjaTrader.Gui.Tools; using NinjaTrader.Data; using NinjaTrader.NinjaScript; using NinjaTrader.Core.FloatingPoint; using NinjaTrader.NinjaScript.Indicators; using NinjaTrader.NinjaScript.DrawingTools; #endregion //This namespace holds Strategies in this folder and is required. Do not change it. namespace NinjaTrader.NinjaScript.Strategies { public class CoopIM2 : Strategy { protected override void OnStateChange() { if (State == State.SetDefaults) { Description = @"Profit!"; Name = "CoopIM2"; 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 information IsInstantiatedOnEachOptimizationIteration = true; // My custom vars MaxBarHeight = 1; MinBarHeight = 1; TradeEntryOffset = 1; TradeTarget = 1; TradeStopLossOffset = 1; BarCompleteMin = 0.5; AskImbalanceTarget = 1; NumberOfContracts = 1; } else if (State == State.Configure) { SetProfitTarget(CalculationMode.Ticks, TradeTarget); SetStopLoss(CalculationMode.Ticks, TradeStopLossOffset); } else if (State == State.DataLoaded) { } else if (State == State.SetDefaults) { } } protected override void OnBarUpdate() { if (BarsInProgress != 0) return; if (CurrentBars[0] < 2) return; int numberOfImbalances = 0; int imbalanceMultiple = 4; double wickSize = High[0] - Low[0]; double barSize = Close[0] - Open[0]; double barRatio = Math.Round(barSize / wickSize, 2); double CurrentBarHeight = ((High[0] - Low[0]) / TickSize) + 1; // Get the height of the current bar // Instantiate volumetric bars NinjaTrader.NinjaScript.BarsTypes.VolumetricBarsTy pe barsType = Bars.BarsSeries.BarsType as NinjaTrader.NinjaScript.BarsTypes.VolumetricBarsTy pe; // Create lists to hold the bid and ask data List<long> myBid = new List<long>(); List<long> myAsk = new List<long>(); // Get the bid and ask into lists for (int i = 0; i <= CurrentBarHeight; i++) // cycle through each tick level { long a = barsType.Volumes[CurrentBar].GetAskVolumeForPrice(High[0] -(i*TickSize)); // start at the top and work down long b = barsType.Volumes[CurrentBar].GetBidVolumeForPrice(High[0] -(i*TickSize)); myBid.Add(b); myAsk.Add(a); } if (CurrentBarHeight <= MaxBarHeight && CurrentBarHeight >= MinBarHeight) // is the bar not to big or too small { if (Open[0] == Close[0]) return; // stop everyhting if this is a doji if (Open[0] < Close[0]) // If the direction of this bar long - GREEN BAR { if ( barRatio < BarCompleteMin ) return; // is the bar is too small in relation to the wick kill everything for (int i = 1; i <= CurrentBarHeight-1; i++) // cycle through each tick level { if (myAsk[i-1] > ( myBid[i] * imbalanceMultiple) ) { if (myAsk[i-1] != 0 && myBid[i] != 0) // scrub out any results with 0's as they don't count as an imbalance { numberOfImbalances++; } } } if (numberOfImbalances >= AskImbalanceTarget) { // do something if all conditions are met //alerts: visual and audio Draw.ArrowUp(this, @"AboveEMA Arrow up_1 " + Convert.ToString(CurrentBars[0]), true, 0, (Low[0] + (-2 * TickSize)) , Brushes.Yellow); Draw.Text(this, "IM_tag"+CurrentBar, "IM:"+numberOfImbalances,0,Low[0]-1.5); PlaySound(@"C:\Program Files (x86)\NinjaTrader 8\sounds\trade_imbalance.wav"); // lets buy some contracts! string mySignal = "LongLimit"+CurrentBar; double myEntryPrice = TradeEntryOffset * TickSize; EnterLongLimit(NumberOfContracts, Close[0] - myEntryPrice, mySignal); } } else { // this is a RED BAR if ( (barRatio * -1) < BarCompleteMin ) return; // is the bar is too small in relation to the wick kill everything numberOfImbalances = 0; for (int i = 1; i <= ((High[0] - Low[0]) / TickSize); i++) // cycle through each tick level { if (myBid[i] > ( myAsk[i-1] * imbalanceMultiple) ) { numberOfImbalances++; } } if (numberOfImbalances >= AskImbalanceTarget) { // do something if all conditions are met Draw.Text(this, "IM_tag"+CurrentBar, "IM:"+numberOfImbalances,0,High[0]+1.5); Draw.ArrowDown(this, @"AboveEMA Arrow down_1 " + Convert.ToString(CurrentBars[0]), true, 0, (High[0] + (+2 * TickSize)) , Brushes.Yellow); // lets buy some contracts! string mySignal = "ShortLimit"+CurrentBar; double myEntryPrice = TradeEntryOffset * TickSize; Print("The Close = " + Close[0] + " and the myEntryPrice = " + myEntryPrice + "TOTAL = " + Close[0]+myEntryPrice); EnterShortLimit(NumberOfContracts, Close[0] + myEntryPrice, mySignal); } } } } #region Properties [NinjaScriptProperty] [Range(1, int.MaxValue)] [Display(Name="MaxBarHeight", Order=1, GroupName="Parameters")] public int MaxBarHeight { get; set; } [NinjaScriptProperty] [Range(1, int.MaxValue)] [Display(Name="MinBarHeight", Order=2, GroupName="Parameters")] public int MinBarHeight { get; set; } [NinjaScriptProperty] [Range(1, int.MaxValue)] [Display(Name="TradeEntryOffset", Order=3, GroupName="Parameters")] public int TradeEntryOffset { get; set; } [NinjaScriptProperty] [Range(1, int.MaxValue)] [Display(Name="TradeTarget", Order=4, GroupName="Parameters")] public int TradeTarget { get; set; } [NinjaScriptProperty] [Range(1, int.MaxValue)] [Display(Name="TradeStopLossOffset", Order=5, GroupName="Parameters")] public int TradeStopLossOffset { get; set; } [NinjaScriptProperty] [Range(0.1, double.MaxValue)] [Display(Name="BarCompleteMin", Order=6, GroupName="Parameters")] public double BarCompleteMin { get; set; } [NinjaScriptProperty] [Range(1, int.MaxValue)] [Display(Name="AskImbalanceTarget", Order=7, GroupName="Parameters")] public int AskImbalanceTarget { get; set; } [NinjaScriptProperty] [Range(1, int.MaxValue)] [Display(Name="NumberOfContracts", Order=8, GroupName="Parameters")] public int NumberOfContracts { get; set; } #endregion } }
Comment