Announcement

Collapse
No announcement yet.

Partner 728x90

Collapse

After "async await with an HTTPClient" Environment is invalid

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    After "async await with an HTTPClient" Environment is invalid

    Hello,
    first, i am not an native Speeker in English, my language is German, so i hope i could describ my Problem

    I wrote some logik to get a good situation to send a signal to my Server, the server do some magic and build a Order-Object.
    After them i will Paint some Informations from this Order-Object in the chart.
    After returning fom my server, CurrentBar is not the bar before calling the server, everey access to an Bar before throws an excption

    And i had realy many Problems, and i wrote an Indicator for this Post which produce alle errors.
    Of course, you can not access to my Server, but i testet this code, you get all errors which i have.

    I hope you can help my.

    Code:
    #region Using declarations
    using System;
    using System.Net.Http;
    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.DrawingTools;
    #endregion
    
    //This namespace holds Indicators in this folder and is required. Do not change it.
    namespace NinjaTrader.NinjaScript.Indicators
    {
    public class NinjaTraderSupport : Indicator
    {
    
    private readonly int StartBarsAgo = 18;
    private int lastPaintedBar = 0;
    
    protected override void OnStateChange()
    {
    if (State == State.SetDefaults)
    {
    Description = @"Indicator für den NinjaTraderSupport";
    Name = "NinjaTraderSupport";
    Calculate = Calculate.OnBarClose;
    IsOverlay = true;
    IsSuspendedWhileInactive = true;
    }
    else if (State == State.Configure)
    {
    }
    }
    
    protected async override void OnBarUpdate()
    {
    if (CurrentBar < StartBarsAgo)
    return;
    
    
    if (CurrentBar - lastPaintedBar < StartBarsAgo)
    return;
    
    string orderException = string.Empty;
    try
    {
    if (CurrentBar % 100 == 0)
    {
    double price = Open[0];
    
    lastPaintedBar = CurrentBar;
    
    if (lastPaintedBar <= 10)
    return;
    
    Draw.Text(this, lastPaintedBar + "tag1","Before Call", 10, price, Brushes.White);
    
    NinjaTrader.DomainModel.Test.Signal signal = new NinjaTrader.DomainModel.Test.Signal(price, lastPaintedBar);
    
    Print(CurrentBar.ToString() + " " + signal.Price);
    
    Task<NinjaTrader.DomainModel.Test.Order> orders = signal.Commit();
    NinjaTrader.DomainModel.Test.Order orderBuy = await orders;
    
    orderException = orderBuy.ExceptionMessage;
    
    
    // change barsAgo to 1 throws an exception
    Draw.Text(this, lastPaintedBar + "tag2","After Call", 0, price - 500, Brushes.Green);
    
    // after returning from HTTPClient call to server, CurrentBar has the last Bar, not the bar which this Method is called.
    // change Bars[0] to Bars[1] throws an exception
    Print(CurrentBar.ToString() + " " + orderBuy.Bar + ": " + orderBuy.StopLoss + " - " + Bars[0]);
    }
    }
    catch(Exception ex)
    {
    Print("MainTryCatch:" + CurrentBar.ToString() + " " + ex.Message + " " + orderException);
    }
    }
    }
    }
    
    namespace NinjaTrader.DomainModel.Test
    {
    public class Signal
    {
    
    public double Price { get; set; }
    
    public int Bar { get; set;}
    
    public Signal(double price, int bar)
    {
    Price = price;
    Bar = bar;
    }
    
    
    public async Task<NinjaTrader.DomainModel.Test.Order> Commit()
    {
    try
    {
    string json = Newtonsoft.Json.JsonConvert.SerializeObject(this);
    using (HttpClient client = new HttpClient())
    {
    HttpContent content = new StringContent(json);
    HttpResponseMessage message = await client.PostAsync("http://192.168.80.128:5001", content);
    
    if (message.StatusCode != System.Net.HttpStatusCode.OK)
    {
    Console.WriteLine("Falschen Status-Code erhalten: {0}.", message.StatusCode);
    string readAs = await message.Content.ReadAsStringAsync();
    Console.WriteLine(string.Format("Gemeldeter Fehler: {0}.", readAs));
    NinjaTrader.DomainModel.Test.Order order = new NinjaTrader.DomainModel.Test.Order();
    order.Bar = this.Bar;
    order.ExceptionMessage = string.Format("Gemeldeter Fehler: {0}.", readAs);
    return order;
    }
    NinjaTrader.DomainModel.Test.Order orders = Newtonsoft.Json.JsonConvert.DeserializeObject<Ninj aTrader.DomainModel.Test.Order>( message.Content.ToString());
    orders.ExceptionMessage = "Original";
    return orders;
    }
    }catch(Exception ex)
    {
    NinjaTrader.DomainModel.Test.Order order = new NinjaTrader.DomainModel.Test.Order();
    order.Bar = this.Bar;
    order.ExceptionMessage = ex.Message;
    return order;
    }
    
    }
    }
    
    public class Order
    {
    public bool Placed { get; set; }
    public bool Buy { get; set; }
    public int Bar { get; set;}
    public double Price { get; set; }
    public double StopLoss { get; set; }
    public double TakeProfit { get; set; }
    public string ExceptionMessage { get; set;}
    }
    }
    
    #region NinjaScript generated code. Neither change nor remove.
    
    namespace NinjaTrader.NinjaScript.Indicators
    {
    public partial class Indicator : NinjaTrader.Gui.NinjaScript.IndicatorRenderBase
    {
    private NinjaTraderSupport[] cacheNinjaTraderSupport;
    public NinjaTraderSupport NinjaTraderSupport()
    {
    return NinjaTraderSupport(Input);
    }
    
    public NinjaTraderSupport NinjaTraderSupport(ISeries<double> input)
    {
    if (cacheNinjaTraderSupport != null)
    for (int idx = 0; idx < cacheNinjaTraderSupport.Length; idx++)
    if (cacheNinjaTraderSupport[idx] != null && cacheNinjaTraderSupport[idx].EqualsInput(input))
    return cacheNinjaTraderSupport[idx];
    return CacheIndicator<NinjaTraderSupport>(new NinjaTraderSupport(), input, ref cacheNinjaTraderSupport);
    }
    }
    }
    
    namespace NinjaTrader.NinjaScript.MarketAnalyzerColumns
    {
    public partial class MarketAnalyzerColumn : MarketAnalyzerColumnBase
    {
    public Indicators.NinjaTraderSupport NinjaTraderSupport()
    {
    return indicator.NinjaTraderSupport(Input);
    }
    
    public Indicators.NinjaTraderSupport NinjaTraderSupport(ISeries<double> input )
    {
    return indicator.NinjaTraderSupport(input);
    }
    }
    }
    
    namespace NinjaTrader.NinjaScript.Strategies
    {
    public partial class Strategy : NinjaTrader.Gui.NinjaScript.StrategyRenderBase
    {
    public Indicators.NinjaTraderSupport NinjaTraderSupport()
    {
    return indicator.NinjaTraderSupport(Input);
    }
    
    public Indicators.NinjaTraderSupport NinjaTraderSupport(ISeries<double> input )
    {
    return indicator.NinjaTraderSupport(input);
    }
    }
    }
    
    #endregion

    #2
    Hello SpikeLGWG,

    Thanks for your post.

    Much of this is going to be unsupported. Supported NinjaScript is limited to what we have documented in the Help Guide. While "anything is possible with C#" there will be limits on what we can assist with.

    I did give your script a test after adding Newtonsoft.Json.dll which is needed with your example to see if I can give some further insight.

    CurrentBar will always represent the the bar index of the currently developing bar in OnBarUpdate. Any asynchronous request made from this event would not "pause" OnBarUpdate, and we would not suggest sleeping threads to wait for async tasks to complete as this can cause issues with other parts of the platform that may be using that thread. You could consider using a timer to wait for the task to complete, and then you could consider using TriggerCustomEvent to perform operations from the timer once complete.

    I am not sure why Bar is used in your print, but when I change the print to Close[1], I do not get an exception. I may suggest using PriceSeries like Open, High, Low and Close for your purposes.

    We will also leave this thread open for any community members that have tried similar and would like to report their findings.

    We look forward to assisting.
    JimNinjaTrader Customer Service

    Comment


      #3
      Hallo Jim,
      thank you for your answer!
      the Bar[0] in the Print is only used to show, i can't access to previous Bars, but you are right, Closes[1] works.

      The greatest Point in my Code is the last Draw.Text to use barsAgo != 0.

      // change barsAgo to 1 throws an exception
      Draw.Text(this, lastPaintedBar + "tag2","After Call", 0, price - 500, Brushes.Green);

      Change this one to barsAgo 1 results in Exception:
      Object reference not set to an instance of an object. An error occurred while sending the request.

      What is the best way to use a HTTPClient to request a Server and manage the Result?
      I will try to check first the Timer object, but i hope you have some hints for me.

      Thanks for the support!

      Comment


        #4
        Hello SpikeLGWG,

        I can't reproduce with the unsupported code removed. The issue looks to be attributed to performing the asynchronous task.

        I may suggest a different approach here. Instead of creating an asynchronous task in OnBarUpdate and waiting for it to complete to keep your OnBarUpdate tasks "synchronous, " you may wish to consider letting your task run asynchronously and keep track of the bar indexes when you start your asynchronous task. When the task completes, you can see what the CurrentBar is, and then do any "catch up" work by looping over those bars that have been processed.

        Essentially, I would not suggest trying to stick an asynchronous operation in OnBarUpdate and make OnBarUpdate wait for that operation to complete. Letting that operation complete and then making adjustments after completion may be a better way to go.

        That is the most I can offer for insight on this matter. If any community members have insight to share for starting asynchronous operations in OnBarUpdate and have had success trying something similar to what you are trying, we will leave the thread open for their feedback.
        JimNinjaTrader Customer Service

        Comment


          #5
          Hello Jim,

          first i solved this Problem!
          The Reason of the Problem was my missunderstanding of asynchronus Handling.
          In the Task which handels the returnValue from the Server, there are no static Properties from the Ninjatrader existing or have not the Values from original OnBarUpdate where the Taks was created.
          Here the Code of my Solution, imported: the Calculate Setting should be OnPriceChage
          Code:
          private List<NinjaTrader.DomainModel.Test.Order> returnedOrders;
          private readonly object returnedOrders_Lock = new object();
          protected async override void OnBarUpdate()
          {
          // read "Cachlist"
          if (returnedOrders.Count > 0)
          {
          Print("returnedOrders.Count: " + returnedOrders.Count);
          
          lock(returnedOrders_Lock)
          for (int index = returnedOrders.Count -1; index >= 0; index--)
          {
          Print("in CurrentBarloop: " + CurrentBar.ToString() + " " + returnedOrders[index].Bar);
          returnedOrders.RemoveAt(index);
          }
          }
          
          try
          {
          if (CurrentBar % 100 == 0)
          {
          double price = Open[0];
          
          Print(CurrentBar.ToString() + " send Signal at Price: " + price);
          NinjaTrader.DomainModel.Test.Signal signal = new NinjaTrader.DomainModel.Test.Signal(price, CurrentBar);
          Task<NinjaTrader.DomainModel.Test.Order> orders = signal.Commit();
          
          // asyncronus Call!!
          NinjaTrader.DomainModel.Test.Order orderBuy = await orders;
          
          // store anwer of Server in "Cachlist"
          lock(returnedOrders_Lock)
          returnedOrders.Add(orderBuy);
          }
          }
          catch (Exception ex)
          {
          Print("OnBarUpdate_TryCatch: " + CurrentBar.ToString() + " " + ex.Message);
          }
          }

          Comment

          Latest Posts

          Collapse

          Topics Statistics Last Post
          Started by demarcog, Today, 12:28 PM
          1 response
          6 views
          0 likes
          Last Post NinjaTrader_ChelseaB  
          Started by demarcog, Today, 11:03 AM
          5 responses
          20 views
          0 likes
          Last Post NinjaTrader_ChelseaB  
          Started by jo54321, Today, 04:26 AM
          1 response
          9 views
          0 likes
          Last Post NinjaTrader_ChelseaB  
          Started by pserrera, Today, 03:26 AM
          1 response
          12 views
          0 likes
          Last Post NinjaTrader_ChelseaB  
          Started by maxuscz, Today, 03:01 AM
          1 response
          9 views
          0 likes
          Last Post NinjaTrader_ChelseaB  
          Working...
          X