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 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;
}