protected override void OnStateChange() { if (State == State.SetDefaults) { Description = NinjaTrader.Custom.Resource.NinjaScriptIndicatorDescriptionNetChangeDisplay; Name = NinjaTrader.Custom.Resource.NinjaScriptIndicatorNameNetChangeDisplay; Calculate = Calculate.OnPriceChange; IsOverlay = true; DrawOnPricePanel = true; IsSuspendedWhileInactive = true; Unit = PerformanceUnit.Percent; PositiveBrush = Brushes.LimeGreen; NegativeBrush = Brushes.Red; Location = NetChangePosition.TopRight; Font = new NinjaTrader.Gui.Tools.SimpleFont("Arial", 18); } else if (State == State.Configure) { instrument = Instruments[0]; } }
protected override void OnBarUpdate() { if (Count - 2 == CurrentBar) //Calculate cycle on last finished, closed bar { string APIresultContent = ""; //Get and prepare the close data array int seriesCount = Close.Count - 1; List <double> closeList = new List <double>(); for (int i = 0; i <= seriesCount; i++) { closeList.Add(Close.GetValueAt(i)); } //Call the WhenToTrade Cycles API endpoint POST CycleExplorer using (var client = new HttpClient()) { //WhenToTrade API URL client.BaseAddress = new Uri("https://api.marketcycles.online/"); //Load the close dataset for HTTP API POST call var contents = JsonConvert.SerializeObject(closeList.ToArray()); StringContent POSTcontent = new StringContent(contents, Encoding.UTF8, "application/json"); //POST API CALL var response = client.PostAsync("/api/CycleExplorer?minCycleLength=" + minCycleLength + "&maxCycleLength=" + maxCycleLength + "&plotForward=" + plotForward + "&includeTimeseries=true&api_Key=" + apiKey, POSTcontent).Result; //Check for network errors if (response.IsSuccessStatusCode) { APIresultContent = response.Content.ReadAsStringAsync().Result; } else { string msg = response.Content.ReadAsStringAsync().Result; Draw.TextFixed(this, "apierror", "API ERROR:" + msg, TextPosition.TopLeft); return; } } // Decode the cycle data from API call var dominantCycle = JsonConvert.DeserializeObject <dynamic>(APIresultContent); // Test for return errors from API? string statusCode = dominantCycle.StatusCode != null ? dominantCycle.StatusCode : ""; bool error = statusCode.IndexOf("error", StringComparison.OrdinalIgnoreCase) >= 0; if (error) { Draw.TextFixed(this, "apierror", "API ERROR:" + statusCode, TextPosition.TopLeft); return; } //get key cycle information from return object var cyclelength = dominantCycle.length; var currentPrice = dominantCycle.currentPrice; var timeSeries = dominantCycle.TimeSeries; // DEBUG: Print return values to log Print(dominantCycle); // Fill cycle indicator values from timeSeries API return array (info: called just once for the full chart) for (int i = 0; i <= CurrentBar; i++) { try { Value[CurrentBar - i] = timeSeries[i + plotForward].dominantCycle; if (timeSeries[i + plotForward].cycleHighlighter != null) { Values[1][CurrentBar - i] = timeSeries[i + plotForward].cycleHighlighter; } } catch (Exception ex) { //should never happen, but in case lets ignore them and only print to log Print("Error: " + i + " - " + ex.Message); } } // Plot Dominant Cycle Information TextFixed myTF = Draw.TextFixed(this, "dctext", "Cycle Length: " + cyclelength.ToString("0") + Environment.NewLine + "Next Low: " + dominantCycle.nextlow.ToString("0.00") + Environment.NewLine + "Next Top: " + dominantCycle.nexttop.ToString("0.00") + Environment.NewLine + "Status: " + dominantCycle.phase_status, TextPosition.TopLeft); // Plot the dot at current bar cycle position double doty = timeSeries[CurrentBar].dominantCycle; NinjaTrader.Gui.Tools.SimpleFont myFont = new NinjaTrader.Gui.Tools.SimpleFont("Wingdings", 12) { Size = 12 }; Draw.Text(this, "dot", true, "l", 0, doty, 0, Brushes.Green, myFont, TextAlignment.Center, Brushes.Transparent, Brushes.Transparent, 0); } }