private static void InitializeLogging() { // Delete all log files older than 1 week try { var applicationDataDirectory = Catel.IO.Path.GetApplicationDataDirectory(); if (Directory.Exists(applicationDataDirectory)) { var logFiles = Directory.GetFiles(applicationDataDirectory, "*.log"); foreach (var logFile in logFiles) { var lastWriteTime = File.GetLastWriteTime(logFile); if (lastWriteTime < DateTime.Now.AddDays(-7)) { File.Delete(logFile); } } } } catch (Exception) { // Ignore } var fileLogListener = new FileLogListener() { IgnoreCatelLogging = true, IsDebugEnabled = false, IsInfoEnabled = true, IsWarningEnabled = true, IsErrorEnabled = true }; LogManager.AddListener(fileLogListener); }
static void Main(string[] args) { _trader = new QuikTrader(); // объкт, управляющий логгированием _logManager = new LogManager(); // слушатель - устройство вывода, куда будут записываться сообщения // слушатели: // консоль _logManager.Listeners.Add(new ConsoleLogListener()); // окно вывода _logManager.Listeners.Add(new DebugLogListener()); // файл var fileListener = new FileLogListener { Append = false, // true - добавляет сообщения в конец существующего файла, false - перезаписывает существующий файл Extension = "log", // расширение файла лога FileName = "FirstLog", // имя файла лога MaxLength = 1000000, // максимальная длинна файла лога в байтах / в данном случае 1мб LogDirectory = "Logs", // максимальная длинна файла лога SeparateByDates = SeparateByDateModes.FileName // режим разделения логов по датам }; _logManager.Listeners.Add(fileListener); // добавляем источник логов. В данном случае это коннектор. // Роль истоника логов может выполнять любой класс, наследующий от BaseLogReceiver, или реализующий интерфейс ILogSource _logManager.Sources.Add(_trader); _connection = new Connection(_trader, "NL0011100043", "SBER@QJSIM"); // Уровни логирования // Off - логи не выводятся // Error - выводятся только сообщения об ошибках // Warning - выводятся предупреждения и сообщения об ошибках // Info - выводятся информационные сообщения, предупреждения и сообщения об ошибках // Debug - выводятся все сообщения _connection.LogLevel = LogLevels.Debug; // добавляем еще один источник логов. _logManager.Sources.Add(_connection); _connection.Connect(); Console.Read(); _connection.Disconnect(); }
/// <summary> /// This is where the work is done. /// </summary> protected override void ExecuteTask() { IRecorder recorder = _recorders[LogName.FullName]; switch (Action) { case ActionType.Start: if (recorder == null) { recorder = new FileLogListener(LogName.FullName); Recorders.Add(recorder); } recorder.AutoFlush = AutoFlush; recorder.Logger.Threshold = ThresholdLevel; recorder.Start(); AttachRecorder(recorder); break; case ActionType.Stop: if (recorder == null) { throw new BuildException(string.Format(CultureInfo.InvariantCulture, "Tried to stop non-existent recorder '{0}'", LogName.FullName), Location); } recorder.Stop(); break; case ActionType.Close: if (recorder == null) { throw new BuildException(string.Format(CultureInfo.InvariantCulture, "Tried to close non-existent recorder '{0}'", LogName.FullName), Location); } DetachRecorder(recorder); recorder.Close(); Recorders.Remove(recorder.Name); break; case ActionType.Flush: if (recorder == null) { throw new BuildException(string.Format(CultureInfo.InvariantCulture, "Tried to flush non-existent recorder '{0}'", LogName.FullName), Location); } recorder.Flush(); break; } }
private static void AddFileLogListener(string prefix) { Argument.IsNotNull(() => prefix); var fileName = Path.Combine(Path.GetApplicationDataDirectory(), string.Format("{0}_{1}.txt", prefix, DateTime.Now.ToString("yyyyMMdd_HHmm"))); var fileLogListener = new FileLogListener(fileName, 10 * 1024); //fileLogger.IgnoreCatelLogging = true; LogManager.AddListener(fileLogListener); Log.LogProductInfo(); Log.LogDeviceInfo(); }
public void ReturnsRightFullPath(string path, string expectedPath) { var assembly = GetType().Assembly; var fileLogListener = new FileLogListener(path, 25000, assembly); fileLogListener.FilePath = path; var returnedPath = fileLogListener.FilePath; var appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); returnedPath = returnedPath.Replace(appDataPath, "{AppData}"); Assert.AreEqual(expectedPath, returnedPath); }
public static ILogListener CreateFileLogListener(string prefix) { Argument.IsNotNull(() => prefix); var directory = Path.Combine(Path.GetApplicationDataDirectory(), "log"); if (!Directory.Exists(directory)) { Directory.CreateDirectory(directory); } var fileName = Path.Combine(directory, prefix + "_{Date}_{Time}_{ProcessId}"); var fileLogListener = new FileLogListener(fileName, 10 * 1024); return(fileLogListener); }
protected override void OnStartup(StartupEventArgs e) { #if DEBUG LogManager.AddDebugListener(); #endif var fileLogListener = new FileLogListener(); fileLogListener.FilePath = "{AppDir}/{AssemblyName}"; fileLogListener.IgnoreCatelLogging = true; LogManager.AddListener(fileLogListener); Log.Info("Starting application"); // To force the loading of all assemblies at startup, uncomment the lines below: //Log.Info("Preloading assemblies"); //AppDomain.CurrentDomain.PreloadAssemblies(); // Want to improve performance? Uncomment the lines below. Note though that this will disable // some features. // // For more information, see https://catelproject.atlassian.net/wiki/display/CTL/Performance+considerations // Log.Info("Improving performance"); // Catel.Data.ModelBase.DefaultSuspendValidationValue = true; // Catel.Windows.Controls.UserControl.DefaultCreateWarningAndErrorValidatorForViewModelValue = false; // Catel.Windows.Controls.UserControl.DefaultSkipSearchingForInfoBarMessageControlValue = true; // TODO: Register custom types in the ServiceLocator //Log.Info("Registering custom types"); //var serviceLocator = ServiceLocator.Default; //serviceLocator.RegisterType<IMyInterface, IMyClass>(); StyleHelper.CreateStyleForwardersForDefaultStyles(); Log.Info("Calling base.OnStartup"); base.OnStartup(e); }
private CommandHandler(IConnector connector) { _connector = connector; var logger = new FileLogListener { Append = true, MaxLength = 2048000, FileName = "{0:00}_{1:00}_{2:00}_log.txt".Put(DateTime.Now.Hour, DateTime.Now.Minute, DateTime.Now.Second), SeparateByDates = SeparateByDateModes.FileName, LogDirectory = "logs" }; _logManager = new LogManager(); _userPositions = new Dictionary <string, UserPosition>(); _messageManager = new MessageManager(); _messageManager.AutoMessage += DoAutoGeneralInfo; UserPosition.LoadFromXml()?.ForEach(up => { _userPositions.Add(up.SecCode, up); }); _logManager.Listeners.Add(logger); _logManager.Sources.Add(_connector); }
public void Log_logs_an_entry_to_a_file() { DateTime testTime = DateTime.Now; Logger logger = new Logger(LogLevel.Message); FileLogListener listener = new FileLogListener(AppDomain.CurrentDomain.BaseDirectory); listener.TestTime = testTime; logger.Listeners.Add(listener); string message = Guid.NewGuid().ToString(); string expectedText = string.Format("{0} {1} {2}", testTime.ToString("s"), "Warning", message); string expectedFileName = "LogFile_" + testTime.ToString("yyyy-MM-dd") + ".txt"; string expectedFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, expectedFileName); logger.LogWarning(message); Assert.IsTrue(File.Exists(expectedFilePath)); string actual = File.ReadAllText(expectedFilePath); Assert.IsTrue(actual.Contains(expectedText)); }
private void StartBtnClick(object sender, RoutedEventArgs e) { if (_connectors.Count > 0) { foreach (var connector in _connectors) { connector.Start(); } return; } if (HistoryPath.Folder.IsEmpty() || !Directory.Exists(HistoryPath.Folder)) { MessageBox.Show(this, LocalizedStrings.Str3014); return; } if (_connectors.Any(t => t.State != EmulationStates.Stopped)) { MessageBox.Show(this, LocalizedStrings.Str3015); return; } var id = SecId.Text.ToSecurityId(); //if (secIdParts.Length != 2) //{ // MessageBox.Show(this, LocalizedStrings.Str3016); // return; //} var timeFrame = TimeSpan.FromMinutes(TimeFrame.SelectedIndex == 0 ? 1 : 5); var secCode = id.SecurityCode; var board = _exchangeInfoProvider.GetOrCreateBoard(id.BoardCode); // create test security var security = new Security { Id = SecId.Text, // sec id has the same name as folder with historical data Code = secCode, Board = board, }; if (FinamCandlesCheckBox.IsChecked == true) { _finamHistorySource.Refresh(new FinamSecurityStorage(security), security, s => {}, () => false); } // create backtesting modes var settings = new[] { Tuple.Create( TicksCheckBox, TicksProgress, TicksParameterGrid, // ticks new EmulationInfo { UseTicks = true, CurveColor = Colors.DarkGreen, StrategyName = LocalizedStrings.Ticks }, TicksChart, TicksEquity, TicksPosition), Tuple.Create( TicksAndDepthsCheckBox, TicksAndDepthsProgress, TicksAndDepthsParameterGrid, // ticks + order book new EmulationInfo { UseTicks = true, UseMarketDepth = true, CurveColor = Colors.Red, StrategyName = LocalizedStrings.XamlStr757 }, TicksAndDepthsChart, TicksAndDepthsEquity, TicksAndDepthsPosition), Tuple.Create( DepthsCheckBox, DepthsProgress, DepthsParameterGrid, // order book new EmulationInfo { UseMarketDepth = true, CurveColor = Colors.OrangeRed, StrategyName = LocalizedStrings.MarketDepths }, DepthsChart, DepthsEquity, DepthsPosition), Tuple.Create( CandlesCheckBox, CandlesProgress, CandlesParameterGrid, // candles new EmulationInfo { UseCandleTimeFrame = timeFrame, CurveColor = Colors.DarkBlue, StrategyName = LocalizedStrings.Candles }, CandlesChart, CandlesEquity, CandlesPosition), Tuple.Create( CandlesAndDepthsCheckBox, CandlesAndDepthsProgress, CandlesAndDepthsParameterGrid, // candles + orderbook new EmulationInfo { UseMarketDepth = true, UseCandleTimeFrame = timeFrame, CurveColor = Colors.Cyan, StrategyName = LocalizedStrings.XamlStr635 }, CandlesAndDepthsChart, CandlesAndDepthsEquity, CandlesAndDepthsPosition), Tuple.Create( OrderLogCheckBox, OrderLogProgress, OrderLogParameterGrid, // order log new EmulationInfo { UseOrderLog = true, CurveColor = Colors.CornflowerBlue, StrategyName = LocalizedStrings.OrderLog }, OrderLogChart, OrderLogEquity, OrderLogPosition), Tuple.Create( Level1CheckBox, Level1Progress, Level1ParameterGrid, // order log new EmulationInfo { UseLevel1 = true, CurveColor = Colors.Aquamarine, StrategyName = LocalizedStrings.Level1 }, Level1Chart, Level1Equity, Level1Position), Tuple.Create( FinamCandlesCheckBox, FinamCandlesProgress, FinamCandlesParameterGrid, // candles new EmulationInfo { UseCandleTimeFrame = timeFrame, HistorySource = d => _finamHistorySource.GetCandles(security, timeFrame, d.Date, d.Date), CurveColor = Colors.DarkBlue, StrategyName = LocalizedStrings.FinamCandles }, FinamCandlesChart, FinamCandlesEquity, FinamCandlesPosition), Tuple.Create( YahooCandlesCheckBox, YahooCandlesProgress, YahooCandlesParameterGrid, // candles new EmulationInfo { UseCandleTimeFrame = timeFrame, HistorySource = d => new YahooHistorySource(_exchangeInfoProvider).GetCandles(security, timeFrame, d.Date, d.Date), CurveColor = Colors.DarkBlue, StrategyName = LocalizedStrings.YahooCandles }, YahooCandlesChart, YahooCandlesEquity, YahooCandlesPosition), }; // storage to historical data var storageRegistry = new StorageRegistry { // set historical path DefaultDrive = new LocalMarketDataDrive(HistoryPath.Folder) }; var startTime = ((DateTime)From.Value).ChangeKind(DateTimeKind.Utc); var stopTime = ((DateTime)To.Value).ChangeKind(DateTimeKind.Utc); // (ru only) ОЛ необходимо загружать с 18.45 пред дня, чтобы стаканы строились правильно if (OrderLogCheckBox.IsChecked == true) { startTime = startTime.Subtract(TimeSpan.FromDays(1)).AddHours(18).AddMinutes(45).AddTicks(1).ApplyTimeZone(TimeHelper.Moscow).UtcDateTime; } // ProgressBar refresh step var progressStep = ((stopTime - startTime).Ticks / 100).To <TimeSpan>(); // set ProgressBar bounds _progressBars.ForEach(p => { p.Value = 0; p.Maximum = 100; }); var logManager = new LogManager(); var fileLogListener = new FileLogListener("sample.log"); logManager.Listeners.Add(fileLogListener); //logManager.Listeners.Add(new DebugLogListener()); // for track logs in output window in Vusial Studio (poor performance). var generateDepths = GenDepthsCheckBox.IsChecked == true; var maxDepth = MaxDepth.Text.To <int>(); var maxVolume = MaxVolume.Text.To <int>(); var secId = security.ToSecurityId(); SetIsEnabled(false, false, false); foreach (var set in settings) { if (set.Item1.IsChecked == false) { continue; } var title = (string)set.Item1.Content; InitChart(set.Item5, set.Item6, set.Item7); var progressBar = set.Item2; var statistic = set.Item3; var emulationInfo = set.Item4; var level1Info = new Level1ChangeMessage { SecurityId = secId, ServerTime = startTime, } .TryAdd(Level1Fields.PriceStep, secCode == "RIZ2" ? 10m : 1) .TryAdd(Level1Fields.StepPrice, 6m) .TryAdd(Level1Fields.MinPrice, 10m) .TryAdd(Level1Fields.MaxPrice, 1000000m) .TryAdd(Level1Fields.MarginBuy, 10000m) .TryAdd(Level1Fields.MarginSell, 10000m); // test portfolio var portfolio = new Portfolio { Name = "test account", BeginValue = 1000000, }; // create backtesting connector var connector = new HistoryEmulationConnector( new[] { security }, new[] { portfolio }) { EmulationAdapter = { Emulator = { Settings = { // match order if historical price touched our limit order price. // It is terned off, and price should go through limit order price level // (more "severe" test mode) MatchOnTouch = false, } } }, //UseExternalCandleSource = emulationInfo.UseCandleTimeFrame != null, CreateDepthFromOrdersLog = emulationInfo.UseOrderLog, CreateTradesFromOrdersLog = emulationInfo.UseOrderLog, HistoryMessageAdapter = { StorageRegistry = storageRegistry, // set history range StartDate = startTime, StopDate = stopTime, OrderLogMarketDepthBuilders = { { secId, LocalizedStrings.ActiveLanguage == Languages.Russian ? (IOrderLogMarketDepthBuilder) new PlazaOrderLogMarketDepthBuilder(secId) : new ItchOrderLogMarketDepthBuilder(secId) } } }, // set market time freq as time frame MarketTimeChangedInterval = timeFrame, }; ((ILogSource)connector).LogLevel = DebugLogCheckBox.IsChecked == true ? LogLevels.Debug : LogLevels.Info; logManager.Sources.Add(connector); var candleManager = new CandleManager(connector); var series = new CandleSeries(typeof(TimeFrameCandle), security, timeFrame) { BuildCandlesMode = emulationInfo.UseCandleTimeFrame == null ? BuildCandlesModes.Build : BuildCandlesModes.Load }; _shortMa = new SimpleMovingAverage { Length = 10 }; _shortElem = new ChartIndicatorElement { Color = Colors.Coral, ShowAxisMarker = false, FullTitle = _shortMa.ToString() }; var chart = set.Item5; chart.AddElement(_area, _shortElem); _longMa = new SimpleMovingAverage { Length = 80 }; _longElem = new ChartIndicatorElement { ShowAxisMarker = false, FullTitle = _longMa.ToString() }; chart.AddElement(_area, _longElem); // create strategy based on 80 5-min и 10 5-min var strategy = new SmaStrategy(chart, _candlesElem, _tradesElem, _shortMa, _shortElem, _longMa, _longElem, candleManager, series) { Volume = 1, Portfolio = portfolio, Security = security, Connector = connector, LogLevel = DebugLogCheckBox.IsChecked == true ? LogLevels.Debug : LogLevels.Info, // by default interval is 1 min, // it is excessively for time range with several months UnrealizedPnLInterval = ((stopTime - startTime).Ticks / 1000).To <TimeSpan>() }; logManager.Sources.Add(strategy); connector.NewSecurity += s => { if (s != security) { return; } // fill level1 values connector.HistoryMessageAdapter.SendOutMessage(level1Info); if (emulationInfo.HistorySource != null) { if (emulationInfo.UseCandleTimeFrame != null) { connector.RegisterHistorySource(security, MarketDataTypes.CandleTimeFrame, emulationInfo.UseCandleTimeFrame.Value, emulationInfo.HistorySource); } if (emulationInfo.UseTicks) { connector.RegisterHistorySource(security, MarketDataTypes.Trades, null, emulationInfo.HistorySource); } if (emulationInfo.UseLevel1) { connector.RegisterHistorySource(security, MarketDataTypes.Level1, null, emulationInfo.HistorySource); } if (emulationInfo.UseMarketDepth) { connector.RegisterHistorySource(security, MarketDataTypes.MarketDepth, null, emulationInfo.HistorySource); } } else { if (emulationInfo.UseMarketDepth) { connector.RegisterMarketDepth(security); if ( // if order book will be generated generateDepths || // of backtesting will be on candles emulationInfo.UseCandleTimeFrame != TimeSpan.Zero ) { // if no have order book historical data, but strategy is required, // use generator based on last prices connector.RegisterMarketDepth(new TrendMarketDepthGenerator(connector.GetSecurityId(security)) { Interval = TimeSpan.FromSeconds(1), // order book freq refresh is 1 sec MaxAsksDepth = maxDepth, MaxBidsDepth = maxDepth, UseTradeVolume = true, MaxVolume = maxVolume, MinSpreadStepCount = 2, // min spread generation is 2 pips MaxSpreadStepCount = 5, // max spread generation size (prevent extremely size) MaxPriceStepCount = 3 // pips size, }); } } if (emulationInfo.UseOrderLog) { connector.RegisterOrderLog(security); } if (emulationInfo.UseTicks) { connector.RegisterTrades(security); } if (emulationInfo.UseLevel1) { connector.RegisterSecurity(security); } } // start strategy before emulation started strategy.Start(); candleManager.Start(series); // start historical data loading when connection established successfully and all data subscribed connector.Start(); }; // fill parameters panel statistic.Parameters.Clear(); statistic.Parameters.AddRange(strategy.StatisticManager.Parameters); var equity = set.Item6; var pnlCurve = equity.CreateCurve(LocalizedStrings.PnL + " " + emulationInfo.StrategyName, emulationInfo.CurveColor, LineChartStyles.Area); var unrealizedPnLCurve = equity.CreateCurve(LocalizedStrings.PnLUnreal + " " + emulationInfo.StrategyName, Colors.Black); var commissionCurve = equity.CreateCurve(LocalizedStrings.Str159 + " " + emulationInfo.StrategyName, Colors.Red, LineChartStyles.DashedLine); var posItems = set.Item7.CreateCurve(emulationInfo.StrategyName, emulationInfo.CurveColor); strategy.PnLChanged += () => { var pnl = new EquityData { Time = strategy.CurrentTime, Value = strategy.PnL - strategy.Commission ?? 0 }; var unrealizedPnL = new EquityData { Time = strategy.CurrentTime, Value = strategy.PnLManager.UnrealizedPnL ?? 0 }; var commission = new EquityData { Time = strategy.CurrentTime, Value = strategy.Commission ?? 0 }; pnlCurve.Add(pnl); unrealizedPnLCurve.Add(unrealizedPnL); commissionCurve.Add(commission); }; strategy.PositionChanged += () => posItems.Add(new EquityData { Time = strategy.CurrentTime, Value = strategy.Position }); var nextTime = startTime + progressStep; // handle historical time for update ProgressBar connector.MarketTimeChanged += d => { if (connector.CurrentTime < nextTime && connector.CurrentTime < stopTime) { return; } var steps = (connector.CurrentTime - startTime).Ticks / progressStep.Ticks + 1; nextTime = startTime + (steps * progressStep.Ticks).To <TimeSpan>(); this.GuiAsync(() => progressBar.Value = steps); }; connector.StateChanged += () => { if (connector.State == EmulationStates.Stopped) { candleManager.Stop(series); strategy.Stop(); SetIsChartEnabled(chart, false); if (_connectors.All(c => c.State == EmulationStates.Stopped)) { logManager.Dispose(); _connectors.Clear(); SetIsEnabled(true, false, false); } this.GuiAsync(() => { if (connector.IsFinished) { progressBar.Value = progressBar.Maximum; MessageBox.Show(this, LocalizedStrings.Str3024.Put(DateTime.Now - _startEmulationTime), title); } else { MessageBox.Show(this, LocalizedStrings.cancelled, title); } }); } else if (connector.State == EmulationStates.Started) { if (_connectors.All(c => c.State == EmulationStates.Started)) { SetIsEnabled(false, true, true); } SetIsChartEnabled(chart, true); } else if (connector.State == EmulationStates.Suspended) { if (_connectors.All(c => c.State == EmulationStates.Suspended)) { SetIsEnabled(true, false, true); } } }; if (ShowDepth.IsChecked == true) { MarketDepth.UpdateFormat(security); connector.NewMessage += message => { var quoteMsg = message as QuoteChangeMessage; if (quoteMsg != null) { MarketDepth.UpdateDepth(quoteMsg); } }; } _connectors.Add(connector); progressBar.Value = 0; } _startEmulationTime = DateTime.Now; // start emulation foreach (var connector in _connectors) { // raise NewSecurities and NewPortfolio for full fill strategy properties connector.Connect(); // 1 cent commission for trade connector.SendInMessage(new CommissionRuleMessage { Rule = new CommissionPerTradeRule { Value = 0.01m } }); } TabControl.Items.Cast <TabItem>().First(i => i.Visibility == Visibility.Visible).IsSelected = true; }
private void StartBtnClick(object sender, RoutedEventArgs e) { if (HistoryPath.Text.IsEmpty() || !Directory.Exists(HistoryPath.Text)) { MessageBox.Show(this, LocalizedStrings.Str3014); return; } if (Math.Abs(TestingProcess.Value - 0) > double.Epsilon) { MessageBox.Show(this, LocalizedStrings.Str3015); return; } var logManager = new LogManager(); var fileLogListener = new FileLogListener("sample.log"); logManager.Listeners.Add(fileLogListener); // SMA periods var periods = new[] { new Tuple <int, int, Color>(80, 10, Colors.DarkGreen), new Tuple <int, int, Color>(70, 8, Colors.Red), new Tuple <int, int, Color>(60, 6, Colors.DarkBlue) }; // storage to historical data var storageRegistry = new StorageRegistry { // set historical path DefaultDrive = new LocalMarketDataDrive(HistoryPath.Text) }; var timeFrame = TimeSpan.FromMinutes(5); // create test security var security = new Security { Id = "RIZ2@FORTS", // sec id has the same name as folder with historical data Code = "RIZ2", Name = "RTS-12.12", Board = ExchangeBoard.Forts, }; var startTime = new DateTime(2012, 10, 1); var stopTime = new DateTime(2012, 10, 31); var level1Info = new Level1ChangeMessage { SecurityId = security.ToSecurityId(), ServerTime = startTime, } .TryAdd(Level1Fields.PriceStep, 10m) .TryAdd(Level1Fields.StepPrice, 6m) .TryAdd(Level1Fields.MinPrice, 10m) .TryAdd(Level1Fields.MaxPrice, 1000000m) .TryAdd(Level1Fields.MarginBuy, 10000m) .TryAdd(Level1Fields.MarginSell, 10000m); // test portfolio var portfolio = new Portfolio { Name = "test account", BeginValue = 1000000, }; // create backtesting connector var batchEmulation = new BatchEmulation(new[] { security }, new[] { portfolio }, storageRegistry) { EmulationSettings = { MarketTimeChangedInterval = timeFrame, StartTime = startTime, StopTime = stopTime, // count of parallel testing strategies BatchSize = periods.Length, } }; // handle historical time for update ProgressBar batchEmulation.ProgressChanged += (curr, total) => this.GuiAsync(() => TestingProcess.Value = total); batchEmulation.StateChanged += (oldState, newState) => { if (batchEmulation.State != EmulationStates.Stopped) { return; } this.GuiAsync(() => { if (batchEmulation.IsFinished) { TestingProcess.Value = TestingProcess.Maximum; MessageBox.Show(this, LocalizedStrings.Str3024.Put(DateTime.Now - _startEmulationTime)); } else { MessageBox.Show(this, LocalizedStrings.cancelled); } }); }; // get emulation connector var connector = batchEmulation.EmulationConnector; logManager.Sources.Add(connector); connector.NewSecurities += securities => { if (securities.All(s => s != security)) { return; } // fill level1 values connector.SendInMessage(level1Info); connector.RegisterMarketDepth(new TrendMarketDepthGenerator(connector.GetSecurityId(security)) { // order book freq refresh is 1 sec Interval = TimeSpan.FromSeconds(1), }); }; TestingProcess.Maximum = 100; TestingProcess.Value = 0; _startEmulationTime = DateTime.Now; var strategies = periods .Select(period => { var series = new CandleSeries(typeof(TimeFrameCandle), security, timeFrame); // create strategy based SMA var strategy = new SmaStrategy(series, new SimpleMovingAverage { Length = period.Item1 }, new SimpleMovingAverage { Length = period.Item2 }) { Volume = 1, Security = security, Portfolio = portfolio, Connector = connector, // by default interval is 1 min, // it is excessively for time range with several months UnrealizedPnLInterval = ((stopTime - startTime).Ticks / 1000).To <TimeSpan>() }; strategy.SetCandleManager(new CandleManager(connector)); var curveItems = Curve.CreateCurve(LocalizedStrings.Str3026Params.Put(period.Item1, period.Item2), period.Item3); strategy.PnLChanged += () => { var data = new EquityData { Time = strategy.CurrentTime, Value = strategy.PnL, }; this.GuiAsync(() => curveItems.Add(data)); }; Stat.AddStrategies(new[] { strategy }); return(strategy); }) .ToEx(periods.Length); // start emulation batchEmulation.Start(strategies); }
protected override async void OnStartup(StartupEventArgs e) { var languageService = ServiceLocator.Default.ResolveType <ILanguageService>(); languageService.PreferredCulture = new CultureInfo("en-US"); languageService.FallbackCulture = new CultureInfo("en-US"); #if DEBUG _debugListener = LogManager.AddDebugListener(true); #endif var fileLogListener = new FileLogListener { IgnoreCatelLogging = true, FilePath = FileLocations.LogFile, TimeDisplay = TimeDisplay.DateTime }; LogManager.IgnoreDuplicateExceptionLogging = false; LogManager.AddListener(fileLogListener); LogManager.GetCurrentClassLogger().Debug($"Started with command line {Environment.CommandLine}"); var serviceLocator = ServiceLocator.Default; var updateService = serviceLocator.ResolveType <IUpdateService>(); updateService.Initialize(Settings.Application.AutomaticUpdates.AvailableChannels, Settings.Application.AutomaticUpdates.DefaultChannel, Settings.Application.AutomaticUpdates.CheckForUpdatesDefaultValue); if (updateService.IsUpdateSystemAvailable) { LogManager.GetCurrentClassLogger().Debug("Update system available, processing squirrel events"); using (var mgr = new UpdateManager(updateService.CurrentChannel.DefaultUrl)) { // Note, in most of these scenarios, the app exits after this method // completes! SquirrelAwareApp.HandleEvents( onInitialInstall: v => { LogManager.GetCurrentClassLogger().Debug("Installing shortcuts"); mgr.CreateShortcutForThisExe(); Environment.Exit(0); }, onAppUpdate: v => { LogManager.GetCurrentClassLogger().Debug("Update: Installing shortcuts"); mgr.CreateShortcutForThisExe(); Environment.Exit(0); }, onAppUninstall: v => { mgr.RemoveShortcutForThisExe(); Environment.Exit(0); }); } } LogManager.GetCurrentClassLogger().Debug("Startup"); try { RotateLogFile(fileLogListener.FilePath); } catch (Exception exception) { LogManager.GetCurrentClassLogger().Error("Tried to rotate the log file, but it failed."); LogManager.GetCurrentClassLogger().Error(exception); MessageBox.Show( $"Unable to rotate the log file {fileLogListener.FilePath}. Please verify that you have access to that file. " + $"We will continue, but no logging will be available. Additional information: {Environment.NewLine}{Environment.NewLine}{exception}", "Log File Error", MessageBoxButton.OK, MessageBoxImage.Error); } // Clean up old RemoteVstHost logs VstUtils.CleanupVstWorkerLogDirectory(); await StartShell(); }
private void StartBtnClick(object sender, RoutedEventArgs e) { if (HistoryPath.Text.IsEmpty() || !Directory.Exists(HistoryPath.Text)) { MessageBox.Show(this, LocalizedStrings.Str3014); return; } if (Math.Abs(TestingProcess.Value - 0) > double.Epsilon) { MessageBox.Show(this, LocalizedStrings.Str3015); return; } var logManager = new LogManager(); var fileLogListener = new FileLogListener("sample.log"); logManager.Listeners.Add(fileLogListener); // создаем длины скользящих средник var periods = new[] { new Tuple <int, int, Color>(80, 10, Colors.DarkGreen), new Tuple <int, int, Color>(70, 8, Colors.Red), new Tuple <int, int, Color>(60, 6, Colors.DarkBlue) }; // хранилище, через которое будет производиться доступ к тиковой и котировочной базе var storageRegistry = new StorageRegistry { // изменяем путь, используемый по умолчанию DefaultDrive = new LocalMarketDataDrive(HistoryPath.Text) }; var timeFrame = TimeSpan.FromMinutes(5); // создаем тестовый инструмент, на котором будет производится тестирование var security = new Security { Id = "RIZ2@FORTS", // по идентификатору инструмента будет искаться папка с историческими маркет данными Code = "RIZ2", Name = "RTS-12.12", Board = ExchangeBoard.Forts, }; var startTime = new DateTime(2012, 10, 1); var stopTime = new DateTime(2012, 10, 31); var level1Info = new Level1ChangeMessage { SecurityId = security.ToSecurityId(), ServerTime = startTime, } .TryAdd(Level1Fields.PriceStep, 10m) .TryAdd(Level1Fields.StepPrice, 6m) .TryAdd(Level1Fields.MinPrice, 10m) .TryAdd(Level1Fields.MaxPrice, 1000000m) .TryAdd(Level1Fields.MarginBuy, 10000m) .TryAdd(Level1Fields.MarginSell, 10000m); // тестовый портфель var portfolio = new Portfolio { Name = "test account", BeginValue = 1000000, }; // создаем подключение для эмуляции var batchEmulation = new BatchEmulation(new[] { security }, new[] { portfolio }, storageRegistry) { // инициализируем настройки (инструмент в истории обновляется раз в секунду) EmulationSettings = { MarketTimeChangedInterval = timeFrame, StartTime = startTime, StopTime = stopTime, // кол-во одновременно тестируемых стратегий BatchSize = periods.Length, } }; // и подписываемся на событие изменения прогресса тестирования, чтобы обновить ProgressBar batchEmulation.ProgressChanged += (curr, total) => this.GuiAsync(() => TestingProcess.Value = total); batchEmulation.StateChanged += (oldState, newState) => { if (batchEmulation.State != EmulationStates.Stopped) { return; } this.GuiAsync(() => { if (batchEmulation.IsFinished) { TestingProcess.Value = TestingProcess.Maximum; MessageBox.Show(LocalizedStrings.Str3024 + (DateTime.Now - _startEmulationTime)); } else { MessageBox.Show(LocalizedStrings.cancelled); } }); }; // получаем подключение для эмуляции var connector = batchEmulation.EmulationConnector; logManager.Sources.Add(connector); // подписываемся на получение данных после получения инструмента connector.NewSecurities += securities => { if (securities.All(s => s != security)) { return; } // отправляем данные Level1 для инструмента connector.MarketDataAdapter.SendOutMessage(level1Info); connector.RegisterMarketDepth(new TrendMarketDepthGenerator(connector.GetSecurityId(security)) { // стакан для инструмента в истории обновляется раз в секунду Interval = TimeSpan.FromSeconds(1), }); }; TestingProcess.Maximum = 100; TestingProcess.Value = 0; _startEmulationTime = DateTime.Now; var strategies = periods .Select(period => { var series = new CandleSeries(typeof(TimeFrameCandle), security, timeFrame); // создаем торговую стратегию var strategy = new SmaStrategy(series, new SimpleMovingAverage { Length = period.Item1 }, new SimpleMovingAverage { Length = period.Item2 }) { Volume = 1, Security = security, Portfolio = portfolio, Connector = connector, // по-умолчанию интервал равен 1 минут, // что для истории в диапазон от нескольких месяцев излишне UnrealizedPnLInterval = ((stopTime - startTime).Ticks / 1000).To <TimeSpan>() }; strategy.SetCandleManager(new CandleManager(connector)); var curveItems = Curve.CreateCurve(LocalizedStrings.Str3026Params.Put(period.Item1, period.Item2), period.Item3); strategy.PnLChanged += () => { var data = new EquityData { Time = strategy.CurrentTime, Value = strategy.PnL, }; this.GuiAsync(() => curveItems.Add(data)); }; Stat.AddStrategies(new[] { strategy }); return(strategy); }) .ToEx(periods.Length); // запускаем эмуляцию batchEmulation.Start(strategies); }
private void StartBtnClick(object sender, RoutedEventArgs e) { if (_batchEmulation != null) { _batchEmulation.Resume(); return; } if (HistoryPath.Folder.IsEmpty() || !Directory.Exists(HistoryPath.Folder)) { MessageBox.Show(this, LocalizedStrings.Str3014); return; } TestingProcess.Value = 0; Curve.Clear(); Stat.Clear(); var logManager = new LogManager(); var fileLogListener = new FileLogListener("sample.log"); logManager.Listeners.Add(fileLogListener); // SMA periods var periods = new List <(int longMa, int shortMa, Color color)>(); for (var l = 100; l >= 50; l -= 10) { for (var s = 10; s >= 5; s -= 1) { periods.Add((l, s, Color.FromRgb((byte)RandomGen.GetInt(255), (byte)RandomGen.GetInt(255), (byte)RandomGen.GetInt(255)))); } } // storage to historical data var storageRegistry = new StorageRegistry { // set historical path DefaultDrive = new LocalMarketDataDrive(HistoryPath.Folder) }; var timeFrame = TimeSpan.FromMinutes(1); // create test security var security = new Security { Id = "SBER@TQBR", // sec id has the same name as folder with historical data Code = "SBER", Name = "SBER", Board = ExchangeBoard.Micex, }; var startTime = new DateTime(2020, 4, 1); var stopTime = new DateTime(2020, 4, 20); var level1Info = new Level1ChangeMessage { SecurityId = security.ToSecurityId(), ServerTime = startTime, } .TryAdd(Level1Fields.PriceStep, 0.01m) .TryAdd(Level1Fields.StepPrice, 0.01m) .TryAdd(Level1Fields.MinPrice, 0.01m) .TryAdd(Level1Fields.MaxPrice, 1000000m) .TryAdd(Level1Fields.MarginBuy, 10000m) .TryAdd(Level1Fields.MarginSell, 10000m); // test portfolio var portfolio = Portfolio.CreateSimulator(); // create backtesting connector _batchEmulation = new BatchEmulation(new[] { security }, new[] { portfolio }, storageRegistry) { EmulationSettings = { MarketTimeChangedInterval = timeFrame, StartTime = startTime, StopTime = stopTime, // count of parallel testing strategies // if not set, then CPU count * 2 //BatchSize = 3, } }; // handle historical time for update ProgressBar _batchEmulation.TotalProgressChanged += (currBatch, total) => this.GuiAsync(() => TestingProcess.Value = total); _batchEmulation.StateChanged += (oldState, newState) => { var isFinished = _batchEmulation.IsFinished; if (_batchEmulation.State == ChannelStates.Stopped) { _batchEmulation = null; } this.GuiAsync(() => { switch (newState) { case ChannelStates.Stopping: case ChannelStates.Starting: case ChannelStates.Suspending: SetIsEnabled(false, false, false); break; case ChannelStates.Stopped: SetIsEnabled(true, false, false); if (isFinished) { TestingProcess.Value = TestingProcess.Maximum; MessageBox.Show(this, LocalizedStrings.Str3024.Put(DateTime.Now - _startEmulationTime)); } else { MessageBox.Show(this, LocalizedStrings.cancelled); } break; case ChannelStates.Started: SetIsEnabled(false, true, true); break; case ChannelStates.Suspended: SetIsEnabled(true, false, true); break; default: throw new ArgumentOutOfRangeException(newState.ToString()); } }); }; _startEmulationTime = DateTime.Now; var strategies = periods .Select(period => { var series = new CandleSeries(typeof(TimeFrameCandle), security, timeFrame); // create strategy based SMA var strategy = new SampleHistoryTesting.SmaStrategy(series) { ShortSma = { Length = period.shortMa }, LongSma = { Length = period.longMa }, Volume = 1, Security = security, Portfolio = portfolio, //Connector = connector, // by default interval is 1 min, // it is excessively for time range with several months UnrealizedPnLInterval = ((stopTime - startTime).Ticks / 1000).To <TimeSpan>() }; this.GuiSync(() => { var curveElem = Curve.CreateCurve(LocalizedStrings.Str3026Params.Put(period.Item1, period.Item2), period.Item3, ChartIndicatorDrawStyles.Line); strategy.PnLChanged += () => { var data = new ChartDrawData(); data .Group(strategy.CurrentTime) .Add(curveElem, strategy.PnL); Curve.Draw(data); }; Stat.AddStrategies(new[] { strategy }); }); return(strategy); }); // start emulation _batchEmulation.Start(strategies, periods.Count); }
public static int Link(Context context) { int?exitCode = null; var stopWatch = new Stopwatch(); stopWatch.Start(); context.ValidateContext(); if (!string.IsNullOrEmpty(context.LogFile)) { var fileLogListener = new FileLogListener(context.LogFile, 25 * 1024); fileLogListener.IsDebugEnabled = context.IsDebug; fileLogListener.IgnoreCatelLogging = true; LogManager.AddListener(fileLogListener); } if (!PdbStrHelper.IsPdbStrAvailable()) { Log.Error("PdbStr is not found on the computer, please install 'Debugging Tools for Windows'"); return(-1); } try { var projects = new List <Project>(); string[] solutionFiles; if (string.IsNullOrEmpty(context.SolutionFile)) { solutionFiles = Directory.GetFiles(context.SolutionDirectory, "*.sln", SearchOption.AllDirectories); } else { var pathToSolutionFile = Path.Combine(context.SolutionDirectory, context.SolutionFile); if (!File.Exists(pathToSolutionFile)) { Log.Error("Could not find solution file: " + pathToSolutionFile); return(-1); } solutionFiles = new[] { pathToSolutionFile }; } foreach (var solutionFile in solutionFiles) { var solutionProjects = ProjectHelper.GetProjects(solutionFile, context.ConfigurationName, context.PlatformName); projects.AddRange(solutionProjects); } var provider = context.Provider; if (provider == null) { Log.ErrorAndThrowException <GitLinkException>("Cannot find a matching provider for '{0}'", context.TargetUrl); } Log.Info("Using provider '{0}'", provider.GetType().Name); var shaHash = context.Provider.GetShaHashOfCurrentBranch(context); Log.Info("Using commit sha '{0}' as version stamp", shaHash); var projectCount = projects.Count(); var failedProjects = new List <Project>(); Log.Info("Found '{0}' project(s)", projectCount); Log.Info(string.Empty); foreach (var project in projects) { try { if (project.ShouldBeIgnored(context.IgnoredProjects)) { Log.Info("Ignoring '{0}'", project.GetProjectName()); Log.Info(string.Empty); continue; } if (context.IsDebug) { project.DumpProperties(); } if (!LinkProject(context, project, shaHash)) { failedProjects.Add(project); } } catch (Exception) { failedProjects.Add(project); } } Log.Info("All projects are done. {0} of {1} succeeded", projectCount - failedProjects.Count, projectCount); if (failedProjects.Count > 0) { Log.Info(string.Empty); Log.Info("The following projects have failed:"); Log.Indent(); foreach (var failedProject in failedProjects) { Log.Info("* {0}", context.GetRelativePath(failedProject.GetProjectName())); } Log.Unindent(); } exitCode = (failedProjects.Count == 0) ? 0 : -1; } catch (GitLinkException ex) { Log.Error(ex, "An error occurred"); } catch (Exception ex) { Log.Error(ex, "An unexpected error occurred"); } stopWatch.Stop(); Log.Info(string.Empty); Log.Info("Completed in '{0}'", stopWatch.Elapsed); return(exitCode ?? -1); }
public static int Link(Context context) { int?exitCode = null; var stopWatch = new Stopwatch(); stopWatch.Start(); context.ValidateContext(); if (!string.IsNullOrEmpty(context.LogFile)) { var fileLogListener = new FileLogListener(context.LogFile, 25 * 1024); fileLogListener.IsDebugEnabled = context.IsDebug; fileLogListener.IgnoreCatelLogging = true; LogManager.AddListener(fileLogListener); } using (var temporaryFilesContext = new TemporaryFilesContext()) { Log.Info("Extracting embedded pdbstr.exe"); var pdbStrFile = temporaryFilesContext.GetFile("pdbstr.exe"); ResourceHelper.ExtractEmbeddedResource("GitLink.Resources.Files.pdbstr.exe", pdbStrFile); try { var projects = new List <Project>(); string[] solutionFiles; if (string.IsNullOrEmpty(context.SolutionFile)) { solutionFiles = Directory.GetFiles(context.SolutionDirectory, "*.sln", SearchOption.AllDirectories); } else { var pathToSolutionFile = Path.Combine(context.SolutionDirectory, context.SolutionFile); if (!File.Exists(pathToSolutionFile)) { Log.Error("Could not find solution file: {0}", pathToSolutionFile); return(-1); } solutionFiles = new[] { pathToSolutionFile }; } foreach (var solutionFile in solutionFiles) { var solutionProjects = ProjectHelper.GetProjects(solutionFile, context.ConfigurationName, context.PlatformName); projects.AddRange(solutionProjects); } var provider = context.Provider; if (provider == null) { throw Log.ErrorAndCreateException <GitLinkException>("Cannot find a matching provider for '{0}'", context.TargetUrl); } Log.Info("Using provider '{0}'", provider.GetType().Name); var shaHash = context.Provider.GetShaHashOfCurrentBranch(context, temporaryFilesContext); Log.Info("Using commit sha '{0}' as version stamp", shaHash); var projectCount = projects.Count(); var failedProjects = new List <Project>(); Log.Info("Found '{0}' project(s)", projectCount); Log.Info(string.Empty); foreach (var project in projects) { try { var projectName = project.GetProjectName(); if (ProjectHelper.ShouldBeIgnored(projectName, context.IncludedProjects, context.IgnoredProjects)) { Log.Info("Ignoring '{0}'", project.GetProjectName()); Log.Info(string.Empty); continue; } if (context.IsDebug) { project.DumpProperties(); } if (!LinkProject(context, project, pdbStrFile, shaHash, context.PdbFilesDirectory)) { failedProjects.Add(project); } } catch (Exception) { failedProjects.Add(project); } } Log.Info("All projects are done. {0} of {1} succeeded", projectCount - failedProjects.Count, projectCount); if (failedProjects.Count > 0) { Log.Info(string.Empty); Log.Info("The following projects have failed:"); Log.Indent(); foreach (var failedProject in failedProjects) { Log.Info("* {0}", context.GetRelativePath(failedProject.GetProjectName())); } Log.Unindent(); } exitCode = (failedProjects.Count == 0) ? 0 : -1; } catch (GitLinkException ex) { Log.Error(ex, "An error occurred"); } catch (Exception ex) { Log.Error(ex, "An unexpected error occurred"); } stopWatch.Stop(); } Log.Info(string.Empty); Log.Info("Completed in '{0}'", stopWatch.Elapsed); exitCode = exitCode ?? -1; if (context.ErrorsAsWarnings && exitCode != 0) { Log.Info("One or more errors occurred, but treating it as warning instead"); exitCode = 0; } return(exitCode.Value); }
private void StartBtnClick(object sender, RoutedEventArgs e) { InitChart(); if (HistoryPath.Text.IsEmpty() || !Directory.Exists(HistoryPath.Text)) { MessageBox.Show(this, LocalizedStrings.Str3014); return; } if (_connectors.Any(t => t.State != EmulationStates.Stopped)) { MessageBox.Show(this, LocalizedStrings.Str3015); return; } var secIdParts = SecId.Text.Split('@'); if (secIdParts.Length != 2) { MessageBox.Show(this, LocalizedStrings.Str3016); return; } var timeFrame = TimeSpan.FromMinutes(5); // создаем настройки для тестирования var settings = new[] { Tuple.Create( TicksCheckBox, TicksTestingProcess, TicksParameterGrid, // тест только на тиках new EmulationInfo { CurveColor = Colors.DarkGreen, StrategyName = LocalizedStrings.Str3017 }), Tuple.Create( TicksAndDepthsCheckBox, TicksAndDepthsTestingProcess, TicksAndDepthsParameterGrid, // тест на тиках + стаканы new EmulationInfo { UseMarketDepth = true, CurveColor = Colors.Red, StrategyName = LocalizedStrings.Str3018 }), Tuple.Create( CandlesCheckBox, CandlesTestingProcess, CandlesParameterGrid, // тест на свечах new EmulationInfo { UseCandleTimeFrame = timeFrame, CurveColor = Colors.DarkBlue, StrategyName = LocalizedStrings.Str3019 }), Tuple.Create( CandlesAndDepthsCheckBox, CandlesAndDepthsTestingProcess, CandlesAndDepthsParameterGrid, // тест на свечах + стаканы new EmulationInfo { UseMarketDepth = true, UseCandleTimeFrame = timeFrame, CurveColor = Colors.Cyan, StrategyName = LocalizedStrings.Str3020 }), Tuple.Create( OrderLogCheckBox, OrderLogTestingProcess, OrderLogParameterGrid, // тест на логе заявок new EmulationInfo { UseOrderLog = true, CurveColor = Colors.CornflowerBlue, StrategyName = LocalizedStrings.Str3021 }) }; // хранилище, через которое будет производиться доступ к тиковой и котировочной базе var storageRegistry = new StorageRegistry { // изменяем путь, используемый по умолчанию DefaultDrive = new LocalMarketDataDrive(HistoryPath.Text) }; var startTime = (DateTime)From.Value; var stopTime = (DateTime)To.Value; // ОЛ необходимо загружать с 18.45 пред дня, чтобы стаканы строились правильно if (OrderLogCheckBox.IsChecked == true) { startTime = startTime.Subtract(TimeSpan.FromDays(1)).AddHours(18).AddMinutes(45).AddTicks(1); } // задаем шаг ProgressBar var progressStep = ((stopTime - startTime).Ticks / 100).To <TimeSpan>(); // в реальности период может быть другим, и это зависит от объема данных, // хранящихся по пути HistoryPath, TicksTestingProcess.Maximum = TicksAndDepthsTestingProcess.Maximum = CandlesTestingProcess.Maximum = 100; TicksTestingProcess.Value = TicksAndDepthsTestingProcess.Value = CandlesTestingProcess.Value = 0; var logManager = new LogManager(); var fileLogListener = new FileLogListener("sample.log"); logManager.Listeners.Add(fileLogListener); //logManager.Listeners.Add(new DebugLogListener()); // чтобы смотреть логи в отладчике - работает медленно. var generateDepths = GenDepthsCheckBox.IsChecked == true; var maxDepth = MaxDepth.Text.To <int>(); var maxVolume = MaxVolume.Text.To <int>(); var secCode = secIdParts[0]; var board = ExchangeBoard.GetOrCreateBoard(secIdParts[1]); foreach (var set in settings) { if (set.Item1.IsChecked == false) { continue; } var progressBar = set.Item2; var statistic = set.Item3; var emulationInfo = set.Item4; // создаем тестовый инструмент, на котором будет производится тестирование var security = new Security { Id = SecId.Text, // по идентификатору инструмента будет искаться папка с историческими маркет данными Code = secCode, Board = board, }; var level1Info = new Level1ChangeMessage { SecurityId = security.ToSecurityId(), ServerTime = startTime, } .TryAdd(Level1Fields.PriceStep, 10m) .TryAdd(Level1Fields.StepPrice, 6m) .TryAdd(Level1Fields.MinPrice, 10m) .TryAdd(Level1Fields.MaxPrice, 1000000m) .TryAdd(Level1Fields.MarginBuy, 10000m) .TryAdd(Level1Fields.MarginSell, 10000m); // тестовый портфель var portfolio = new Portfolio { Name = "test account", BeginValue = 1000000, }; // создаем подключение для эмуляции // инициализируем настройки (инструмент в истории обновляется раз в секунду) var connector = new HistoryEmulationConnector( new[] { security }, new[] { portfolio }) { StorageRegistry = storageRegistry, MarketEmulator = { Settings = { // использовать свечи UseCandlesTimeFrame = emulationInfo.UseCandleTimeFrame, // сведение сделки в эмуляторе если цена коснулась нашей лимитной заявки. // Если выключено - требуется "прохождение цены сквозь уровень" // (более "суровый" режим тестирования.) MatchOnTouch = false, } }, //UseExternalCandleSource = true, CreateDepthFromOrdersLog = emulationInfo.UseOrderLog, CreateTradesFromOrdersLog = emulationInfo.UseOrderLog, }; connector.MarketDataAdapter.SessionHolder.MarketTimeChangedInterval = timeFrame; ((ILogSource)connector).LogLevel = DebugLogCheckBox.IsChecked == true ? LogLevels.Debug : LogLevels.Info; logManager.Sources.Add(connector); connector.NewSecurities += securities => { //подписываемся на получение данных после получения инструмента if (securities.All(s => s != security)) { return; } // отправляем данные Level1 для инструмента connector.MarketDataAdapter.SendOutMessage(level1Info); // тест подразумевает наличие стаканов if (emulationInfo.UseMarketDepth) { connector.RegisterMarketDepth(security); if ( // если выбрана генерация стаканов вместо реальных стаканов generateDepths || // для свечей генерируем стаканы всегда emulationInfo.UseCandleTimeFrame != TimeSpan.Zero ) { // если история по стаканам отсутствует, но стаканы необходимы для стратегии, // то их можно сгенерировать на основании цен последних сделок или свечек. connector.RegisterMarketDepth(new TrendMarketDepthGenerator(connector.GetSecurityId(security)) { Interval = TimeSpan.FromSeconds(1), // стакан для инструмента в истории обновляется раз в секунду MaxAsksDepth = maxDepth, MaxBidsDepth = maxDepth, UseTradeVolume = true, MaxVolume = maxVolume, MinSpreadStepCount = 2, // минимальный генерируемый спред - 2 минимальных шага цены MaxSpreadStepCount = 5, // не генерировать спрэд между лучшим бид и аск больше чем 5 минимальных шагов цены - нужно чтобы при генерации из свечей не получалось слишком широкого спреда. MaxPriceStepCount = 3 // максимальное количество шагов между ценами, }); } } else if (emulationInfo.UseOrderLog) { connector.RegisterOrderLog(security); } }; // соединяемся с трейдером и запускаем экспорт, // чтобы инициализировать переданными инструментами и портфелями необходимые свойства EmulationTrader connector.Connect(); connector.StartExport(); var candleManager = new CandleManager(connector); var series = new CandleSeries(typeof(TimeFrameCandle), security, timeFrame); _shortMa = new SimpleMovingAverage { Length = 10 }; _shortElem = new ChartIndicatorElement { Color = Colors.Coral, ShowAxisMarker = false, FullTitle = _shortMa.ToString() }; _bufferedChart.AddElement(_area, _shortElem); _longMa = new SimpleMovingAverage { Length = 80 }; _longElem = new ChartIndicatorElement { ShowAxisMarker = false, FullTitle = _longMa.ToString() }; _bufferedChart.AddElement(_area, _longElem); // создаем торговую стратегию, скользящие средние на 80 5-минуток и 10 5-минуток var strategy = new SmaStrategy(_bufferedChart, _candlesElem, _tradesElem, _shortMa, _shortElem, _longMa, _longElem, series) { Volume = 1, Portfolio = portfolio, Security = security, Connector = connector, LogLevel = DebugLogCheckBox.IsChecked == true ? LogLevels.Debug : LogLevels.Info, // по-умолчанию интервал равен 1 минут, // что для истории в диапазон от нескольких месяцев излишне UnrealizedPnLInterval = ((stopTime - startTime).Ticks / 1000).To <TimeSpan>() }; // комиссия в 1 копейку за сделку connector.MarketEmulator.SendInMessage(new CommissionRuleMessage { Rule = new CommissionPerTradeRule { Value = 0.01m } }); logManager.Sources.Add(strategy); // копируем параметры на визуальную панель statistic.Parameters.Clear(); statistic.Parameters.AddRange(strategy.StatisticManager.Parameters); var pnlCurve = Curve.CreateCurve("P&L " + emulationInfo.StrategyName, emulationInfo.CurveColor, EquityCurveChartStyles.Area); var unrealizedPnLCurve = Curve.CreateCurve(LocalizedStrings.PnLUnreal + emulationInfo.StrategyName, Colors.Black); var commissionCurve = Curve.CreateCurve(LocalizedStrings.Str159 + " " + emulationInfo.StrategyName, Colors.Red, EquityCurveChartStyles.DashedLine); var posItems = PositionCurve.CreateCurve(emulationInfo.StrategyName, emulationInfo.CurveColor); strategy.PnLChanged += () => { var pnl = new EquityData { Time = strategy.CurrentTime, Value = strategy.PnL - strategy.Commission ?? 0 }; var unrealizedPnL = new EquityData { Time = strategy.CurrentTime, Value = strategy.PnLManager.UnrealizedPnL }; var commission = new EquityData { Time = strategy.CurrentTime, Value = strategy.Commission ?? 0 }; pnlCurve.Add(pnl); unrealizedPnLCurve.Add(unrealizedPnL); commissionCurve.Add(commission); }; strategy.PositionChanged += () => posItems.Add(new EquityData { Time = strategy.CurrentTime, Value = strategy.Position }); var nextTime = startTime + progressStep; // и подписываемся на событие изменения времени, чтобы обновить ProgressBar connector.MarketTimeChanged += d => { if (connector.CurrentTime < nextTime && connector.CurrentTime < stopTime) { return; } var steps = (connector.CurrentTime - startTime).Ticks / progressStep.Ticks + 1; nextTime = startTime + (steps * progressStep.Ticks).To <TimeSpan>(); this.GuiAsync(() => progressBar.Value = steps); }; connector.StateChanged += () => { if (connector.State == EmulationStates.Stopped) { candleManager.Stop(series); strategy.Stop(); logManager.Dispose(); _connectors.Clear(); SetIsEnabled(false); this.GuiAsync(() => { if (connector.IsFinished) { progressBar.Value = progressBar.Maximum; MessageBox.Show(LocalizedStrings.Str3024.Put(DateTime.Now - _startEmulationTime)); } else { MessageBox.Show(LocalizedStrings.cancelled); } }); } else if (connector.State == EmulationStates.Started) { SetIsEnabled(true); // запускаем стратегию когда эмулятор запустился strategy.Start(); candleManager.Start(series); } }; if (ShowDepth.IsChecked == true) { MarketDepth.UpdateFormat(security); connector.NewMessage += (message, dir) => { var quoteMsg = message as QuoteChangeMessage; if (quoteMsg != null) { MarketDepth.UpdateDepth(quoteMsg); } }; } _connectors.Add(connector); } _startEmulationTime = DateTime.Now; // запускаем эмуляцию foreach (var connector in _connectors) { // указываем даты начала и конца тестирования connector.Start(startTime, stopTime); } TabControl.Items.Cast <TabItem>().First(i => i.Visibility == Visibility.Visible).IsSelected = true; }
/// <summary> /// Initializes a new instance of the <see cref="ShellWindow"/> class. /// </summary> /// <remarks>This method is required for design time support.</remarks> public ShellWindow() : base(DataWindowMode.Custom, setOwnerAndFocus: false) { var currentLogFileName = TaskRunnerEnvironment.CurrentLogFileName; if (File.Exists(currentLogFileName)) { File.Delete(currentLogFileName); } var fileLogListener = new FileLogListener(currentLogFileName, 25 * 1000) { IgnoreCatelLogging = true, IsDebugEnabled = false }; LogManager.AddListener(fileLogListener); var serviceLocator = this.GetServiceLocator(); var taskRunnerService = serviceLocator.ResolveType <ITaskRunnerService>(); var commandManager = serviceLocator.ResolveType <ICommandManager>(); var uiVisualizerService = serviceLocator.ResolveType <IUIVisualizerService>(); if (taskRunnerService.ShowCustomizeShortcutsButton) { AddCustomButton(DataWindowButton.FromAsync("Keyboard shortcuts", () => uiVisualizerService.ShowDialogAsync <KeyboardMappingsOverviewViewModel>(), null)); } serviceLocator.RegisterInstance <IAboutInfoService>(taskRunnerService); if (taskRunnerService.GetAboutInfo() != null) { var aboutService = serviceLocator.ResolveType <IAboutService>(); #pragma warning disable AvoidAsyncVoid // Avoid async void commandManager.RegisterAction("Help.About", async() => await aboutService.ShowAboutAsync()); #pragma warning restore AvoidAsyncVoid // Avoid async void AddCustomButton(new DataWindowButton("About", commandManager.GetCommand("Help.About"))); } ThemeHelper.EnsureApplicationThemes(GetType().Assembly, true); InitializeComponent(); serviceLocator.RegisterInstance <ILogControlService>(new LogControlService(traceOutputControl)); ConfigurationContext = taskRunnerService.GetViewDataContext(); var startupSize = taskRunnerService.GetInitialWindowSize(); if (startupSize != null && !startupSize.IsEmpty) { var setWidth = startupSize.Width > 0d; var setHeight = startupSize.Height > 0d; if (setHeight && setWidth) { SetCurrentValue(SizeToContentProperty, SizeToContent.Manual); } else if (setHeight) { SetCurrentValue(SizeToContentProperty, SizeToContent.Width); } else if (setWidth) { SetCurrentValue(SizeToContentProperty, SizeToContent.Height); } else { SetCurrentValue(SizeToContentProperty, SizeToContent.WidthAndHeight); } if (setWidth) { SetCurrentValue(MinWidthProperty, startupSize.Width); SetCurrentValue(WidthProperty, startupSize.Width); } if (setHeight) { SetCurrentValue(MinHeightProperty, startupSize.Height); SetCurrentValue(HeightProperty, startupSize.Height); } } var view = taskRunnerService.GetView(); contentControl.Content = view; }
/// <summary> /// Initializes a new instance of the <see cref="ShellWindow"/> class. /// </summary> /// <remarks>This method is required for design time support.</remarks> public ShellWindow() : base(DataWindowMode.Custom, setOwnerAndFocus: false) { var currentLogFileName = TaskRunnerEnvironment.CurrentLogFileName; if (File.Exists(currentLogFileName)) { File.Delete(currentLogFileName); } var fileLogListener = new FileLogListener(currentLogFileName, 25 * 1000) { IgnoreCatelLogging = true, IsDebugEnabled = false }; LogManager.AddListener(fileLogListener); var serviceLocator = this.GetServiceLocator(); var processService = serviceLocator.ResolveType <IProcessService>(); var taskRunnerService = serviceLocator.ResolveType <ITaskRunnerService>(); var commandManager = serviceLocator.ResolveType <ICommandManager>(); var uiVisualizerService = serviceLocator.ResolveType <IUIVisualizerService>(); AddCustomButton(new DataWindowButton("Open log...", () => { LogManager.FlushAll(); processService.StartProcess(currentLogFileName); })); if (taskRunnerService.ShowCustomizeShortcutsButton) { AddCustomButton(new DataWindowButton("Keyboard shortcuts", () => uiVisualizerService.ShowDialog <KeyboardMappingsOverviewViewModel>())); } serviceLocator.RegisterInstance <IAboutInfoService>(taskRunnerService); if (taskRunnerService.GetAboutInfo() != null) { var aboutService = serviceLocator.ResolveType <IAboutService>(); commandManager.RegisterAction("Help.About", aboutService.ShowAbout); AddCustomButton(new DataWindowButton("About", commandManager.GetCommand("Help.About"))); } ThemeHelper.EnsureApplicationThemes(GetType().Assembly, true); InitializeComponent(); serviceLocator.RegisterInstance <ILogControlService>(new LogControlService(traceOutputControl)); var task = taskRunnerService.GetViewDataContext(); task.Wait(); ConfigurationContext = task.Result; var startupSize = taskRunnerService.GetInitialWindowSize(); if (startupSize != null && !startupSize.IsEmpty) { bool setWidth = startupSize.Width > 0d; bool setHeight = startupSize.Height > 0d; if (setHeight && setWidth) { SizeToContent = SizeToContent.Manual; } else if (setHeight) { SizeToContent = SizeToContent.Width; } else if (setWidth) { SizeToContent = SizeToContent.Height; } else { SizeToContent = SizeToContent.WidthAndHeight; } if (setWidth) { MinWidth = startupSize.Width; Width = startupSize.Width; } if (setHeight) { MinHeight = startupSize.Height; Height = startupSize.Height; } } var view = taskRunnerService.GetView(); contentControl.Content = view; }
private void StartBtnClick(object sender, RoutedEventArgs e) { InitChart(); if (HistoryPath.Text.IsEmpty() || !Directory.Exists(HistoryPath.Text)) { MessageBox.Show(this, LocalizedStrings.Str3014); return; } if (_connectors.Any(t => t.State != EmulationStates.Stopped)) { MessageBox.Show(this, LocalizedStrings.Str3015); return; } var secIdParts = SecId.Text.Split('@'); if (secIdParts.Length != 2) { MessageBox.Show(this, LocalizedStrings.Str3016); return; } var timeFrame = TimeSpan.FromMinutes(5); // create backtesting modes var settings = new[] { Tuple.Create( TicksCheckBox, TicksTestingProcess, TicksParameterGrid, // ticks new EmulationInfo { UseTicks = true, CurveColor = Colors.DarkGreen, StrategyName = LocalizedStrings.Str3017 }), Tuple.Create( TicksAndDepthsCheckBox, TicksAndDepthsTestingProcess, TicksAndDepthsParameterGrid, // ticks + order book new EmulationInfo { UseTicks = true, UseMarketDepth = true, CurveColor = Colors.Red, StrategyName = LocalizedStrings.Str3018 }), Tuple.Create( CandlesCheckBox, CandlesTestingProcess, CandlesParameterGrid, // candles new EmulationInfo { UseCandleTimeFrame = timeFrame, CurveColor = Colors.DarkBlue, StrategyName = LocalizedStrings.Str3019 }), Tuple.Create( CandlesAndDepthsCheckBox, CandlesAndDepthsTestingProcess, CandlesAndDepthsParameterGrid, // candles + orderbook new EmulationInfo { UseMarketDepth = true, UseCandleTimeFrame = timeFrame, CurveColor = Colors.Cyan, StrategyName = LocalizedStrings.Str3020 }), Tuple.Create( OrderLogCheckBox, OrderLogTestingProcess, OrderLogParameterGrid, // order log new EmulationInfo { UseOrderLog = true, CurveColor = Colors.CornflowerBlue, StrategyName = LocalizedStrings.Str3021 }) }; // storage to historical data var storageRegistry = new StorageRegistry { // set historical path DefaultDrive = new LocalMarketDataDrive(HistoryPath.Text) }; var startTime = (DateTime)From.Value; var stopTime = (DateTime)To.Value; // ОЛ необходимо загружать с 18.45 пред дня, чтобы стаканы строились правильно if (OrderLogCheckBox.IsChecked == true) { startTime = startTime.Subtract(TimeSpan.FromDays(1)).AddHours(18).AddMinutes(45).AddTicks(1); } // ProgressBar refresh step var progressStep = ((stopTime - startTime).Ticks / 100).To <TimeSpan>(); // set ProgressBar bounds TicksTestingProcess.Maximum = TicksAndDepthsTestingProcess.Maximum = CandlesTestingProcess.Maximum = 100; TicksTestingProcess.Value = TicksAndDepthsTestingProcess.Value = CandlesTestingProcess.Value = 0; var logManager = new LogManager(); var fileLogListener = new FileLogListener("sample.log"); logManager.Listeners.Add(fileLogListener); //logManager.Listeners.Add(new DebugLogListener()); // for track logs in output window in Vusial Studio (poor performance). var generateDepths = GenDepthsCheckBox.IsChecked == true; var maxDepth = MaxDepth.Text.To <int>(); var maxVolume = MaxVolume.Text.To <int>(); var secCode = secIdParts[0]; var board = ExchangeBoard.GetOrCreateBoard(secIdParts[1]); foreach (var set in settings) { if (set.Item1.IsChecked == false) { continue; } var progressBar = set.Item2; var statistic = set.Item3; var emulationInfo = set.Item4; // create test security var security = new Security { Id = SecId.Text, // sec id has the same name as folder with historical data Code = secCode, Board = board, }; var level1Info = new Level1ChangeMessage { SecurityId = security.ToSecurityId(), ServerTime = startTime, } .TryAdd(Level1Fields.PriceStep, 10m) .TryAdd(Level1Fields.StepPrice, 6m) .TryAdd(Level1Fields.MinPrice, 10m) .TryAdd(Level1Fields.MaxPrice, 1000000m) .TryAdd(Level1Fields.MarginBuy, 10000m) .TryAdd(Level1Fields.MarginSell, 10000m); // test portfolio var portfolio = new Portfolio { Name = "test account", BeginValue = 1000000, }; // create backtesting connector var connector = new HistoryEmulationConnector( new[] { security }, new[] { portfolio }) { StorageRegistry = storageRegistry, MarketEmulator = { Settings = { // set time frame is backtesting on candles UseCandlesTimeFrame = emulationInfo.UseCandleTimeFrame, // match order if historical price touched our limit order price. // It is terned off, and price should go through limit order price level // (more "severe" test mode) MatchOnTouch = false, } }, //UseExternalCandleSource = true, CreateDepthFromOrdersLog = emulationInfo.UseOrderLog, CreateTradesFromOrdersLog = emulationInfo.UseOrderLog, }; connector.StartDate = startTime; connector.StopDate = stopTime; connector.MarketTimeChangedInterval = timeFrame; ((ILogSource)connector).LogLevel = DebugLogCheckBox.IsChecked == true ? LogLevels.Debug : LogLevels.Info; logManager.Sources.Add(connector); connector.NewSecurities += securities => { if (securities.All(s => s != security)) { return; } // fill level1 values connector.SendOutMessage(level1Info); if (emulationInfo.UseMarketDepth) { connector.RegisterMarketDepth(security); if ( // if order book will be generated generateDepths || // of backtesting will be on candles emulationInfo.UseCandleTimeFrame != TimeSpan.Zero ) { // if no have order book historical data, but strategy is required, // use generator based on last prices connector.RegisterMarketDepth(new TrendMarketDepthGenerator(connector.GetSecurityId(security)) { Interval = TimeSpan.FromSeconds(1), // order book freq refresh is 1 sec MaxAsksDepth = maxDepth, MaxBidsDepth = maxDepth, UseTradeVolume = true, MaxVolume = maxVolume, MinSpreadStepCount = 2, // min spread generation is 2 pips MaxSpreadStepCount = 5, // max spread generation size (prevent extremely size) MaxPriceStepCount = 3 // pips size, }); } } if (emulationInfo.UseOrderLog) { connector.RegisterOrderLog(security); } if (emulationInfo.UseTicks) { connector.RegisterTrades(security); } // start historical data loading when connection established successfully and all data subscribed connector.Start(); }; var candleManager = new CandleManager(connector); var series = new CandleSeries(typeof(TimeFrameCandle), security, timeFrame); _shortMa = new SimpleMovingAverage { Length = 10 }; _shortElem = new ChartIndicatorElement { Color = Colors.Coral, ShowAxisMarker = false, FullTitle = _shortMa.ToString() }; _bufferedChart.AddElement(_area, _shortElem); _longMa = new SimpleMovingAverage { Length = 80 }; _longElem = new ChartIndicatorElement { ShowAxisMarker = false, FullTitle = _longMa.ToString() }; _bufferedChart.AddElement(_area, _longElem); // create strategy based on 80 5-min и 10 5-min var strategy = new SmaStrategy(_bufferedChart, _candlesElem, _tradesElem, _shortMa, _shortElem, _longMa, _longElem, series) { Volume = 1, Portfolio = portfolio, Security = security, Connector = connector, LogLevel = DebugLogCheckBox.IsChecked == true ? LogLevels.Debug : LogLevels.Info, // by default interval is 1 min, // it is excessively for time range with several months UnrealizedPnLInterval = ((stopTime - startTime).Ticks / 1000).To <TimeSpan>() }; logManager.Sources.Add(strategy); // fill parameters panel statistic.Parameters.Clear(); statistic.Parameters.AddRange(strategy.StatisticManager.Parameters); var pnlCurve = Curve.CreateCurve("P&L " + emulationInfo.StrategyName, emulationInfo.CurveColor, EquityCurveChartStyles.Area); var unrealizedPnLCurve = Curve.CreateCurve(LocalizedStrings.PnLUnreal + emulationInfo.StrategyName, Colors.Black); var commissionCurve = Curve.CreateCurve(LocalizedStrings.Str159 + " " + emulationInfo.StrategyName, Colors.Red, EquityCurveChartStyles.DashedLine); var posItems = PositionCurve.CreateCurve(emulationInfo.StrategyName, emulationInfo.CurveColor); strategy.PnLChanged += () => { var pnl = new EquityData { Time = strategy.CurrentTime, Value = strategy.PnL - strategy.Commission ?? 0 }; var unrealizedPnL = new EquityData { Time = strategy.CurrentTime, Value = strategy.PnLManager.UnrealizedPnL }; var commission = new EquityData { Time = strategy.CurrentTime, Value = strategy.Commission ?? 0 }; pnlCurve.Add(pnl); unrealizedPnLCurve.Add(unrealizedPnL); commissionCurve.Add(commission); }; strategy.PositionChanged += () => posItems.Add(new EquityData { Time = strategy.CurrentTime, Value = strategy.Position }); var nextTime = startTime + progressStep; // handle historical time for update ProgressBar connector.MarketTimeChanged += d => { if (connector.CurrentTime < nextTime && connector.CurrentTime < stopTime) { return; } var steps = (connector.CurrentTime - startTime).Ticks / progressStep.Ticks + 1; nextTime = startTime + (steps * progressStep.Ticks).To <TimeSpan>(); this.GuiAsync(() => progressBar.Value = steps); }; connector.StateChanged += () => { if (connector.State == EmulationStates.Stopped) { candleManager.Stop(series); strategy.Stop(); logManager.Dispose(); _connectors.Clear(); SetIsEnabled(false); this.GuiAsync(() => { if (connector.IsFinished) { progressBar.Value = progressBar.Maximum; MessageBox.Show(LocalizedStrings.Str3024.Put(DateTime.Now - _startEmulationTime)); } else { MessageBox.Show(LocalizedStrings.cancelled); } }); } else if (connector.State == EmulationStates.Started) { SetIsEnabled(true); // start strategy when emulation started strategy.Start(); candleManager.Start(series); } }; if (ShowDepth.IsChecked == true) { MarketDepth.UpdateFormat(security); connector.NewMessage += (message, dir) => { var quoteMsg = message as QuoteChangeMessage; if (quoteMsg != null) { MarketDepth.UpdateDepth(quoteMsg); } }; } _connectors.Add(connector); } _startEmulationTime = DateTime.Now; // start emulation foreach (var connector in _connectors) { // raise NewSecurities and NewPortfolio for full fill strategy properties connector.Connect(); // 1 cent commission for trade connector.SendInMessage(new CommissionRuleMessage { Rule = new CommissionPerTradeRule { Value = 0.01m } }); } TabControl.Items.Cast <TabItem>().First(i => i.Visibility == Visibility.Visible).IsSelected = true; }
public DynamicPluginClient() { FileLogListener.AddFileLogListener(this); }