Announcement

Collapse

Looking for a User App or Add-On built by the NinjaTrader community?

Visit NinjaTrader EcoSystem and our free User App Share!

Have a question for the NinjaScript developer community? Open a new thread in our NinjaScript File Sharing Discussion Forum!
See more
See less

Partner 728x90

Collapse

stop limit (mkt) order 1 tick above previous bar highest bid+offer volume price

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

    stop limit (mkt) order 1 tick above previous bar highest bid+offer volume price

    Hello
    If I want to create a script and assign to button (or assign to a hot key) for placing stop limit (market) order 1 tick above/below previous bar highest bid+offer volume price and cancel order if not triggered during the current candle.

    what would be the simplest approach? I was hoping some way to assign this script using ATM and assign button in chart trader...


    Is there any reference doc I can refer? Any suggestiong is welcome.
    Marble

    #2
    Hello Marble,

    To do what you are asking would be easiest with a button. Keyboard events in NinjaScript are much more involved however that could also be possible.

    You can find a sample of a strategy that uses buttons on the public user app share: https://ninjatraderecosystem.com/use...bar-buttons-2/

    For this task you could change the order that is being submitted to a Stop Limit or Stop Market order. When a limit or stop type orders is submitted it will expire after 1 bar if not filled by default so that wouldn't need any extra logic for that. You would just need to make sure the entry is only submitted once and then don't call the same entry method again. If you continue to call the same entry method it will update the existing order and keep it active for more bars.

    Using an ATM would require much more logic and you would have to set up logic to cancel the order if not filled in one bar. You can see an example of what is involved with working with ATMs by viewing the SampleATMStrategy script that comes with the platform. You can include that type of code in the example linked above however none of the Managed or Unmanaged strategy code can be used with ATM's. You need to use the ATM specific code shown in the following link: https://ninjatrader.com/support/help...gy_methods.htm


    JesseNinjaTrader Customer Service

    Comment


      #3
      Hello Jesse

      Thank you for your suggestion. I have looked into the strategy suggested. Now I am facing issues below would you be able to help?

      1) Is there any place that I can refer code to obtain hightest volume price of previous candle, which can be used under free license version?
      2) If I press "close" button on charttrader panel, the whole strategy disappears. Is there any way to avoid issue?

      Any inputs are appreciated.
      Marble

      Comment


        #4
        Hello Marble,

        To know which price had the highest volume during a candle would require that you accumulate volumes at prices in a dictionary and then figure out which price had the highest volume, that is not something the bar information could tell you. That would require using OnEachTick calculation or using OnMarketData and then storing each ticks volume at price. You can see the VolumeProfile indicator for an example of sorting volumes at prices using OnMarketData.

        Pressing the close button will terminate your strategy so you would want to avoid doing that if you wanted to keep the strategy active. If you absolutely need to manually close a position you would want to program the strategy to have a custom button so you can use the button to submit strategy based orders to close that position. you can find an example of adding buttons to the chart in the following like, alternatively if you already used the toolbar buttons you can just add another button using that approach. https://ninjatrader.com/support/help...ub=usercontrol
        JesseNinjaTrader Customer Service

        Comment


          #5
          Hi Jesse

          Can you please provide me the code example that I can embedd in the sample strategy you shared me in #2?

          "To know which price had the highest volume during a candle would require that you accumulate volumes at prices in a dictionary and then figure out which price had the highest volume, that is not something the bar information could tell you. That would require using OnEachTick calculation or using OnMarketData and then storing each ticks volume at price. You can see the VolumeProfile indicator for an example of sorting volumes at prices using OnMarketData."

          Comment


            #6
            Hello Marble,

            You can see the VolumeProfile indicator for a code example. I am not aware of a volume accumulation that you could just plug into your strategy but you can learn from the concepts from that indicator. That indicator does the task that you are asking for to accumulate volume, you could learn from that indicator on how to do that type of task.
            JesseNinjaTrader Customer Service

            Comment


              #7
              HI Jesse
              I looked up for VolumeProfile indicator under eco system but no open source indicator was available. can you please direct me to any of code reference?

              Comment


                #8
                Hello Marble,

                The volume profile comes with NinjaTrader, its in your indicators folder already.
                JesseNinjaTrader Customer Service

                Comment


                  #9
                  Hello. I could not figure out from the volume profile. But I found the calculation of hightest volume of each bar within the indicator offered in ninja trader ecosystem.
                  Hi I'm Gabriel Zenobi, this is a toolkit that I developed for investment funds, banks and traders of all kinds. - gbzenobi/CSharp-NT8-OrderFlowKit


                  I want to use _maxPrice set in the code below. I have saved this SE.cs file under Addons folder in NT8.
                  https://github.com/gbzenobi/CSharp-N...n/AddOns/SE.cs

                  Here is the coded below to refer, I get CS0165 error. I am assuing below is where code is in correct.
                  //question: what to code to _maxPrice=pocprice
                  maxvolprice[0] = pocprice;
                  Print(maxvolprice[1]);
                  Can you please advise how to refer Addons and what is missing from code below?


                  Code:
                  [HASHTAG="t3322"]region[/HASHTAG] 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.Data;
                  using NinjaTrader.NinjaScript;
                  using NinjaTrader.Core.FloatingPoint;
                  using NinjaTrader.NinjaScript.Indicators;
                  using NinjaTrader.NinjaScript.DrawingTools;
                  
                  #endregion
                  using NinjaTrader.NinjaScript.AddOns.SightEngine;
                  using NinjaTrader.NinjaScript.AddOns.WyckoffRenderUtils;
                  
                  //This namespace holds Strategies in this folder and is required. Do not change it.
                  namespace NinjaTrader.NinjaScript.Strategies
                  {
                  public class StopLimit0918 : Strategy
                  {
                  private bool longButtonClicked;
                  private bool shortButtonClicked;
                  private System.Windows.Controls.Button longButton;
                  private System.Windows.Controls.Button shortButton;
                  private System.Windows.Controls.Grid myGrid;
                  public Series<double> maxvolprice;
                  private int currbar;
                  
                  protected override void OnStateChange()
                  {
                  if (State == State.SetDefaults)
                  {
                  Description = @"StopLimit0918";
                  Name = "StopLimit0918";
                  Calculate = Calculate.OnEachTick;
                  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;
                  
                  StopLoss = 4;
                  ProfitTarget = 9;
                  }
                  else if (State == State.Configure)
                  {
                  SetStopLoss(CalculationMode.Ticks, StopLoss);
                  SetProfitTarget(CalculationMode.Ticks, ProfitTarget);
                  maxvolprice = new Series<double>(this);
                  currbar = 0;
                  }
                  else if (State == State.Historical)
                  {
                  if (UserControlCollection.Contains(myGrid))
                  return;
                  
                  Dispatcher.InvokeAsync((() =>
                  {
                  myGrid = new System.Windows.Controls.Grid
                  {
                  Name = "MyCustomGrid", HorizontalAlignment = HorizontalAlignment.Right, VerticalAlignment = VerticalAlignment.Top
                  };
                  
                  System.Windows.Controls.ColumnDefinition column1 = new System.Windows.Controls.ColumnDefinition();
                  System.Windows.Controls.ColumnDefinition column2 = new System.Windows.Controls.ColumnDefinition();
                  
                  myGrid.ColumnDefinitions.Add(column1);
                  myGrid.ColumnDefinitions.Add(column2);
                  
                  longButton = new System.Windows.Controls.Button
                  {
                  Name = "LongButton", Content = "LONG", Foreground = Brushes.White, Background = Brushes.Green
                  };
                  
                  shortButton = new System.Windows.Controls.Button
                  {
                  Name = "ShortButton", Content = "SHORT", Foreground = Brushes.Black, Background = Brushes.Red
                  };
                  
                  longButton.Click += OnButtonClick;
                  shortButton.Click += OnButtonClick;
                  
                  System.Windows.Controls.Grid.SetColumn(longButton, 0);
                  System.Windows.Controls.Grid.SetColumn(shortButton , 1);
                  
                  myGrid.Children.Add(longButton);
                  myGrid.Children.Add(shortButton);
                  
                  UserControlCollection.Add(myGrid);
                  }));
                  }
                  else if (State == State.Terminated)
                  {
                  Dispatcher.InvokeAsync((() =>
                  {
                  if (myGrid != null)
                  {
                  if (longButton != null)
                  {
                  myGrid.Children.Remove(longButton);
                  longButton.Click -= OnButtonClick;
                  longButton = null;
                  }
                  if (shortButton != null)
                  {
                  myGrid.Children.Remove(shortButton);
                  shortButton.Click -= OnButtonClick;
                  shortButton = null;
                  }
                  }
                  }));
                  }
                  }
                  
                  protected override void OnBarUpdate()
                  {
                  //if(CurrentBar < BarsRequiredToTrade)
                  // return;
                  
                  
                  double pocprice;
                  [COLOR=#c0392b][B]//question: what to code to _maxPrice=pocprice [/B][/COLOR]
                  maxvolprice[0] = pocprice;
                  Print(maxvolprice[1]);
                  
                  
                  if (longButtonClicked && Position.MarketPosition != MarketPosition.Long
                  //Insert condition to place stop order 1 tick above previous bar POC
                  )
                  EnterLongLimit(maxvolprice[1] + TickSize);
                  //currbar = CurrentBar;
                  
                  if (shortButtonClicked && Position.MarketPosition != MarketPosition.Short
                  //Insert condition to place stop order 1 tick below previous bar POC
                  
                  )
                  EnterShortLimit(maxvolprice[1] - TickSize);
                  //currbar = CurrentBar;
                  
                  if(Position.MarketPosition == MarketPosition.Long && longButtonClicked && Close[0] > Position.AveragePrice + TickSize*4){
                  SetStopLoss(CalculationMode.Price, Position.AveragePrice);
                  }
                  if(Position.MarketPosition == MarketPosition.Short && shortButtonClicked && Close[0] < Position.AveragePrice - TickSize*4){
                  SetStopLoss(CalculationMode.Price, Position.AveragePrice);
                  }
                  
                  if (!longButtonClicked
                  && Position.MarketPosition == MarketPosition.Long)
                  ExitLong();
                  
                  if (!shortButtonClicked
                  && Position.MarketPosition == MarketPosition.Short)
                  ExitShort();
                  }
                  
                  private void OnButtonClick(object sender, RoutedEventArgs rea)
                  {
                  System.Windows.Controls.Button button = sender as System.Windows.Controls.Button;
                  if (button == longButton && button.Name == "LongButton" && button.Content == "LONG")
                  {
                  button.Content = "Exit L";
                  button.Name = "ExitLongButton";
                  longButtonClicked = true;
                  return;
                  }
                  
                  if (button == shortButton && button.Name == "ShortButton" && button.Content == "SHORT")
                  {
                  button.Content = "Exit S";
                  button.Name = "ExitShortButton";
                  shortButtonClicked = true;
                  return;
                  }
                  
                  if (button == longButton && button.Name == "ExitLongButton" && button.Content == "Exit L")
                  {
                  button.Content = "LONG";
                  button.Name = "LongButton";
                  longButtonClicked = false;
                  return;
                  }
                  
                  if (button == shortButton && button.Name == "ExitShortButton" && button.Content == "Exit S")
                  {
                  button.Content = "SHORT";
                  button.Name = "ShortButton";
                  shortButtonClicked = false;
                  return;
                  }
                  }
                  
                  [NinjaScriptProperty]
                  [Range(1, int.MaxValue)]
                  [Display(Name="StopLoss", Description="StopLoss Value", Order=1, GroupName="Parameters")]
                  public int StopLoss
                  { get; set; }
                  
                  [NinjaScriptProperty]
                  [Range(1, int.MaxValue)]
                  [Display(Name="ProfitTarget", Description="ProfitTarget Value", Order=2, GroupName="Parameters")]
                  public int ProfitTarget
                  { get; set; }
                  }
                  }


                  Thank you
                  Marble

                  Comment


                    #10
                    Hello Marble,

                    Can you please advise how to refer Addons and what is missing from code below?
                    ​Are you asking how to import the item that you had linked or use it?

                    That is a third party item so our support would not have any information on its use. If the script is an indicator that plots a value you may be able to use it similar to other indicators. I would suggest using the strategy builder to see if it can be used in a condition, if so you can create a single condition using the indicator and then click View Code to see the generated code for that indicators use.

                    JesseNinjaTrader Customer Service

                    Comment


                      #11
                      No that is not the point. The question is for the coding to refer the class in other file under addon file. I can not refer the maxprice in strategy builder.

                      Code in the file under Addon
                      I want to use "maxCluster" stated here.



                      Code:
                      [HASHTAG="t3322"]region[/HASHTAG] WYCKOFF_BARS_CLASS
                      
                      public class WyckoffBars : SEBars<WyckoffBars.Bar>
                      {
                      private bool isNewBar;
                      private long minClusterVolumeFilter;
                      private VolumeType volumeType;
                      private int currentBar;
                      private int lastBarLoaded;
                      private double tickSize;
                      protected Bars NT8_Bars;
                      
                      public WyckoffBars(Bars bars)
                      {
                      this.isNewBar = false;
                      this.minClusterVolumeFilter = -1;
                      this.NT8_Bars = bars;
                      this.lastBarLoaded = bars.Count - 1;
                      this.tickSize = bars.Instrument.MasterInstrument.TickSize;
                      this.currentBar = 0;
                      this[currentBar] = new Bar();
                      //DateTime dt = bars.GetTime(bars.Count - 1);
                      //this.lastBarTime = new DateTime(dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second);
                      //this.lastBarTime = this.lastBarTime.AddSeconds(-5);
                      // !- Inicializamos las barras cargadas hasta el momento
                      //for(int i = 0; i <= barsCount; i++) this[i] = new Bar();
                      }
                      
                      public class Bar : Mar****rder
                      {
                      private PriceLadder pvLadder;
                      private Mar****rder barOrderFlow;
                      private Mar****rder minCluster;
                      private Mar****rder maxCluster;
                      private double minClusterPrice;
                      private double maxClusterPrice;
                      //public DateTime Time;
                      
                      public Bar()
                      {
                      this.pvLadder = new PriceLadder();
                      this.minCluster = new Mar****rder();
                      this.maxCluster = new Mar****rder();
                      }
                      public IEnumerator<KeyValuePair<double, Mar****rder>> GetEnumerator(){
                      return pvLadder.GetEnumerator();
                      }
                      // !- la funcion recibe ordenes a mercado, por lo tanto la estructura $MarketDataEventArgs
                      // cambia de informacion continuamente; precio, bid, ask, volume....
                      public void CalculateMarketInfo(MarketDataEventArgs MarketArgs)
                      {
                      pvLadder.AddPrice(MarketArgs);
                      this.CalculateSigmaVolume(MarketArgs);
                      }
                      public void CalculateMinAndMaxCluster()
                      {
                      pvLadder.CalculateMinAndMax(ref this.minCluster, ref this.maxCluster,
                      out this.minClusterPrice, out this.maxClusterPrice);
                      }
                      public void FilterClusterVolume(long minVolume, VolumeType volType)
                      {
                      //List<double> priceRemovals = new List<double>();
                      double price;
                      foreach(var pl in pvLadder)
                      {
                      price = pl.Key;
                      switch( volType )
                      {
                      case VolumeType.BidAsk:
                      {
                      if( Math.Abs(pl.Value.Total) < minVolume ){
                      //priceRemovals.Add(pl.Key);
                      Mar****rder mo = pl.Value;
                      this.pvLadder.TryRemove(price, out mo);
                      }
                      break;
                      }
                      case VolumeType.Delta:
                      {
                      if( Math.Abs(pl.Value.Delta) < minVolume ){
                      //priceRemovals.Add(pl.Key);
                      Mar****rder mo = pl.Value;
                      this.pvLadder.TryRemove(price, out mo);
                      }
                      break;
                      }
                      }
                      
                      }​
                      Last edited by Marble; 09-22-2022, 11:03 AM.

                      Comment


                        #12
                        Hello Marble,

                        I have no knowledge of how that item works to provide that kind of detail. You could try reaching out to the developer of that item for instructions on its use.

                        To otherwise do what you are asking you can see the code in the existing VolumeProfile indicator. A dictionary would be needed to assign volumes at prices for the use you described and would be much less code than the item you linked.

                        JesseNinjaTrader Customer Service

                        Comment


                          #13
                          I am happy to rewrite the code in my own code if that is more appropriate.
                          But need to know what is wrong with my current code (in original question)

                          Comment


                            #14
                            Hello Marble,

                            I wouldn't be able to say what's wrong with the code you provided, that's a third party item so I have no details that I could provide on how to use it. You would need to contact the developer of that item to get details on how its used or how to reference parts of the code in the addon folder for use.

                            JesseNinjaTrader Customer Service

                            Comment


                              #15
                              Hi Jesse,
                              I would like to code the POC based on the volume profile indicator you have suggested.
                              But I do not know how to set "A dictionary would be needed to assign volumes at prices"
                              How to code the dictionary that you mention on top of volume profile code below?

                              Code:
                              namespace NinjaTrader.NinjaScript.Indicators
                              {
                                  public class VolumeProfile : Indicator
                                  {
                                      #region Properties
                                      internal class VolumeInfoItem
                                      {
                                          public double up;
                                          public double down;
                                          public double neutral;
                                      }
                              
                                      private double            alpha                = 50;
                                      private double            askPrice;
                                      private int                barSpacing            = 1;
                                      private double            bidPrice;
                                      private DateTime        cacheSessionEnd        = Globals.MinDate;
                                      private DateTime        currentDate            = Globals.MinDate;
                                      private bool            drawLines;
                                      private List<int>        newSessionBarIdx    = new List<int>();
                                      private DateTime        sessionDateTmp        = Globals.MinDate;
                                      private SessionIterator sessionIterator;
                                      private int                startIndexOf;
                                      private SessionIterator storedSession;
                              
                                      private List<Dictionary<double, VolumeInfoItem>>     sortedDicList   = new List<Dictionary<double, VolumeInfoItem>>();
                                      private Dictionary<double, VolumeInfoItem>             cacheDictionary = new Dictionary<double, VolumeInfoItem>();
                                      #endregion
                              
                                      protected override void OnStateChange()
                                      {
                                          if (State == State.SetDefaults)
                                          {
                                              Description                    = NinjaTrader.Custom.Resource.NinjaScriptIndicatorDescriptionVolumeProfile;
                                              Name                        = NinjaTrader.Custom.Resource.NinjaScriptIndicatorNameVolumeProfile;
                                              Calculate                    = Calculate.OnEachTick;
                                              DrawLines                    = false;
                                              IsChartOnly                    = true;
                                              IsOverlay                    = true;
                                              DrawOnPricePanel            = false;
                                              LineBrush                    = Brushes.DarkGray;
                                              VolumeDownBrush                = Brushes.Crimson;
                                              VolumeNeutralBrush            = Brushes.DarkGray;
                                              VolumeUpBrush                = Brushes.DarkCyan;
                                          }
                                          else if (State == State.Configure)
                                          {
                                              ZOrder = -1;
                                          }
                                          else if (State == State.DataLoaded)
                                          {
                                              storedSession = new SessionIterator(Bars);
                                          }
                                          else if (State == State.Historical)
                                          {
                                              if (Calculate != Calculate.OnEachTick)
                                                  Draw.TextFixed(this, "NinjaScriptInfo", string.Format(NinjaTrader.Custom.Resource.NinjaScriptOnBarCloseError, Name), TextPosition.BottomRight);
                                          }
                                      }
                              
                                      protected override void OnBarUpdate() { }
                              
                                      private DateTime GetLastBarSessionDate(DateTime time)
                                      {
                                          if (time <= cacheSessionEnd)
                                              return sessionDateTmp;
                              
                                          if (!Bars.BarsType.IsIntraday)
                                              return sessionDateTmp;
                              
                                          storedSession.GetNextSession(time, true);
                              
                                          cacheSessionEnd = storedSession.ActualSessionEnd;
                                          sessionDateTmp     = TimeZoneInfo.ConvertTime(cacheSessionEnd.AddSeconds(-1), Globals.GeneralOptions.TimeZoneInfo, Bars.TradingHours.TimeZoneInfo);
                              
                                          if(newSessionBarIdx.Count == 0 || newSessionBarIdx.Count > 0 && CurrentBar > newSessionBarIdx[newSessionBarIdx.Count - 1])
                                              newSessionBarIdx.Add(CurrentBar);
                              
                                          return sessionDateTmp;
                                      }
                              
                                      protected override void OnMarketData(MarketDataEventArgs e)
                                      {
                                          if (Bars.Count <= 0)
                                              return;
                              
                                          double            price;
                                          long            volume;
                                          VolumeInfoItem    volumeInfoItem;
                                          DateTime        lastBarTimeStamp = GetLastBarSessionDate(Time[0]);
                              
                                          if (lastBarTimeStamp != currentDate)
                                          {
                                              cacheDictionary = new Dictionary<double, VolumeInfoItem>();
                                              sortedDicList.Add(cacheDictionary);
                                          }
                              
                                          currentDate = lastBarTimeStamp;
                                          if (Bars.IsTickReplay)
                                          {
                                              if (e.MarketDataType == MarketDataType.Last)
                                              {
                                                  price    = e.Price;
                                                  volume    = e.Volume;
                              
                                                  if (!cacheDictionary.ContainsKey(price))
                                                      cacheDictionary.Add(price, new VolumeInfoItem());
                              
                                                  volumeInfoItem = cacheDictionary[price];
                              
                                                  if (price >= e.Ask)
                                                      volumeInfoItem.up        += volume;
                                                  else if (price <= e.Bid)
                                                      volumeInfoItem.down        += volume;
                                                  else
                                                      volumeInfoItem.neutral    += volume;
                                              }
                                          }
                                          else
                                          {
                                              if (e.MarketDataType == MarketDataType.Ask)
                                              {
                                                  askPrice = e.Price;
                                                  return;
                                              }
                              
                                              if (e.MarketDataType == MarketDataType.Bid)
                                              {
                                                  bidPrice = e.Price;
                                                  return;
                                              }
                              
                                              if (e.MarketDataType != MarketDataType.Last || ChartControl == null || askPrice == 0 || bidPrice == 0)
                                                  return;
                              
                                              if (Bars != null && !SessionIterator.IsInSession(Core.Globals.Now, true, true))
                                                  return;
                              
                                              price    = e.Price;
                                              volume    = e.Volume;
                              
                                              if (!cacheDictionary.ContainsKey(price))
                                                  cacheDictionary.Add(price, new VolumeInfoItem());
                              
                                              volumeInfoItem = cacheDictionary[price];
                              
                                              if (price >= askPrice)
                                                  volumeInfoItem.up        += volume;
                                              else if (price <= bidPrice)
                                                  volumeInfoItem.down        += volume;
                                              else
                                                  volumeInfoItem.neutral    += volume;
                                          }
                                      }
                              
                                      protected override void OnRender(ChartControl chartControl, ChartScale chartScale)
                                      {
                                          if(Bars == null || Bars.Instrument == null || IsInHitTest)
                                              return;
                              
                                          int        firstBarIdxToPaint    = -1;
                                          double    tickSize            = Bars.Instrument.MasterInstrument.TickSize;
                                          double    volumeMax            = 0;
                              
                                          SharpDX.Direct2D1.Brush upBrush            = VolumeUpBrush.ToDxBrush(RenderTarget);
                                          SharpDX.Direct2D1.Brush downBrush        = VolumeDownBrush.ToDxBrush(RenderTarget);
                                          SharpDX.Direct2D1.Brush neutralBrush    = VolumeNeutralBrush.ToDxBrush(RenderTarget);
                                          SharpDX.Direct2D1.Brush lineBrushDx        = LineBrush.ToDxBrush(RenderTarget);
                              
                                          upBrush.Opacity            = (float)(alpha / 100.0);
                                          downBrush.Opacity        = (float)(alpha / 100.0);
                                          neutralBrush.Opacity    = (float)(alpha / 100.0);
                              
                                          for (int i = newSessionBarIdx.Count - 1; i > 0; i--)
                                          {
                                              if (newSessionBarIdx[i] <= ChartBars.ToIndex)
                                              {
                                                  startIndexOf        = i;
                                                  firstBarIdxToPaint    = newSessionBarIdx[i];
                                                  break;
                                              }
                                          }
                              
                                          if (sortedDicList.Count < 1 && cacheDictionary.Keys.Count > 0)
                                              sortedDicList.Add(cacheDictionary);
                              
                                          foreach (Dictionary<double, VolumeInfoItem> tmpDict in sortedDicList)
                                          {
                                              foreach (KeyValuePair<double, VolumeInfoItem> keyValue in tmpDict)
                                              {
                                                  double price = keyValue.Key;
                              
                                                  if (Bars.BarsType.IsIntraday && (price > chartScale.MaxValue || price < chartScale.MinValue))
                                                      continue;
                              
                                                  VolumeInfoItem    vii        = keyValue.Value;
                                                  double            total    = vii.up + vii.down + vii.neutral;
                                                  volumeMax                = Math.Max(volumeMax, total);
                                              }
                                          }
                              
                                          if (volumeMax.ApproxCompare(0) == 0)
                                              return;
                              
                                          int viiPositions = 0;
                              
                                          foreach (KeyValuePair<double, VolumeInfoItem> keyValue in sortedDicList[startIndexOf])
                                          {
                                              viiPositions++;
                              
                                              VolumeInfoItem vii = keyValue.Value;
                              
                                              double    priceLower            = keyValue.Key - tickSize / 2;
                                              float    yLower                = chartScale.GetYByValue(priceLower);
                                              float    yUpper                = chartScale.GetYByValue(priceLower + tickSize);
                                              float    height                = Math.Max(1, Math.Abs(yUpper - yLower) - barSpacing);
                                              int        barWidthUp            = (int)((ChartPanel.W / 2) * (vii.up / volumeMax));
                                              int        barWidthNeutral        = (int)((ChartPanel.W / 2) * (vii.neutral / volumeMax));
                                              int        barWidthDown        = (int)((ChartPanel.W / 2) * (vii.down / volumeMax));
                                              float    stationaryXpos        = chartControl.GetXByBarIndex(ChartBars, !Bars.IsTickReplay ? ChartBars.FromIndex : Math.Max(ChartBars.FromIndex, firstBarIdxToPaint));
                                              float    xpos                = chartControl.GetXByBarIndex(ChartBars, !Bars.IsTickReplay ? ChartBars.FromIndex : Math.Max(1, Math.Max(ChartBars.FromIndex, firstBarIdxToPaint)) - 1);
                              
                                              RenderTarget.FillRectangle(new SharpDX.RectangleF(xpos, yUpper, barWidthUp, height), upBrush);
                                              xpos += barWidthUp;
                                              RenderTarget.FillRectangle(new SharpDX.RectangleF(xpos, yUpper, barWidthNeutral, height), neutralBrush);
                                              xpos += barWidthNeutral;
                                              RenderTarget.FillRectangle(new SharpDX.RectangleF(xpos, yUpper, barWidthDown, height), downBrush);
                              
                                              if (!drawLines)
                                                  continue;
                              
                                              // Lower line
                                              RenderTarget.DrawLine(new SharpDX.Vector2(stationaryXpos, yLower), new SharpDX.Vector2((ChartPanel.X + ChartPanel.W), yLower), lineBrushDx);
                              
                                              // Upper line (only at very top)
                                              if (viiPositions == sortedDicList[startIndexOf].Count)
                                                  RenderTarget.DrawLine(new SharpDX.Vector2(stationaryXpos, yUpper), new SharpDX.Vector2((ChartPanel.X + ChartPanel.W), yUpper), lineBrushDx);
                                          }
                              
                                          lineBrushDx.Dispose();
                                          upBrush.Dispose();
                                          downBrush.Dispose();
                                          neutralBrush.Dispose();
                                      }
                              
                              ​

                              Comment

                              Latest Posts

                              Collapse

                              Topics Statistics Last Post
                              Started by cls71, Today, 04:45 AM
                              0 responses
                              1 view
                              0 likes
                              Last Post cls71
                              by cls71
                               
                              Started by mjairg, 07-20-2023, 11:57 PM
                              3 responses
                              213 views
                              1 like
                              Last Post PaulMohn  
                              Started by TheWhiteDragon, 01-21-2019, 12:44 PM
                              4 responses
                              544 views
                              0 likes
                              Last Post PaulMohn  
                              Started by GLFX005, Today, 03:23 AM
                              0 responses
                              3 views
                              0 likes
                              Last Post GLFX005
                              by GLFX005
                               
                              Started by XXtrader, Yesterday, 11:30 PM
                              2 responses
                              12 views
                              0 likes
                              Last Post XXtrader  
                              Working...
                              X