namespace SampleSMA { using System; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.ComponentModel; using System.Globalization; using System.IO; using System.Windows; using System.Windows.Forms; using MessageBox = System.Windows.MessageBox; using Ecng.Collections; using Ecng.Common; using Ecng.Xaml; using Ecng.ComponentModel; using StockSharp.Algo; using StockSharp.Algo.Logging; using StockSharp.Algo.Candles; using StockSharp.Algo.Reporting; using StockSharp.Algo.Indicators; using StockSharp.Algo.Indicators.Trend; using StockSharp.BusinessEntities; using StockSharp.Quik; using StockSharp.Xaml; using StockSharp.Algo.Testing; public partial class MainWindow { private readonly TimeSpan _timeFrame = TimeSpan.FromMinutes(5); // private QuikTrader _trader; private RealTimeEmulationTrader _trader; private SmaStrategy _strategy; private bool _isDdeStarted; // private bool _isTodaySmaDrawn; private CandleManager _candleManager; private Security _lkoh; private readonly ChartArea _area; private ChartCandleElement _candlesElem; // private ChartIndicatorElement _longMaElem; // private ChartIndicatorElement _shortMaElem; private readonly LogManager _logManager = new LogManager(); public MainWindow() { InitializeComponent(); _area = new ChartArea(); _chart.Areas.Add(_area); _logManager.Listeners.Add(new FileLogListener("log.txt")); // попробовать сразу найти месторасположение Quik по запущенному процессу Path.Text = QuikTerminal.GetDefaultPath(); } private void OrdersOrderSelected(object sender, EventArgs e) { CancelOrders.IsEnabled = !_orders.SelectedOrders.IsEmpty(); } protected override void OnClosing(CancelEventArgs e) { if (_trader != null) { if (_isDdeStarted) StopDde(); _trader.Dispose(); } base.OnClosing(e); } private void FindPathClick(object sender, RoutedEventArgs e) { var dlg = new FolderBrowserDialog(); if (!Path.Text.IsEmpty()) dlg.SelectedPath = Path.Text; if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK) { Path.Text = dlg.SelectedPath; } } private void ConnectClick(object sender, RoutedEventArgs e) { if (_trader == null || !_trader.IsConnected) { if (_trader == null) { if (Path.Text.IsEmpty()) { MessageBox.Show(this, "Путь к Quik не выбран."); return; } // создаем шлюз // _trader = new QuikTrader(Path.Text); _trader = new RealTimeEmulationTrader(new QuikTrader(Path.Text)); Portfolios.Trader = _trader; _trader.Connected += () => { _candleManager = new CandleManager(_trader); _trader.NewSecurities += securities => this.GuiAsync(() => { // находим нужную бумагу var lkoh = securities.FirstOrDefault(s => s.Code == "RIZ2"); if (lkoh != null) { _lkoh = lkoh; this.GuiAsync(() => { Start.IsEnabled = true; }); } }); //_trader.RegisterOrderLog(_lkoh); _trader.NewMyTrades += trades => this.GuiAsync(() => { if (_strategy != null) { // найти те сделки, которые совершила стратегия скользящей средней trades = trades.Where(t => _strategy.Orders.Any(o => o == t.Order)); _trades.Trades.AddRange(trades); } }); _candleManager.Processing += (series, candle) => { // если скользящие за сегодняшний день отрисованы, то рисуем в реальном времени текущие скользящие //if (_isTodaySmaDrawn) this.GuiAsync(() => ProcessCandle(candle)); }; //_trader.ProcessDataError += ex => this.Sync(() => MessageBox.Show(this, ex.ToString())); _trader.ConnectionError += ex => { if (ex != null) this.GuiAsync(() => MessageBox.Show(this, ex.ToString())); }; this.GuiAsync(() => { ConnectBtn.IsEnabled = false; ExportDde.IsEnabled = true; Report.IsEnabled = true; }); }; } _trader.Connect(); } else _trader.Disconnect(); } private void OnLog(LogMessage message) { // если стратегия вывела не просто сообщение, то вывести на экран. // if (message.Level != LogLevels.Info && message.Level != LogLevels.Debug) // this.GuiAsync(() => MessageBox.Show(this, message.Message)); } private void OnStrategyPropertyChanged(object sender, PropertyChangedEventArgs e) { this.GuiAsync(() => { Status.Content = _strategy.ProcessState; PnL.Content = _strategy.PnLManager.PnL; Slippage.Content = _strategy.SlippageManager.Slippage; Position.Content = _strategy.PositionManager.Position; Latency.Content = _strategy.LatencyManager.Latency; }); } private void StartDde() { _trader.StartExport(); _isDdeStarted = true; } private void StopDde() { _trader.StopExport(); _isDdeStarted = false; } private void ExportDdeClick(object sender, RoutedEventArgs e) { if (_isDdeStarted) StopDde(); else StartDde(); } private void CancelOrdersClick(object sender, RoutedEventArgs e) { _orders.SelectedOrders.ForEach(_trader.CancelOrder); } private void StartClick(object sender, RoutedEventArgs e) { if (_strategy == null) { if (Portfolios.SelectedPortfolio == null) { MessageBox.Show(this, "Портфель не выбран."); return; } // регистрируем наш тайм-фрейм var series = new CandleSeries(typeof(TimeFrameCandle), _lkoh, _timeFrame); // создаем торговую стратегию, скользящие средние на 80 5-минуток и 10 5-минуток _strategy = new SmaStrategy(series, new SimpleMovingAverage { Length = 5 }, new SimpleMovingAverage { Length = 3 }) { Volume = 1, Security = _lkoh, Portfolio = Portfolios.SelectedPortfolio, Trader = _trader, }; _strategy.Log += OnLog; _strategy.PropertyChanged += OnStrategyPropertyChanged; //Добавление стратегии в менеджер логирования _logManager.Sources.Add(_strategy); // _logManager.Sources.Add(_trader); _candlesElem = new ChartCandleElement(); _area.Elements.Add(_candlesElem); //_longMaElem = new ChartIndicatorElement //{ // Title = "Длинная", // Indicator = _strategy.LongSma, //}; //_area.Elements.Add(_longMaElem); //_shortMaElem = new ChartIndicatorElement //{ // Title = "Короткая", // Indicator = _strategy.ShortSma, //}; //_area.Elements.Add(_shortMaElem); //IEnumerable candles = CultureInfo.InvariantCulture.DoInCulture(() => File.ReadAllLines("LKOH_history.txt").Select(line => //{ // var parts = line.Split(','); // var time = (parts[0] + parts[1]).ToDateTime("yyyyMMddHHmmss"); // return (Candle)new TimeFrameCandle // { // OpenPrice = parts[2].To(), // HighPrice = parts[3].To(), // LowPrice = parts[4].To(), // ClosePrice = parts[5].To(), // TimeFrame = _timeFrame, // OpenTime = time, // CloseTime = time + _timeFrame, // TotalVolume = parts[6].To(), // Security = _lkoh, // }; //}).ToArray()); // var lastCandleTime = default(DateTime); // начинаем вычислять скользящие средние //foreach (var candle in candles) //{ // ProcessCandle(candle); // lastCandleTime = candle.OpenTime; //} _candleManager.Start(series); // вычисляем временные отрезки текущей свечки //var bounds = _timeFrame.GetCandleBounds(series.Security); //var candles = _candleManager.Container.GetCandles(series, new Range(lastCandleTime + _timeFrame, bounds.Min)); //foreach (var candle in candles) //{ // ProcessCandle(candle); //} //_isTodaySmaDrawn = true; Report.IsEnabled = true; } if (_strategy.ProcessState == ProcessStates.Stopped) { // запускаем процесс получения стакана, необходимый для работы алгоритма котирования _trader.RegisterTrades(_strategy.Security); _trader.RegisterMarketDepth(_strategy.Security); _trader.MarketEmulator.Settings.UseMarketDepth = true; _strategy.Start(); Start.Content = "Стоп"; } else { _trader.UnRegisterTrades(_strategy.Security); _trader.UnRegisterMarketDepth(_strategy.Security); _strategy.Stop(); Start.Content = "Старт"; } } private void ProcessCandle(Candle candle) { //var longValue = candle.State == CandleStates.Finished ? _strategy.LongSma.Process((DecimalIndicatorValue)candle.ClosePrice) : null; //var shortValue = candle.State == CandleStates.Finished ? _strategy.ShortSma.Process((DecimalIndicatorValue)candle.ClosePrice) : null; _chart.ProcessValues(candle.OpenTime, new Dictionary { { _candlesElem, candle }, //{ _longMaElem, longValue }, //{ _shortMaElem, shortValue }, }); } private void ReportClick(object sender, RoutedEventArgs e) { // сгерерировать отчет по прошедшему тестированию new ExcelStrategyReport(_strategy, "sma.xls").Generate(); // открыть отчет //Process.Start("sma.xls"); } } }