﻿<?xml version="1.0" encoding="utf-8"?>
<?xml-stylesheet type='text/css' href='https://stocksharp.ru/css/style.css'?>
<?xml-stylesheet type='text/css' href='https://stocksharp.ru/css/bbeditor.css'?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title type="html">Charting to build custom chart</title>
  <id>~/topic/8481/charting-to-build-custom-chart/</id>
  <rights type="text">Copyright @ StockSharp Platform LLC 2010 - 2025</rights>
  <updated>2026-06-10T11:36:46Z</updated>
  <logo>https://stocksharp.ru/images/logo.png</logo>
  <link href="https://stocksharp.ru/handlers/atom.ashx?category=topic&amp;id=8481" rel="self" type="application/rss+xml" />
  <entry>
    <id>https://stocksharp.ru/posts/m/40651/</id>
    <title type="text">Hi can you please tell if stocksharp chart are capable to draw point and figure chart? Also if possi...</title>
    <published>2017-08-21T16:58:47Z</published>
    <updated>2017-08-21T16:58:47Z</updated>
    <author>
      <name>np74</name>
      <uri>https://stocksharp.ru/users/96813/</uri>
      <email>info@stocksharp.ru</email>
    </author>
    <content type="html">&lt;p&gt;Hi&lt;/p&gt;
&lt;p&gt;can you please tell if stocksharp chart are capable to draw point and figure chart?&lt;/p&gt;
&lt;p&gt;Also if possible can you please share some pseudo code or something to draw pnf chart?&lt;/p&gt;
&lt;p&gt;Thanks&lt;/p&gt;
</content>
    <rights type="html">Copyright @ StockSharp Platform LLC 2010 - 2025</rights>
  </entry>
  <entry>
    <id>https://stocksharp.ru/posts/m/40616/</id>
    <title type="text">Hi I just modified existing sample SampleChartActivOrders as follows to show the pnf chart but i don...</title>
    <published>2017-08-15T00:05:12Z</published>
    <updated>2017-08-15T00:05:12Z</updated>
    <author>
      <name>np74</name>
      <uri>https://stocksharp.ru/users/96813/</uri>
      <email>info@stocksharp.ru</email>
    </author>
    <content type="html">&lt;p&gt;Hi&lt;/p&gt;
&lt;p&gt;I just modified existing sample SampleChartActivOrders as follows to show the pnf chart but i dont see it can you see why? i cant see candle chart though&lt;/p&gt;
&lt;p&gt;public partial class MainWindow
{
public ObservableCollection&lt;Order&gt; Orders { get; }&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;	private ChartArea _area;
	private ChartCandleElement _candleElement;
    private ChartCandleElement _pnfCandleElement;
    private ChartActiveOrdersElement _activeOrdersElement;
	private TimeFrameCandle _candle;

	private readonly DispatcherTimer _chartUpdateTimer = new DispatcherTimer();
	private readonly SynchronizedDictionary&amp;lt;DateTimeOffset, TimeFrameCandle&amp;gt; _updatedCandles = new SynchronizedDictionary&amp;lt;DateTimeOffset, TimeFrameCandle&amp;gt;();
	private readonly CachedSynchronizedList&amp;lt;TimeFrameCandle&amp;gt; _allCandles = new CachedSynchronizedList&amp;lt;TimeFrameCandle&amp;gt;();
	private readonly Dictionary&amp;lt;Order, ChartActiveOrderInfo&amp;gt; _chartOrderInfos = new Dictionary&amp;lt;Order, ChartActiveOrderInfo&amp;gt;();

	private const decimal _priceStep = 10m;
	private const int _timeframe = 1;

	private bool NeedToDelay =&amp;gt; _chkDelay.IsChecked == true;
	private bool NeedToFail =&amp;gt; _chkFail.IsChecked == true;
	private bool NeedToConfirm =&amp;gt; _chkConfirm.IsChecked == true;

	private static readonly TimeSpan _delay = TimeSpan.FromSeconds(2);

	private readonly Security _security = new Security
	{
		Id = &amp;quot;RIZ2@FORTS&amp;quot;,
		PriceStep = _priceStep,
		Board = ExchangeBoard.Forts
	};

	private readonly ThreadSafeObservableCollection&amp;lt;Portfolio&amp;gt; _portfolios = new ThreadSafeObservableCollection&amp;lt;Portfolio&amp;gt;(new ObservableCollectionEx&amp;lt;Portfolio&amp;gt;
	{
		new Portfolio
		{
			Name = &amp;quot;Test portfolio&amp;quot;
		}
	});

    private PnFArg _pngArg = new PnFArg()
    {
        BoxSize = 20,
        ReversalAmount = 3
    };
    public MainWindow()
	{
		ConfigManager.RegisterService(_portfolios);

		Orders = new ObservableCollection&amp;lt;Order&amp;gt;();
		InitializeComponent();
		Loaded += OnLoaded;

		Chart.OrderSettings.Security = _security;
		Chart.OrderSettings.Portfolio = _portfolios.First();
		Chart.OrderSettings.Volume = 5;

		_chartUpdateTimer.Interval = TimeSpan.FromMilliseconds(10000);
		_chartUpdateTimer.Tick += ChartUpdateTimerOnTick;
		_chartUpdateTimer.Start();
	}

	private void OnLoaded(object sender, RoutedEventArgs routedEventArgs)
	{
		InitCharts();
		LoadData(@&amp;quot;..\..\..\..\Testing\HistoryData\&amp;quot;.ToFullPath());
	}

	private void InitCharts()
	{
		Chart.ClearAreas();
		Chart.OrderCreationMode = true;

		_area = new ChartArea();

		var yAxis = _area.YAxises.First();

		yAxis.AutoRange = true;
		Chart.IsAutoRange = true;
		Chart.IsAutoScroll = true;

		Chart.AddArea(_area);

		var series = new CandleSeries(
			typeof(TimeFrameCandle),
			_security,
			TimeSpan.FromMinutes(_timeframe));


       

        var pnfSeries = new CandleSeries(
            typeof(PnFCandle),
            _security,
            _pngArg);

        _candleElement = new ChartCandleElement
        {
            FullTitle = &amp;quot;Candles&amp;quot;
        };
        Chart.AddElement(_area, _candleElement, series);

        _pnfCandleElement = new ChartCandleElement
        {
            FullTitle = &amp;quot;PNF&amp;quot;
        };
        Chart.AddElement(_area, _pnfCandleElement, pnfSeries);

        _activeOrdersElement = new ChartActiveOrdersElement
		{
			FullTitle = &amp;quot;Active orders&amp;quot;
		};
		Chart.AddElement(_area, _activeOrdersElement);
	}

	private void LoadData(string path)
	{
		_candle = null;
		_allCandles.Clear();

		Chart.Reset(new IChartElement[] { _candleElement, _activeOrdersElement });
        //Chart.Reset(new IChartElement[] { _pnfCandleElement, _activeOrdersElement });

        var storage = new StorageRegistry();

		var maxDays = 2;

		BusyIndicator.IsBusy = true;

		Task.Factory.StartNew(() =&amp;gt;
		{
			var date = DateTime.MinValue;

			foreach (var tick in storage.GetTickMessageStorage(_security, new LocalMarketDataDrive(path)).Load())
			{
				AppendTick(_security, tick);

				if (date != tick.ServerTime.Date)
				{
					date = tick.ServerTime.Date;

					this.GuiAsync(() =&amp;gt;
					{
						BusyIndicator.BusyContent = date.ToString();
					});

					maxDays--;

					if (maxDays == 0)
						break;
				}
			}
		})
		.ContinueWith(t =&amp;gt;
		{
			if (t.Exception != null)
				Error(t.Exception.Message);

			this.GuiAsync(() =&amp;gt;
			{
				BusyIndicator.IsBusy = false;
				Chart.IsAutoRange = false;
				_area.YAxises.First().AutoRange = false;

				Log($&amp;quot;Loaded {_allCandles.Count} candles&amp;quot;);
			});

		}, TaskScheduler.FromCurrentSynchronizationContext());
	}

	private void ChartUpdateTimerOnTick(object sender, EventArgs eventArgs)
	{
		TimeFrameCandle[] candlesToUpdate;

		lock (_updatedCandles.SyncRoot)
		{
			candlesToUpdate = _updatedCandles.OrderBy(p =&amp;gt; p.Key).Select(p =&amp;gt; p.Value).ToArray();
			_updatedCandles.Clear();
		}

		var lastCandle = _allCandles.LastOrDefault();
		_allCandles.AddRange(candlesToUpdate.Where(c =&amp;gt; lastCandle == null || c.OpenTime != lastCandle.OpenTime));

		var data = new ChartDrawData();
        PnFCandle prevCandle = null;
        foreach (var candle in candlesToUpdate)
        {
            if(prevCandle ==null)
            {
                PnFCandle newCandle = new PnFCandle()
                {
                    Security = candle.Security,
                    CloseTime = candle.CloseTime,
                    HighTime = candle.HighTime,
                    OpenTime   = candle.OpenTime,
                    ClosePrice = candle.ClosePrice,
                    OpenPrice = candle.OpenPrice,
                    HighPrice = candle.HighPrice,
                    LowPrice = candle.LowPrice,
                    TotalVolume = candle.TotalVolume,

               
                };
                newCandle.PnFArg = _pngArg;
                newCandle.Type = PnFTypes.X;
                prevCandle = newCandle;
                data.Group(candle.OpenTime).Add(_pnfCandleElement, newCandle);
            }
            else
            {
                if( prevCandle.Type == PnFTypes.X)
                {
                    if( candle.ClosePrice - prevCandle.ClosePrice &amp;gt;=  _pngArg.BoxSize)
                    {
                        PnFCandle newCandle = new PnFCandle()
                        {
                            Security = candle.Security,
                            CloseTime = candle.CloseTime,
                            HighTime = candle.HighTime,
                            OpenTime = candle.OpenTime,
                            ClosePrice = candle.ClosePrice,
                            OpenPrice = candle.OpenPrice,
                            HighPrice = candle.HighPrice,
                            LowPrice = candle.LowPrice,
                            TotalVolume = candle.TotalVolume,
                            PnFArg = _pngArg,
                            Type = PnFTypes.X,
                        };
                        prevCandle = newCandle;
                        data.Group(candle.OpenTime).Add(_pnfCandleElement, newCandle);
                    }
                    else if(candle.ClosePrice - prevCandle.ClosePrice &amp;lt;= _pngArg.BoxSize * _pngArg.ReversalAmount)
                    {
                        PnFCandle newCandle = new PnFCandle()
                        {
                            Security = candle.Security,
                            CloseTime = candle.CloseTime,
                            HighTime = candle.HighTime,
                            OpenTime = candle.OpenTime,
                            ClosePrice = candle.ClosePrice,
                            OpenPrice = candle.OpenPrice,
                            HighPrice = candle.HighPrice,
                            LowPrice = candle.LowPrice,
                            TotalVolume = candle.TotalVolume,
                            PnFArg = _pngArg,
                            Type = PnFTypes.O,
                        };
                        prevCandle = newCandle;
                        data.Group(candle.OpenTime).Add(_pnfCandleElement, newCandle);
                    }

                }
                else if (prevCandle.Type == PnFTypes.O)
                {
                    if (candle.ClosePrice - prevCandle.ClosePrice &amp;lt;= _pngArg.BoxSize)
                    {
                        PnFCandle newCandle = new PnFCandle()
                        {
                            Security = candle.Security,
                            CloseTime = candle.CloseTime,
                            HighTime = candle.HighTime,
                            OpenTime = candle.OpenTime,
                            ClosePrice = candle.ClosePrice,
                            OpenPrice = candle.OpenPrice,
                            HighPrice = candle.HighPrice,
                            LowPrice = candle.LowPrice,
                            TotalVolume = candle.TotalVolume,
                            PnFArg = _pngArg,
                            Type = PnFTypes.O,
                        };
                        prevCandle = newCandle;
                        data.Group(candle.OpenTime).Add(_pnfCandleElement, newCandle);
                    }
                    else if (candle.ClosePrice - prevCandle.ClosePrice &amp;gt;= _pngArg.BoxSize * _pngArg.ReversalAmount)
                    {
                        PnFCandle newCandle = new PnFCandle()
                        {
                            Security = candle.Security,
                            CloseTime = candle.CloseTime,
                            HighTime = candle.HighTime,
                            OpenTime = candle.OpenTime,
                            ClosePrice = candle.ClosePrice,
                            OpenPrice = candle.OpenPrice,
                            HighPrice = candle.HighPrice,
                            LowPrice = candle.LowPrice,
                            TotalVolume = candle.TotalVolume,
                            PnFArg = _pngArg,
                            Type = PnFTypes.X,
                        };
                        prevCandle = newCandle;
                        data.Group(candle.OpenTime).Add(_pnfCandleElement, newCandle);
                    }

                }
            }               
        }

		Chart.Draw(data);
	}

	private void AppendTick(Security security, ExecutionMessage tick)
	{
		var time = tick.ServerTime;
		var price = tick.TradePrice.Value;

		if (_candle == null || time &amp;gt;= _candle.CloseTime)
		{
			if (_candle != null)
			{
				_candle.State = CandleStates.Finished;
				lock (_updatedCandles.SyncRoot)
					_updatedCandles[_candle.OpenTime] = _candle;
			}

			var tf = TimeSpan.FromMinutes(_timeframe);
			var bounds = tf.GetCandleBounds(time, _security.Board);
			_candle = new TimeFrameCandle
			{
				TimeFrame = tf,
				OpenTime = bounds.Min,
				CloseTime = bounds.Max,
				Security = security,
			};

			_candle.OpenPrice = _candle.HighPrice = _candle.LowPrice = _candle.ClosePrice = price;
		}

		if (time &amp;lt; _candle.OpenTime)
			throw new InvalidOperationException(&amp;quot;invalid time&amp;quot;);

		if (price &amp;gt; _candle.HighPrice)
			_candle.HighPrice = price;

		if (price &amp;lt; _candle.LowPrice)
			_candle.LowPrice = price;

		_candle.ClosePrice = price;

		_candle.TotalVolume += tick.TradeVolume.Value;

		lock (_updatedCandles.SyncRoot)
			_updatedCandles[_candle.OpenTime] = _candle;
	}
&lt;/code&gt;&lt;/pre&gt;
</content>
    <rights type="html">Copyright @ StockSharp Platform LLC 2010 - 2025</rights>
  </entry>
  <entry>
    <id>https://stocksharp.ru/posts/m/40614/</id>
    <title type="text">Hello, Please see the section http://doc.stocksharp.com/html/956b3163-c537-4e1d-af29-cf80b633db3c.ht...</title>
    <published>2017-08-14T11:25:11Z</published>
    <updated>2017-08-14T11:25:11Z</updated>
    <author>
      <name>Mikhail Sukhov</name>
      <uri>https://stocksharp.ru/users/201/</uri>
      <email>info@stocksharp.ru</email>
    </author>
    <content type="html">&lt;p&gt;Hello,&lt;/p&gt;
&lt;p&gt;Please see the section &lt;a href="http://doc.stocksharp.com/html/956b3163-c537-4e1d-af29-cf80b633db3c.htm"&gt;http://doc.stocksharp.com/html/956b3163-c537-4e1d-af29-cf80b633db3c.htm&lt;/a&gt; There is description how to work with Chart component.&lt;/p&gt;
</content>
    <rights type="html">Copyright @ StockSharp Platform LLC 2010 - 2025</rights>
  </entry>
  <entry>
    <id>https://stocksharp.ru/posts/m/40602/</id>
    <title type="text">Hi Thanks for response. I did looked at it but really didnt understood how do i customize it ? The D...</title>
    <published>2017-08-09T18:20:20Z</published>
    <updated>2017-08-09T18:20:20Z</updated>
    <author>
      <name>np74</name>
      <uri>https://stocksharp.ru/users/96813/</uri>
      <email>info@stocksharp.ru</email>
    </author>
    <content type="html">&lt;p&gt;Hi&lt;/p&gt;
&lt;p&gt;Thanks for response. I did looked at it but really didnt understood how do i customize it ? The DrawStyle got few possible values but what i am trying is not available as DrawStyle.&lt;/p&gt;
&lt;p&gt;It will be very helpful if you could give some pointers - what method or which area i need to look&lt;/p&gt;
&lt;p&gt;thanks&lt;/p&gt;
</content>
    <rights type="html">Copyright @ StockSharp Platform LLC 2010 - 2025</rights>
  </entry>
  <entry>
    <id>https://stocksharp.ru/posts/m/40601/</id>
    <title type="text">Hello, Please see our documentation http://doc.stocksharp.com/html/956b3163-c537-4e1d-af29-cf80b633d...</title>
    <published>2017-08-09T11:40:49Z</published>
    <updated>2017-08-09T11:40:49Z</updated>
    <author>
      <name>Mikhail Sukhov</name>
      <uri>https://stocksharp.ru/users/201/</uri>
      <email>info@stocksharp.ru</email>
    </author>
    <content type="html">&lt;p&gt;Hello,&lt;/p&gt;
&lt;p&gt;Please see our documentation &lt;a href="http://doc.stocksharp.com/html/956b3163-c537-4e1d-af29-cf80b633db3c.htm"&gt;http://doc.stocksharp.com/html/956b3163-c537-4e1d-af29-cf80b633db3c.htm&lt;/a&gt;&lt;/p&gt;
</content>
    <rights type="html">Copyright @ StockSharp Platform LLC 2010 - 2025</rights>
  </entry>
  <entry>
    <id>https://stocksharp.ru/posts/m/40597/</id>
    <title type="text">Hi I looked at your charting sample and i am interested in building point and figure charts, can you...</title>
    <published>2017-08-08T16:34:53Z</published>
    <updated>2017-08-08T16:34:53Z</updated>
    <author>
      <name>np74</name>
      <uri>https://stocksharp.ru/users/96813/</uri>
      <email>info@stocksharp.ru</email>
    </author>
    <content type="html">&lt;p&gt;Hi&lt;/p&gt;
&lt;p&gt;I looked at your charting sample and i am interested in building point and figure charts, can you please guide how can i do it , is it possible to override chart.draw to do custom drawing?&lt;/p&gt;
</content>
    <rights type="html">Copyright @ StockSharp Platform LLC 2010 - 2025</rights>
  </entry>
</feed>