/// <summary>
        /// Запуск оптимизаций
        /// </summary>
        /// <param name="optimiserInputData">Входные данные для оптимизатора</param>
        /// <param name="isAppend">Флаг - нужно ли дополнять файл ?</param>
        /// <param name="dirPrefix">Префикс директории</param>
        public async void StartOptimisation(OptimiserInputData optimiserInputData, bool isAppend, string dirPrefix, List <string> assets)
        {
            if (assets.Count == 0)
            {
                ThrowException("Fill in asset name");
                OnPropertyChanged("ResumeEnablingTogle");
                return;
            }


            await Task.Run(() =>
            {
                try
                {
                    if (optimiserInputData.OptimisationMode == ENUM_OptimisationMode.Disabled &&
                        assets.Count > 1)
                    {
                        throw new Exception("For test there mast be selected only one asset");
                    }
                    StopOptimisationTougle = false;

                    bool doWhile()
                    {
                        if (assets.Count == 0 || StopOptimisationTougle)
                        {
                            return(false);
                        }

                        optimiserInputData.Symb   = assets.First();
                        LoadingOptimisationTougle = assets.Count == 1;

                        assets.Remove(assets.First());

                        return(true);
                    }

                    while (doWhile())
                    {
                        var data = optimiserInputData; // Copy input data
                        StartOptimisation(data, isAppend, dirPrefix);
                    }
                }
                catch (Exception e)
                {
                    LoadingOptimisationTougle = true;
                    OnPropertyChanged("ResumeEnablingTogle");
                    ThrowException?.Invoke(e.Message);
                }
            });
        }
        /// <summary>
        /// Запуск тестов
        /// </summary>
        /// <param name="optimiserInputData">Взодные данные для тестера</param>
        public async void StartTest(OptimiserInputData optimiserInputData)
        {
            // Проверка не запущен ли терминалл
            if (Optimiser.TerminalManager.IsActive)
            {
                ThrowException("Terminal already running");
                return;
            }

            // Задаем диаппазон дат
            #region From/Forward/To
            DateTime Forward  = new DateTime();
            DateTime ToDate   = Forward;
            DateTime FromDate = Forward;

            // Проверка на количество переданных дат. Максимум одна историческая и одна форвардная
            if (optimiserInputData.HistoryBorders.Count > 1 ||
                optimiserInputData.ForwardBorders.Count > 1)
            {
                ThrowException("For test there mast be from 1 to 2 date borders");
                OnPropertyChanged("ResumeEnablingTogle");
                return;
            }

            // Если передана и историческая и форвардная даты
            if (optimiserInputData.HistoryBorders.Count == 1 &&
                optimiserInputData.ForwardBorders.Count == 1)
            {
                // Тестируем на корректность заданного промежутка
                DateBorders _Forward = optimiserInputData.ForwardBorders[0];
                DateBorders _History = optimiserInputData.HistoryBorders[0];

                if (_History > _Forward)
                {
                    ThrowException("History optimisation mast be less than Forward");
                    OnPropertyChanged("ResumeEnablingTogle");
                    return;
                }

                // Запоминаем даты
                Forward  = _Forward.From;
                FromDate = _History.From;
                ToDate   = (_History.Till < _Forward.Till ? _Forward.Till : _History.Till);
            }
            else // Если передана лишь форвардная или же лишь историческая дата
            {
                // Созраняем их и считаем что это была историческая дата (даже если была передана форвардная)
                if (optimiserInputData.HistoryBorders.Count > 0)
                {
                    FromDate = optimiserInputData.HistoryBorders[0].From;
                    ToDate   = optimiserInputData.HistoryBorders[0].Till;
                }
                else
                {
                    FromDate = optimiserInputData.ForwardBorders[0].From;
                    ToDate   = optimiserInputData.ForwardBorders[0].Till;
                }
            }
            #endregion

            PBUpdate("Start test", 100);

            // Запукаем тест во вторичном потоке
            await Task.Run(() =>
            {
                try
                {
                    // Создаем файл с настройкамит эксперта
                    #region Create (*.set) file
                    FileInfo file = new FileInfo(Path.Combine(Optimiser
                                                              .TerminalManager
                                                              .TerminalChangeableDirectory
                                                              .GetDirectory("MQL5")
                                                              .GetDirectory("Profiles")
                                                              .GetDirectory("Tester")
                                                              .FullName, $"{Path.GetFileNameWithoutExtension(optimiserInputData.RelativePathToBot)}.set"));

                    List <ParamsItem> botParams = new List <ParamsItem>(GetBotParams(optimiserInputData.RelativePathToBot, false));

                    // Заполняем настройки эксперта теми что были введены в графическом интерфейсе
                    for (int i = 0; i < optimiserInputData.BotParams.Count; i++)
                    {
                        var item = optimiserInputData.BotParams[i];

                        int ind = botParams.FindIndex(x => x.Variable == item.Variable);
                        if (ind != -1)
                        {
                            var param      = botParams[ind];
                            param.Value    = item.Value;
                            botParams[ind] = param;
                        }
                    }

                    // Созраянем настройки в файл
                    SetFileManager setFile = new SetFileManager(file.FullName, false)
                    {
                        Params = botParams
                    };
                    setFile.SaveParams();
                    #endregion

                    // Создаем конфиг терминала
                    #region Create config file
                    Config config = new Config(Optimiser.TerminalManager
                                               .TerminalChangeableDirectory
                                               .GetDirectory("config")
                                               .GetFiles("common.ini")
                                               .First().FullName);
                    config = config.DublicateFile(Path.Combine(workingDirectory.WDRoot.FullName, $"{Optimiser.TerminalManager.TerminalID}.ini"));

                    config.Tester.Currency         = optimiserInputData.Currency;
                    config.Tester.Deposit          = optimiserInputData.Balance;
                    config.Tester.ExecutionMode    = optimiserInputData.ExecutionDelay;
                    config.Tester.Expert           = optimiserInputData.RelativePathToBot;
                    config.Tester.ExpertParameters = setFile.FileInfo.Name;
                    config.Tester.ForwardMode      = (Forward == new DateTime() ? ENUM_ForvardMode.Disabled : ENUM_ForvardMode.Custom);
                    if (config.Tester.ForwardMode == ENUM_ForvardMode.Custom)
                    {
                        config.Tester.ForwardDate = Forward;
                    }
                    else
                    {
                        config.DeleteKey(ENUM_SectionType.Tester, "ForwardDate");
                    }
                    config.Tester.FromDate         = FromDate;
                    config.Tester.ToDate           = ToDate;
                    config.Tester.Leverage         = $"1:{optimiserInputData.Laverage}";
                    config.Tester.Model            = optimiserInputData.Model;
                    config.Tester.Optimization     = ENUM_OptimisationMode.Disabled;
                    config.Tester.Period           = optimiserInputData.TF;
                    config.Tester.ShutdownTerminal = false;
                    config.Tester.Symbol           = optimiserInputData.Symb;
                    config.Tester.Visual           = false;
                    #endregion

                    // Конфигурируем терминалл и запускаем его
                    Optimiser.TerminalManager.WindowStyle = System.Diagnostics.ProcessWindowStyle.Normal;
                    Optimiser.TerminalManager.Config      = config;
                    Optimiser.TerminalManager.Run();

                    // Ожидаем закрытие терминала
                    Optimiser.TerminalManager.WaitForStop();
                }
                catch (Exception e)
                {
                    ThrowException(e.Message);
                }

                OnPropertyChanged("StopTest");
            });
        }
        private void StartOptimisation(OptimiserInputData optimiserInputData, bool isAppend, string dirPrefix)
        {
            if ((optimiserInputData.HistoryBorders.Count == 0 && optimiserInputData.ForwardBorders.Count == 0))
            {
                ThrowException("Fill in date borders");
                OnPropertyChanged("ResumeEnablingTogle");
                return;
            }

            if (Optimiser.TerminalManager.IsActive)
            {
                ThrowException("Terminal already running");
                return;
            }

            if (optimiserInputData.OptimisationMode == ENUM_OptimisationMode.Disabled)
            {
                StartTest(optimiserInputData);
                return;
            }

            if (!isAppend)
            {
                var dir = workingDirectory.GetOptimisationDirectory(optimiserInputData.Symb,
                                                                    Path.GetFileNameWithoutExtension(optimiserInputData.RelativePathToBot),
                                                                    dirPrefix, Optimiser.Name);
                List <FileInfo> data = dir.GetFiles().ToList();
                data.ForEach(x => x.Delete());
                List <DirectoryInfo> dirData = dir.GetDirectories().ToList();
                dirData.ForEach(x => x.Delete());
            }

            Optimiser.CloseSettingsWindow();

            try
            {
                DirectoryInfo cachDir = Optimiser.TerminalManager.TerminalChangeableDirectory
                                        .GetDirectory("Tester")
                                        .GetDirectory("cache", true);
                DirectoryInfo cacheCopy = workingDirectory.Tester.GetDirectory("cache", true);
                cacheCopy.GetFiles().ToList().ForEach(x => x.Delete());
                cachDir.GetFiles().ToList()
                .ForEach(x => x.MoveTo(Path.Combine(cacheCopy.FullName, x.Name)));

                ClearResults();
                Optimiser.ClearOptimiser();

                int ind = optimiserInputData.BotParams.FindIndex(x => x.Variable == Fixed_Input_Settings.Params[InputParamName.CloseTerminalFromBot]);
                if (ind > -1)
                {
                    var item = optimiserInputData.BotParams[ind];
                    item.Value      = "true";
                    item.IsOptimize = false;
                    optimiserInputData.BotParams[ind] = item;
                }
                var botParams = optimiserInputData.BotParams.ToList(); // Copy expert settings

                Optimiser.Start(optimiserInputData,
                                Path.Combine(terminalDirectory.Common.FullName,
                                             $"{Path.GetFileNameWithoutExtension(optimiserInputData.RelativePathToBot)}_Report.xml"), dirPrefix);

                SetFileManager fileManager = new SetFileManager(
                    Path.Combine(workingDirectory.GetOptimisationDirectory(optimiserInputData.Symb,
                                                                           Path.GetFileNameWithoutExtension(optimiserInputData.RelativePathToBot),
                                                                           dirPrefix, Optimiser.Name).FullName, "OptimisationSettings.set"), true)
                {
                    Params = botParams
                };
                fileManager.SaveParams();

                Optimiser.TerminalManager.WaitForStop();
            }
            catch (Exception e)
            {
                Optimiser.Stop();
                throw e;
            }
        }
        public override void Start(OptimiserInputData optimiserInputData, string PathToResultsFile, string dirPrefix)
        {
            if (IsOptimisationInProcess || TerminalManager.IsActive)
            {
                throw new Exception("Optimisation already in process or terminal is busy");
            }
            // Устанавливает статус оптимизации и переключатель
            OnProcessStatus("Start optimisation", 0);
            IsOptimisationInProcess = true;

            // Проверить доступность папки к результатом оптимизации
            if (string.IsNullOrEmpty(PathToResultsFile) ||
                string.IsNullOrWhiteSpace(PathToResultsFile))
            {
                throw new ArgumentException("Path to results file is null or empty");
            }

            // Проверить количество границ исторических оптимизаций
            if (optimiserInputData.HistoryBorders.Count == 0)
            {
                throw new ArgumentException("There are no history optimisations date borders");
            }
            // Проверить количество границ исторических оптимизаций
            if (optimiserInputData.ForwardBorders.Count == 0)
            {
                throw new ArgumentException("There are no forward optimisations date borders");
            }

            // Проверить флаги сортировки
            if (optimiserInputData.SortingFlags.Count() == 0)
            {
                throw new ArgumentException("There are no sorting params");
            }

            // Установка рабочей директории оптимизатора
            OptimiserWorkingDirectory = workingDirectory.GetOptimisationDirectory(optimiserInputData.Symb,
                                                                                  Path.GetFileNameWithoutExtension(optimiserInputData.RelativePathToBot), dirPrefix, Name).FullName;

            // Уладение существующего файла с резальтатами оптимизаций
            if (File.Exists(PathToResultsFile))
            {
                File.Delete(PathToResultsFile);
            }

            // Установка настроек оптимизатора
            PathToBot = optimiserInputData.RelativePathToBot;
            Currency  = optimiserInputData.Currency;
            Balance   = optimiserInputData.Balance;
            Laverage  = optimiserInputData.Laverage;

            // Создание (*set) файла и созранение в него настроек робота
            string setFileName = CommonMethods.SaveExpertSettings(Path.GetFileNameWithoutExtension(optimiserInputData.RelativePathToBot),
                                                                  optimiserInputData.BotParams, TerminalManager.TerminalChangeableDirectory);

            // Выбор шага для прогресс бара
            double step = 100.0 / optimiserInputData.HistoryBorders.Count;
            // Счетчик итераций прогресс бара
            int i = 1;

            // Config
            Config configFile = CommonMethods.GetConfig(optimiserInputData,
                                                        setFileName,
                                                        optimiserInputData.HistoryBorders[0],
                                                        TerminalManager.TerminalChangeableDirectory,
                                                        Path.Combine(workingDirectory.WDRoot.FullName, $"{TerminalManager.TerminalID}.ini"));

            Dictionary <DateBorders, DateBorders> historyToForwardBorders =
                DateBorders.CompareHistoryToForward(optimiserInputData.HistoryBorders,
                                                    optimiserInputData.ForwardBorders);

            Dictionary <DateBorders, KeyValuePair <DateBorders, IEnumerable <ParamsItem> > > TestInputData =
                new Dictionary <DateBorders, KeyValuePair <DateBorders, IEnumerable <ParamsItem> > >();

            foreach (var item in optimiserInputData.HistoryBorders)
            {
                // Выходим из метода если вдруг остановили оптимизацию извне
                if (!IsOptimisationInProcess)
                {
                    return;
                }

                // Обновляем прогресс бар
                OnProcessStatus("Optimisation", step * i++);

                configFile.Tester.FromDate = item.From;
                configFile.Tester.ToDate   = item.Till;

                // Run
                if (!CommonMethods.RunTester(configFile, TerminalManager))
                {
                    continue;
                }

                // Чтение файла с отчетом и удаление его после прочтения
                List <OptimisationResult> results = new List <OptimisationResult>();
                if (!CommonMethods.ReadFile(results, PathToResultsFile, Currency, Balance, Laverage, PathToBot))
                {
                    continue;
                }
                // Устанавливаем для всех прочитанных результатов единые границы дат оптимизаций
                results.ForEach(x =>
                {
                    x.report.DateBorders = item;
                    AllOptimisationResults.Add(x);
                });

                var test_data = FilterResults(results, historyToForwardBorders[item],
                                              optimiserInputData.CompareData,
                                              optimiserInputData.SortingFlags);
                if (test_data.HasValue)
                {
                    TestInputData.Add(item, test_data.Value);
                }
            }

            // Выбор шага для прогресс бара
            step = 100.0 / TestInputData.Count;
            // Счетчик итераций прогресс бара
            i = 1;
            // Обновляем прогресс бар
            OnProcessStatus("Tests", 0);

            configFile.Tester.Optimization     = ENUM_OptimisationMode.Disabled;
            configFile.Tester.ShutdownTerminal = true;
            configFile.Tester.Model            =
                (Settings.IsTickTest ? ENUM_Model.Every_tick_based_on_real_ticks : ENUM_Model.OHLC_1_minute);
            foreach (var item in TestInputData)
            {
                // Выходим из метода если вдруг остановили оптимизацию извне
                if (!IsOptimisationInProcess)
                {
                    return;
                }

                // Обновляем прогресс бар
                OnProcessStatus("Tests", step * i++);

                Test(item.Key, item.Value.Key, item.Value.Value, configFile, PathToResultsFile);
            }

            CommonMethods.SaveExpertSettings(Path.GetFileNameWithoutExtension(optimiserInputData.RelativePathToBot),
                                             optimiserInputData.BotParams, TerminalManager.TerminalChangeableDirectory);

            // Переключение статуса оптимизаций на завершенный и вызов соответствующего события
            IsOptimisationInProcess = false;
            OnOptimisationProcessFinished(this);
        }