namespace SampleSpreadHistoryTesting
{
    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.IO;
    using System.Windows;
    using System.Windows.Forms;
    using System.Windows.Media;
    using MessageBox = System.Windows.MessageBox;
    using StockSharp.Algo.Equity;
    using StockSharp.Algo.Logging;
    using StockSharp.Algo.Reporting;
    using StockSharp.Algo.Storages;
    using StockSharp.Algo.Strategies;
    using StockSharp.Algo.Testing;
    using StockSharp.BusinessEntities;
    using Ecng.Collections;
    using Ecng.Common;
    using Ecng.Serialization;
    using Ecng.Xaml;
    public partial class MainWindow
    {
        private ICollection<EquityData> _curveItems;
        private readonly LogManager _logManager = new LogManager();
        private DateTime _lastUpdateDate;
        private DateTime _startEmulationTime;
        public void LogManager()
        {
            InitializeComponent();
            _logManager.Listeners.Add(new FileLogListener("log.txt"));
        }
        private void FindPathClick(object sender, RoutedEventArgs e)
        {
            var dlg = new FolderBrowserDialog();
            if (!HistoryPath.Text.IsEmpty())
                dlg.SelectedPath = HistoryPath.Text;
            if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
            {
                HistoryPath.Text = dlg.SelectedPath;
            }
        }
        public void StartBtnClick(object sender, RoutedEventArgs e)
        {
            // создаем хранилище для работы с базой данных котировок
            var storage =
                new TradingStorage(new InMemoryStorage())
                    {
                        BasePath = HistoryPath.Text
                    };
            if (HistoryPath.Text.IsEmpty() || !Directory.Exists(HistoryPath.Text))
            {
                MessageBox.Show(this, "Неправильный путь");
                return;
            }
            // выбираем интервал времени для тестирования (таймфрейм)
            var timeFrame = TimeSpan.FromTicks(1);
            // устанавливаем период тестирования (зависит от объема данных, хранящихся по пути HistoryPath) 
            var startTime = new DateTime(2012, 1, 1);
            var stopTime = new DateTime(2012, 2, 1);
            // создаем тестовый портфель
            var portfolio =
                new Portfolio
                    {
                        BeginAmount = 1000000m,
                        Name = "Test account"
                    };
            // создаем первый инструмент спреда
            var security1 =
                new Security
                    {
                        Code = "SBER",
                        Exchange = Exchange.Test,
                        // идентификатор инструмента, по которому будет осуществлен поиск папки с историей стаканов
                        Id = "SBER@EQBR",
                        MinStepPrice = 0.01m,
                        MinStepSize = 0.01m,
                        Name = "Сбербанк России ОАО ао"
                    };
            // создаем второй инструмент спреда
            var security2 =
                new Security
                    {
                        Code = "SRH2",
                        Exchange = Exchange.Test,
                        // идентификатор инструмента, по которому будет осуществлен поиск папки с историей стаканов
                        Id = "SRH2@RTS",
                        MinStepPrice = 1,
                        MinStepSize = 1,
                        Name = "SBRF-3.12"
                    };
            // создаем стратегию для торговли спредом
            var spreadStrategy =
                new SpreadStrategy(security1, security2)
                    {
                        Security1 = security1,
                        Security2 = security2
                    };
            
            // создаем шлюз для торговли
            var trader =
                new EmulationTrader(new[] {security1, security2}, new[] {portfolio})
                    {
                        // параметр влияет на занимаемую память (в случае достаточного объема памяти лучше увеличить)
                        DaysInMemory = 2,
                        MarketTimeChangedInterval = timeFrame,
                        Storage = storage,
                        WorkingTime = Exchange.Micex.WorkingTime
                    };
            // если процесс был запущен, останавливаем его
            if (trader.State != EmulationStates.Stopped)
            {
                StartBtn.IsEnabled = false;
                spreadStrategy.Stop();
                trader.Stop();
                _logManager.Sources.Clear();
                return;
            }
            trader.DepthGenerators[security1] =
                new TrendMarketDepthGenerator(security1)
                    {
                        // время обновления стакана в базе данных для первого инструмента
                        Interval = TimeSpan.FromTicks(1)
                    };
            trader.DepthGenerators[security2] =
                new TrendMarketDepthGenerator(security2)
                    {
                        // время обновления стакана в базе данных для второго инструмента
                        Interval = TimeSpan.FromTicks(1)
                    };
            // копируем параметры на визуальную панель
            ParametersPanel.Parameters.Clear();
            ParametersPanel.Parameters.AddRange(spreadStrategy.EquityManager.Parameters);
            if (_curveItems == null)
                _curveItems = Curve.CreateCurve(spreadStrategy.Name, Colors.DarkGreen);
            else
            _curveItems.Clear();
            spreadStrategy.EquityManager.NewEquityData += data => this.GuiAsync(() => _curveItems.Add(data));
            _logManager.Sources.Add(spreadStrategy);
            // подписываемся на событие изменения времени, чтобы обновить ProgressBar
            trader.MarketTimeChanged +=
                () =>
                    {
                        // для оптимизации обновляем ProgressBar только при начале нового дня
                        if (trader.MarketTime.Date == _lastUpdateDate && trader.MarketTime < stopTime) return;
                        _lastUpdateDate = trader.MarketTime.Date;
                        this.GuiAsync(() => TestingProcess.Value = (trader.MarketTime - startTime).Ticks);
                    };
            trader.StateChanged +=
                () =>
                    {
                        switch (trader.State)
                        {
                            case EmulationStates.Stopped:
                                this.GuiAsync(
                                    () =>
                                        {
                                            StartBtn.IsEnabled = true;
                                            if (Convert.ToDecimal(TestingProcess.Value) ==
                                                Convert.ToDecimal(TestingProcess.Maximum))
                                                MessageBox.Show("Закончено за " + (DateTime.Now - _startEmulationTime));
                                            else
                                            MessageBox.Show("Отменено");
                                        });
                                break;
                            case EmulationStates.Started:
                                // запускаем стратегию, когда эмулятор запустился
                                spreadStrategy.Start();
                                break;
                        }
                    };
            // устанавливаем в визуальный элемент ProgressBar максимальное количество итераций
            TestingProcess.Maximum = (stopTime - startTime).Ticks;
            TestingProcess.Value = 0;
            Report.IsEnabled = true;
            _startEmulationTime = DateTime.Now;
            // устанавливаем соединение и запускаем экспорт
            trader.Connect();
            trader.StartExport();
            // задаем период тестирования (startTime, stopTime) и запускаем эмуляцию
            trader.Start(startTime, stopTime);
        }
        private void ReportClick(object sender, RoutedEventArgs e)
        {
            // генерируем отчет по прошедшему тестированию (Excel может тормозить из-за большого количества данных)
            new ExcelStrategyReport(ExcelStrategy, "sma.xls").Generate();
            // открываем отчет
            Process.Start("sma.xls");
        }
        public Strategy ExcelStrategy { get; set; }
    }
}