Charting to build custom chart
Atom
8/8/2017


Hi

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?



Thanks:




5 Answers
Mikhail Sukhov

Avatar
Articles author Programmer Trader
Date: 8/9/2017
Reply


Hello,

Please see our documentation http://doc.stocksharp.co...1d-af29-cf80b633db3c.htm
Thanks:

np74

Avatar
Date: 8/9/2017
Reply


Hi

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.

It will be very helpful if you could give some pointers - what method or which area i need to look

thanks
Topic starter
Thanks:

Mikhail Sukhov

Avatar
Articles author Programmer Trader
Date: 8/14/2017
Reply


Hello,

Please see the section http://doc.stocksharp.co...1d-af29-cf80b633db3c.htm There is description how to work with Chart component.
Thanks:

np74

Avatar
Date: 8/15/2017
Reply


Hi

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


public partial class MainWindow
{
public ObservableCollection<Order> Orders { get; }

private ChartArea _area;
private ChartCandleElement _candleElement;
private ChartCandleElement _pnfCandleElement;
private ChartActiveOrdersElement _activeOrdersElement;
private TimeFrameCandle _candle;

private readonly DispatcherTimer _chartUpdateTimer = new DispatcherTimer();
private readonly SynchronizedDictionary<DateTimeOffset, TimeFrameCandle> _updatedCandles = new SynchronizedDictionary<DateTimeOffset, TimeFrameCandle>();
private readonly CachedSynchronizedList<TimeFrameCandle> _allCandles = new CachedSynchronizedList<TimeFrameCandle>();
private readonly Dictionary<Order, ChartActiveOrderInfo> _chartOrderInfos = new Dictionary<Order, ChartActiveOrderInfo>();

private const decimal _priceStep = 10m;
private const int _timeframe = 1;

private bool NeedToDelay => _chkDelay.IsChecked == true;
private bool NeedToFail => _chkFail.IsChecked == true;
private bool NeedToConfirm => _chkConfirm.IsChecked == true;

private static readonly TimeSpan _delay = TimeSpan.FromSeconds(2);

private readonly Security _security = new Security
{
Id = "RIZ2@FORTS",
PriceStep = _priceStep,
Board = ExchangeBoard.Forts
};

private readonly ThreadSafeObservableCollection<Portfolio> _portfolios = new ThreadSafeObservableCollection<Portfolio>(new ObservableCollectionEx<Portfolio>
{
new Portfolio
{
Name = "Test portfolio"
}
});

private PnFArg _pngArg = new PnFArg()
{
BoxSize = 20,
ReversalAmount = 3
};
public MainWindow()
{
ConfigManager.RegisterService(_portfolios);

Orders = new ObservableCollection<Order>();
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(@"..\..\..\..\Testing\HistoryData\".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 = "Candles"
};
Chart.AddElement(_area, _candleElement, series);

_pnfCandleElement = new ChartCandleElement
{
FullTitle = "PNF"
};
Chart.AddElement(_area, _pnfCandleElement, pnfSeries);

_activeOrdersElement = new ChartActiveOrdersElement
{
FullTitle = "Active orders"
};
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(() =>
{
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(() =>
{
BusyIndicator.BusyContent = date.ToString();
});

maxDays--;

if (maxDays == 0)
break;
}
}
})
.ContinueWith(t =>
{
if (t.Exception != null)
Error(t.Exception.Message);

this.GuiAsync(() =>
{
BusyIndicator.IsBusy = false;
Chart.IsAutoRange = false;
_area.YAxises.First().AutoRange = false;

Log($"Loaded {_allCandles.Count} candles");
});

}, TaskScheduler.FromCurrentSynchronizationContext());
}

private void ChartUpdateTimerOnTick(object sender, EventArgs eventArgs)
{
TimeFrameCandle[] candlesToUpdate;

lock (_updatedCandles.SyncRoot)
{
candlesToUpdate = _updatedCandles.OrderBy(p => p.Key).Select(p => p.Value).ToArray();
_updatedCandles.Clear();
}

var lastCandle = _allCandles.LastOrDefault();
_allCandles.AddRange(candlesToUpdate.Where(c => 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 >= _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 <= _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 <= _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 >= _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 >= _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 < _candle.OpenTime)
throw new InvalidOperationException("invalid time");

if (price > _candle.HighPrice)
_candle.HighPrice = price;

if (price < _candle.LowPrice)
_candle.LowPrice = price;

_candle.ClosePrice = price;

_candle.TotalVolume += tick.TradeVolume.Value;

lock (_updatedCandles.SyncRoot)
_updatedCandles[_candle.OpenTime] = _candle;
}
Topic starter
Thanks:

np74

Avatar
Date: 8/21/2017
Reply


Hi

can you please tell if stocksharp chart are capable to draw point and figure chart?


Also if possible can you please share some pseudo code or something to draw pnf chart?

Thanks
Topic starter
Thanks:


Attach files by dragging & dropping, , or pasting from the clipboard.

loading
clippy