/// <summary> /// Load settings. /// </summary> /// <param name="storage">Storage.</param> public override void Load(SettingsStorage storage) { base.Load(storage); var boardCode = storage.GetValue <string>(nameof(Board)); if (!boardCode.IsEmpty()) { Board = ConfigManager.TryGetService <IExchangeInfoProvider>()?.GetExchangeBoard(boardCode); } }
/// <inheritdoc /> public override void Save(ExchangeBoard board) { if (board == null) { throw new ArgumentNullException(nameof(board)); } _entityRegistry.ExchangeBoards.Save(board); base.Save(board); }
private BusinessEntities.Security GetSecurity(QScalp.Security security, ExchangeBoard board) { return(new BusinessEntities.Security { Id = _idGenerator.GenerateId(security.Ticker, board), Code = security.Ticker, Board = board, PriceStep = (decimal)security.Step, Decimals = security.Precision }); }
public static TimeSpan GetTimeZone <TMetaInfo>(this BinaryMetaInfo <TMetaInfo> metaInfo, bool isUtc, SecurityId securityId) where TMetaInfo : BinaryMetaInfo <TMetaInfo> { if (isUtc) { return(metaInfo.ServerOffset); } var board = ExchangeBoard.GetBoard(securityId.BoardCode); return(board == null ? metaInfo.LocalOffset : board.Exchange.TimeZoneInfo.BaseUtcOffset); }
// Преобразует данные DataRow таблицы в Security private static Security CreateSecurity(DataRow row) { var id = row.Field <string>("Id"); var board = row.Field <string>("Board"); var priceStep = row.Field <double?>("PriceStep"); var decimals = row.Field <long?>("Decimals"); var typeInt = row.Field <long?>("Type"); SecurityTypes?type = null; if (typeInt != null) { type = (SecurityTypes)typeInt; } var expDate = row.Field <string>("ExpiryDate"); var underlyingSecurityId = row.Field <string>("UnderlyingSecurityId"); var strike = row.Field <double?>("Strike"); var optTypeInt = row.Field <long?>("OptionType"); var security = new Security { Id = id, Board = ExchangeBoard.GetOrCreateBoard(board), PriceStep = (decimal?)priceStep, Decimals = (int?)decimals, Type = type }; if (security.Type == SecurityTypes.Future || security.Type == SecurityTypes.Option) { security.ExpiryDate = string.IsNullOrWhiteSpace(expDate) ? null : (DateTimeOffset?)DateTimeOffset.Parse(expDate); security.UnderlyingSecurityId = underlyingSecurityId; if (security.Type == SecurityTypes.Option) { security.Strike = (decimal?)strike; OptionTypes?optType = null; if (optTypeInt != null) { optType = (OptionTypes)optTypeInt; } security.OptionType = optType; } } return(security); }
/// <inheritdoc /> public void UnSubscribeBoard(ExchangeBoard board) { if (board == null) { throw new ArgumentNullException(nameof(board)); } SendInMessage(new BoardRequestMessage { IsSubscribe = false, BoardCode = board.Code, TransactionId = TransactionIdGenerator.GetNextId(), }); }
public MainWindow() { InitializeComponent(); Title = TypeHelper.ApplicationNameWithVersion; Directory.CreateDirectory(_settingsDir); _logManager.Application.LogLevel = LogLevels.Verbose; _logManager.Listeners.Add(new GuiLogListener(LogControl)); _logManager.Listeners.Add(new FileLogListener { LogDirectory = "Logs", SeparateByDates = SeparateByDateModes.FileName }); Format.SetDataSource <StorageFormats>(); Format.SetSelectedValue <StorageFormats>(StorageFormats.Binary); Board.Boards.AddRange(ExchangeBoard.EnumerateExchangeBoards().Where(b => b.Exchange == Exchange.Moex)); Board.SelectedBoard = ExchangeBoard.Forts; try { if (File.Exists(_settingsFile)) { var settings = new XmlSerializer <Settings>().Deserialize(_settingsFile); QshFolder.Folder = settings.QshFolder; StockSharpFolder.Folder = settings.StockSharpFolder; Format.SetSelectedValue <StorageFormats>(settings.Format); SecurityLike.Text = settings.SecurityLike; MultiThread.IsChecked = settings.MultiThread; OrderLog2OrderBook.IsChecked = settings.OrderLog2OrderBook; Board.SelectedBoard = settings.Board.IsEmpty() ? ExchangeBoard.Forts : Board.Boards.FirstOrDefault(b => b.Code.CompareIgnoreCase(settings.Board)) ?? ExchangeBoard.Forts; } if (File.Exists(_convertedFilesFile)) { _convertedFiles.AddRange(File.ReadAllLines(_convertedFilesFile)); } } catch (Exception ex) { ex.LogError(); } }
/// <summary> /// Сгенерировать <see cref="Security.Id"/> инструмента. /// </summary> /// <param name="secCode">Код инструмента.</param> /// <param name="board">Площадка инструмента.</param> /// <returns><see cref="Security.Id"/> инструмента.</returns> public virtual string GenerateId(string secCode /*, string secClass*/, ExchangeBoard board) { if (secCode.IsEmpty()) { throw new ArgumentNullException("secCode"); } if (board == null) { throw new ArgumentNullException("board"); } return(GenerateId(secCode, board.Code)); }
public void UnSubscribeBoard(ExchangeBoard board) { if (board == null) { throw new ArgumentNullException(nameof(board)); } var subscription = _subscriptionManager.TryFindSubscription(0, DataType.BoardState); if (subscription == null) { return; } UnSubscribe(subscription); }
/// <inheritdoc /> public void LookupBoards(ExchangeBoard criteria, IMessageAdapter adapter = null, MessageOfflineModes offlineMode = MessageOfflineModes.None) { if (criteria == null) { throw new ArgumentNullException(nameof(criteria)); } var msg = new BoardLookupMessage { TransactionId = TransactionIdGenerator.GetNextId(), Like = criteria.Code, Adapter = adapter, OfflineMode = offlineMode, }; LookupBoards(msg); }
/// <summary> /// To get the number of time frames within the specified time range. /// </summary> /// <param name="board">The information about the board by which working hours are calculated through the <see cref="ExchangeBoard.WorkingTime"/> property.</param> /// <param name="range">The specified time range for which you need to get the number of time frames.</param> /// <param name="timeFrame">The time frame size.</param> /// <returns>The received number of time frames.</returns> public static long GetTimeFrameCount(this ExchangeBoard board, Range <DateTimeOffset> range, TimeSpan timeFrame) { if (board == null) { throw new ArgumentNullException(nameof(board)); } if (range == null) { throw new ArgumentNullException(nameof(range)); } var workingTime = board.WorkingTime; var to = range.Max.ToLocalTime(board.TimeZone); var from = range.Min.ToLocalTime(board.TimeZone); var days = (int)(to.Date - from.Date).TotalDays; var period = workingTime.GetPeriod(from); if (period == null || period.Times.IsEmpty()) { return((to - from).Ticks / timeFrame.Ticks); } if (days == 0) { return(workingTime.GetTimeFrameCount(from, new Range <TimeSpan>(from.TimeOfDay, to.TimeOfDay), timeFrame)); } var totalCount = workingTime.GetTimeFrameCount(from, new Range <TimeSpan>(from.TimeOfDay, TimeHelper.LessOneDay), timeFrame); totalCount += workingTime.GetTimeFrameCount(to, new Range <TimeSpan>(TimeSpan.Zero, to.TimeOfDay), timeFrame); if (days <= 1) { return(totalCount); } var fullDayLength = period.Times.Sum(r => r.Length.Ticks); totalCount += TimeSpan.FromTicks((days - 1) * fullDayLength).Ticks / timeFrame.Ticks; return(totalCount); }
/// <summary> /// To save the board. /// </summary> /// <param name="board">Trading board.</param> public virtual void Save(ExchangeBoard board) { if (board == null) { throw new ArgumentNullException(nameof(board)); } lock (_boards.SyncRoot) { if (!_boards.TryAdd(board.Code, board)) { return; } } BoardAdded?.Invoke(board); }
private Security TryCreateSecurity(SecurityId securityId) { if (securityId.SecurityCode.IsEmpty() || securityId.BoardCode.IsEmpty()) { return(null); } var security = new Security { Id = securityId.ToStringId(), Code = securityId.SecurityCode, Board = ExchangeBoard.GetOrCreateBoard(securityId.BoardCode), ExtensionInfo = new Dictionary <object, object>() }; _entityRegistry.Securities.Add(security); return(security); }
/// <summary> /// To save the board. /// </summary> /// <param name="board">Trading board.</param> public void Save(ExchangeBoard board) { if (board == null) { throw new ArgumentNullException(nameof(board)); } _entityRegistry.ExchangeBoards.Save(board); lock (_boards.SyncRoot) { if (!_boards.TryAdd(board.Code, board)) { return; } } BoardAdded.SafeInvoke(board); }
/// <summary> /// To save the board. /// </summary> /// <param name="board">Trading board.</param> public virtual void Save(ExchangeBoard board) { if (board == null) { throw new ArgumentNullException(nameof(board)); } lock (_boards.SyncRoot) { var oldBoard = _boards.TryGetValue(board.Code); if (ReferenceEquals(oldBoard, board)) { return; } _boards[board.Code] = board; } BoardAdded?.Invoke(board); }
public Security CreateSecurity(string secStr) { Security security; int strLn = secStr.IndexOfAny("@".ToCharArray()); string secBorad = secStr.Substring(strLn + 1); ExchangeBoard eb = new ExchangeBoard(); SecurityTypes st = new SecurityTypes(); switch (secBorad) { case "FORTS": eb = ExchangeBoard.Forts; st = SecurityTypes.Future; break; case "EQBR": eb = ExchangeBoard.MicexEqbr; st = SecurityTypes.Stock; break; default: eb = ExchangeBoard.Micex; st = SecurityTypes.Future; break; } string secCode = secStr.Substring(0, strLn); security = new Security() { Id = secStr, Code = secCode, Board = eb, Type = st }; return(security); }
private void ProcessTime(DateTimeOffset time, string boardCode) { if (boardCode.IsEmpty()) { return; } var exchangeBoard = ExchangeBoard.GetBoard(boardCode); if (exchangeBoard == null) { return; } if (time <= exchangeBoard.Exchange.ToExchangeTime(_connectTime)) { return; } _isInitialization = false; _strategy.SetIsInitialization(false); }
protected override IEnumerable <T> OnGetGroup(long startIndex, long count, Field orderBy, ListSortDirection direction) { var securities = base.OnGetGroup(startIndex, count, orderBy, direction); var logManager = ConfigManager.TryGetService <LogManager>(); foreach (var security in securities) { if (security.Board == null) { if (logManager != null) { logManager.Application.AddWarningLog(LocalizedStrings.Str3626Params.Put(security.Id)); } if (!security.Class.IsEmpty()) { security.Board = ExchangeBoard.GetBoard(security.Class); } if (security.Board == null) { var parts = security.Id.Split('@'); if (parts.Length == 2) { security.Board = ExchangeBoard.GetBoard(parts[1]); } } if (security.Board == null) { security.Board = ExchangeBoard.Associated; } } } return(securities); }
private Security GetSecurityBySecCode(string secCode) { var sfxSecurity = new SfxSecurity { SlotID = _slot.ID, SecCode = secCode }; sfxSecurity.Load().ThrowIfNeed(LocalizedStrings.Str3704); secCode = sfxSecurity.SecCode; var secBoard = ExchangeBoard.GetBoard(sfxSecurity.SecBoard); var id = SecurityIdGenerator.GenerateId(secCode, secBoard); return(GetSecurity(id, name => { var security = EntityFactory.CreateSecurity(name); security.Board = secBoard; security.Code = secCode; return security; }, security => false)); }
private Security InitSecurity(SecurityId securityId) { var id = securityId.SecurityCode + "@" + securityId.BoardCode; var security = _entityRegistry.Securities.ReadById(id); if (security != null) { return(security); } security = new Security { Id = id, ExtensionInfo = new Dictionary <object, object>(), Code = securityId.SecurityCode, Board = ExchangeBoard.GetOrCreateBoard(securityId.SecurityCode), Type = securityId.SecurityType, }; _entityRegistry.Securities.Save(security); _logManager.Application.AddInfoLog(LocalizedStrings.Str2871Params.Put(id)); return(security); }
private void ProviderOnBoardAdded(ExchangeBoard board) { Dispatcher.GuiAsync(() => { //using (Dispatcher.DisableProcessing()) try { _updatingUI = true; //var selectedVal = CbBoardCode.SelectedValue as string ?? CbBoardCode.Text.Trim(); //Boards.Clear(); Boards.Add(board); CbBoardCode.SelectedItem = board; //if (!selectedVal.IsEmpty()) SetBoardCode(board.Code); } finally { _updatingUI = false; } }); }
/// <summary> /// Initializes a new instance of the <see cref="InMemoryExchangeInfoProvider"/>. /// </summary> public InMemoryExchangeInfoProvider() { ExchangeBoard.EnumerateExchanges().ForEach(b => _exchanges[b.Name] = b); ExchangeBoard.EnumerateExchangeBoards().ForEach(b => _boards[b.Code] = b); }
private void Sync_Click(object sender, RoutedEventArgs e) { if (_token != null) { StopSync(); return; } Sync.Content = LocalizedStrings.Str2890; _token = new CancellationTokenSource(); Task.Factory.StartNew(() => { var securityPaths = new List <string>(); foreach (var dir in DriveCache.Instance.AllDrives .OfType <LocalMarketDataDrive>() .Select(drive => drive.Path) .Distinct()) { foreach (var letterDir in InteropHelper.GetDirectories(dir)) { if (_token.IsCancellationRequested) { break; } var name = Path.GetFileName(letterDir); if (name == null || name.Length != 1) { continue; } securityPaths.AddRange(InteropHelper.GetDirectories(letterDir)); } if (_token.IsCancellationRequested) { break; } } if (_token.IsCancellationRequested) { return; } var iterCount = securityPaths.Count + // кол-во проходов по директории для создания инструмента DriveCache.Instance.AllDrives.Count() * (EntityRegistry.Securities.Count + securityPaths.Count); // кол-во сбросов кэша дат this.GuiSync(() => Progress.Maximum = iterCount); var logSource = ConfigManager.GetService <LogManager>().Application; var securityIdGenerator = new SecurityIdGenerator(); var securities = EntityRegistry.Securities.ToDictionary(s => s.Id, s => new KeyValuePair <Security, bool>(s, true), StringComparer.InvariantCultureIgnoreCase); foreach (var securityPath in securityPaths) { if (_token.IsCancellationRequested) { break; } var securityId = Path.GetFileName(securityPath).FolderNameToSecurityId(); var isNew = false; var security = securities.TryGetValue(securityId).Key; if (security == null) { var firstDataFile = Directory.EnumerateDirectories(securityPath) .SelectMany(d => Directory.EnumerateFiles(d, "*.bin") .Concat(Directory.EnumerateFiles(d, "*.csv")) .OrderBy(f => Path.GetExtension(f).CompareIgnoreCase(".bin") ? 0 : 1)) .FirstOrDefault(); if (firstDataFile != null) { var info = securityIdGenerator.Split(securityId); decimal priceStep; if (Path.GetExtension(firstDataFile).CompareIgnoreCase(".bin")) { try { priceStep = File.ReadAllBytes(firstDataFile).Range(6, 16).To <decimal>(); } catch (Exception ex) { throw new InvalidOperationException(LocalizedStrings.Str2929Params.Put(firstDataFile), ex); } } else { priceStep = 0.01m; } security = new Security { Id = securityId, PriceStep = priceStep, Name = info.Item1, Code = info.Item1, Board = ExchangeBoard.GetOrCreateBoard(info.Item2), ExtensionInfo = new Dictionary <object, object>() }; securities.Add(securityId, new KeyValuePair <Security, bool>(security, false)); isNew = true; } } this.GuiSync(() => { Progress.Value++; if (isNew) { Logs.Messages.Add(new LogMessage(logSource, TimeHelper.Now, LogLevels.Info, LocalizedStrings.Str2930Params.Put(security))); } }); } EntityRegistry.Securities.AddRange(securities.Values.Where(p => !p.Value).Select(p => p.Key)); if (_token.IsCancellationRequested) { return; } var dataTypes = new Dictionary <Type, object> { { typeof(ExecutionMessage), ExecutionTypes.Tick }, { typeof(ExecutionMessage), ExecutionTypes.OrderLog }, { typeof(ExecutionMessage), ExecutionTypes.Order }, { typeof(ExecutionMessage), ExecutionTypes.Trade }, { typeof(QuoteChangeMessage), null }, { typeof(Level1ChangeMessage), null }, { typeof(NewsMessage), null } }; var formats = Enumerator.GetValues <StorageFormats>(); foreach (var drive in DriveCache.Instance.AllDrives) { foreach (var security in EntityRegistry.Securities) { foreach (var dataType in dataTypes) { foreach (var format in formats) { if (_token.IsCancellationRequested) { break; } drive.GetStorageDrive(security.ToSecurityId(), dataType.Key, dataType.Value, format).ClearDatesCache(); } } if (_token.IsCancellationRequested) { break; } this.GuiSync(() => { Progress.Value++; Logs.Messages.Add(new LogMessage(logSource, TimeHelper.Now, LogLevels.Info, LocalizedStrings.Str2931Params.Put(security, drive.Path))); }); } if (_token.IsCancellationRequested) { break; } } }, _token.Token) .ContinueWithExceptionHandling(this, res => { Sync.Content = LocalizedStrings.Str2932; Sync.IsEnabled = true; Progress.Value = 0; _token = null; }); }
private void ProcessSessionMessage(SessionMessage message) { var board = ExchangeBoard.GetOrCreateBoard(message.BoardCode); _sessionStates[board] = message.State; SessionStateChanged?.Invoke(board, message.State); }
public Tuple <News, bool> ProcessNewsMessage(Security security, NewsMessage message) { if (message == null) { throw new ArgumentNullException("message"); } var isNew = false; News news; if (!message.Id.IsEmpty()) { news = _cache.NewsById.SafeAdd(message.Id, key => { isNew = true; return(EntityFactory.CreateNews()); }); } else { isNew = true; news = EntityFactory.CreateNews(); _cache.NewsWithoutId.Add(news); } if (isNew) { news.ServerTime = message.ServerTime; news.LocalTime = message.LocalTime; } if (!message.Source.IsEmpty()) { news.Source = message.Source; } if (!message.Headline.IsEmpty()) { news.Headline = message.Headline; } if (security != null) { news.Security = security; } if (!message.Story.IsEmpty()) { news.Story = message.Story; } if (!message.BoardCode.IsEmpty()) { news.Board = ExchangeBoard.GetOrCreateBoard(message.BoardCode); } if (message.Url != null) { news.Url = message.Url; } message.CopyExtensionInfo(news); return(Tuple.Create(news, isNew)); }
/// <summary> /// To get candle time frames relatively to the exchange working hours. /// </summary> /// <param name="timeFrame">The time frame for which you need to get time range.</param> /// <param name="currentTime">The current time within the range of time frames.</param> /// <param name="board">The information about the board from which <see cref="ExchangeBoard.WorkingTime"/> working hours will be taken.</param> /// <returns>The candle time frames.</returns> public static Range <DateTimeOffset> GetCandleBounds(this TimeSpan timeFrame, DateTimeOffset currentTime, ExchangeBoard board) { if (board == null) { throw new ArgumentNullException(nameof(board)); } return(timeFrame.GetCandleBounds(currentTime, board, board.WorkingTime)); }
/// <summary> /// To get candle time frames relatively to the exchange working pattern. /// </summary> /// <param name="timeFrame">The time frame for which you need to get time range.</param> /// <param name="currentTime">The current time within the range of time frames.</param> /// <param name="board">Board info.</param> /// <param name="time">The information about the exchange working pattern.</param> /// <returns>The candle time frames.</returns> public static Range <DateTimeOffset> GetCandleBounds(this TimeSpan timeFrame, DateTimeOffset currentTime, ExchangeBoard board, WorkingTime time) { if (board == null) { throw new ArgumentNullException(nameof(board)); } if (time == null) { throw new ArgumentNullException(nameof(time)); } var exchangeTime = currentTime.ToLocalTime(board.TimeZone); Range <DateTime> bounds; if (timeFrame.Ticks == _weekTf) { var monday = exchangeTime.StartOfWeek(DayOfWeek.Monday); var endDay = exchangeTime.Date; while (endDay.DayOfWeek != DayOfWeek.Sunday) { var nextDay = endDay.AddDays(1); if (nextDay.Month != endDay.Month) { break; } endDay = nextDay; } bounds = new Range <DateTime>(monday, endDay.EndOfDay()); } else if (timeFrame.Ticks == TimeHelper.TicksPerMonth) { var month = new DateTime(exchangeTime.Year, exchangeTime.Month, 1); bounds = new Range <DateTime>(month, (month + TimeSpan.FromDays(month.DaysInMonth())).EndOfDay()); } else { var period = time.GetPeriod(exchangeTime); // http://stocksharp.com/forum/yaf_postsm13887_RealtimeEmulationTrader---niepravil-nyie-sviechi.aspx#post13887 // отсчет свечек идет от начала сессии и игнорируются клиринги var startTime = period != null && period.Times.Length > 0 ? period.Times[0].Min : TimeSpan.Zero; var length = (exchangeTime.TimeOfDay - startTime).To <long>(); var beginTime = exchangeTime.Date + (startTime + length.Floor(timeFrame.Ticks).To <TimeSpan>()); //последняя свеча должна заканчиваться в конец торговой сессии var tempEndTime = beginTime.TimeOfDay + timeFrame; TimeSpan stopTime; if (period != null && period.Times.Length > 0) { var last = period.Times.LastOrDefault(t => tempEndTime > t.Min); stopTime = last == null ? TimeSpan.MaxValue : last.Max; } else { stopTime = TimeSpan.MaxValue; } var endTime = beginTime + timeFrame.Min(stopTime - beginTime.TimeOfDay); // если currentTime попало на клиринг if (endTime < beginTime) { endTime = beginTime.Date + tempEndTime; } var days = timeFrame.Days > 1 ? timeFrame.Days - 1 : 0; var min = beginTime.Truncate(TimeSpan.TicksPerMillisecond); var max = endTime.Truncate(TimeSpan.TicksPerMillisecond).AddDays(days); bounds = new Range <DateTime>(min, max); } var offset = currentTime.Offset; var diff = currentTime.DateTime - exchangeTime; return(new Range <DateTimeOffset>( (bounds.Min + diff).ApplyTimeZone(offset), (bounds.Max + diff).ApplyTimeZone(offset))); }
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.Ticks }), Tuple.Create( TicksAndDepthsCheckBox, TicksAndDepthsTestingProcess, TicksAndDepthsParameterGrid, // ticks + order book new EmulationInfo { UseTicks = true, UseMarketDepth = true, CurveColor = Colors.Red, StrategyName = LocalizedStrings.XamlStr757 }), Tuple.Create( DepthsCheckBox, DepthsTestingProcess, DepthsParameterGrid, // order book new EmulationInfo { UseMarketDepth = true, CurveColor = Colors.OrangeRed, StrategyName = LocalizedStrings.MarketDepths }), Tuple.Create( CandlesCheckBox, CandlesTestingProcess, CandlesParameterGrid, // candles new EmulationInfo { UseCandleTimeFrame = timeFrame, CurveColor = Colors.DarkBlue, StrategyName = LocalizedStrings.Candles }), Tuple.Create( CandlesAndDepthsCheckBox, CandlesAndDepthsTestingProcess, CandlesAndDepthsParameterGrid, // candles + orderbook new EmulationInfo { UseMarketDepth = true, UseCandleTimeFrame = timeFrame, CurveColor = Colors.Cyan, StrategyName = LocalizedStrings.XamlStr635 }), Tuple.Create( OrderLogCheckBox, OrderLogTestingProcess, OrderLogParameterGrid, // order log new EmulationInfo { UseOrderLog = true, CurveColor = Colors.CornflowerBlue, StrategyName = LocalizedStrings.OrderLog }) }; // storage to historical data var storageRegistry = new StorageRegistry { // set historical path DefaultDrive = new LocalMarketDataDrive(HistoryPath.Text) }; var startTime = ((DateTime)From.Value).ChangeKind(DateTimeKind.Utc); var stopTime = ((DateTime)To.Value).ChangeKind(DateTimeKind.Utc); // ОЛ необходимо загружать с 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 _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 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 }) { MarketEmulator = { 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, }, // 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 = emulationInfo.UseCandleTimeFrame == null ? new CandleManager(new TradeCandleBuilderSourceEx(connector)) : 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); connector.NewSecurities += securities => { if (securities.All(s => s != security)) { return; } // fill level1 values connector.SendInMessage(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 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 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(this, LocalizedStrings.Str3024.Put(DateTime.Now - _startEmulationTime)); } else { MessageBox.Show(this, LocalizedStrings.cancelled); } }); } else if (connector.State == EmulationStates.Started) { SetIsEnabled(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 OnNewSecurity(int row, int rowCount, string smartId, string name, string secCode, string secClass, int decimals, int lotSize, decimal?stepPrice, decimal?priceStep, string isin, string board, DateTime?expiryDate, decimal?daysBeforeExpiry, decimal?strike) { //AMU: заглушка. 11.01.2013 обнаружил, что через SmartCom стали приходить инструменты (класс EQBR и FISS) с пустым secCode - "longName" в понятии АйтиИнвеста if (secCode.IsEmpty()) { secCode = smartId; } var securityId = new SecurityId { SecurityCode = secCode, BoardCode = board, Native = smartId, Isin = isin }; if (secClass.IsEmpty()) { secClass = board; } var secMsg = new SecurityMessage { PriceStep = priceStep, Decimals = decimals, Multiplier = lotSize, Name = name, ShortName = name, ExpiryDate = expiryDate?.ApplyTimeZone(TimeHelper.Moscow), ExtensionInfo = new Dictionary <object, object> { { "Class", secClass } }, OriginalTransactionId = _lookupSecuritiesId }; if (secClass.CompareIgnoreCase("IDX")) { secMsg.SecurityType = SecurityTypes.Index; switch (secMsg.SecurityId.BoardCode) { case "RUSIDX": securityId.BoardCode = secCode.ContainsIgnoreCase("MICEX") || secCode.ContainsIgnoreCase("MCX") ? ExchangeBoard.Micex.Code : ExchangeBoard.Forts.Code; break; //default: // security.Board = ExchangeBoard.Test; // break; } } else { var info = SecurityClassInfo.GetSecurityClassInfo(secClass); secMsg.SecurityType = info.Item1; securityId.BoardCode = info.Item2; // http://stocksharp.com/forum/yaf_postsm16847_Vopros-po-vystavlieniiu-zaiavok.aspx#post16847 if (ExchangeBoard.GetOrCreateBoard(info.Item2).IsMicex && /* проверяем, что не началась ли трансляция правильных дробных шагов */ secMsg.PriceStep != null && secMsg.PriceStep == (int)secMsg.PriceStep) { // http://stocksharp.com/forum/yaf_postsm21245_Sokhranieniie-stakanov-po-GAZP-EQNE.aspx#post21245 secMsg.PriceStep = 1m / 10m.Pow(secMsg.PriceStep.Value); } } secMsg.SecurityId = securityId; if (secMsg.SecurityType == SecurityTypes.Option) { var optionInfo = secMsg.Name.GetOptionInfo(ExchangeBoard.Forts); if (optionInfo != null) { // http://stocksharp.com/forum/yaf_postst1355_Exception-Change-Set-11052.aspx if (!secCode.IsEmpty()) { var futureInfo = optionInfo.UnderlyingSecurityId.GetFutureInfo(secCode, ExchangeBoard.Forts); if (futureInfo != null) { secMsg.UnderlyingSecurityCode = futureInfo.SecurityId.SecurityCode; } } secMsg.ExpiryDate = optionInfo.ExpiryDate; secMsg.OptionType = optionInfo.OptionType; secMsg.Strike = optionInfo.Strike; } } SendOutMessage(secMsg); if (stepPrice != null) { SendOutMessage( new Level1ChangeMessage { SecurityId = securityId, ServerTime = CurrentTime.Convert(TimeHelper.Moscow), } .TryAdd(Level1Fields.StepPrice, stepPrice.Value)); } if ((row + 1) < rowCount) { return; } SendOutMessage(new SecurityLookupResultMessage { OriginalTransactionId = _lookupSecuritiesId }); _lookupSecuritiesId = 0; }
public static Transaction CreateRegisterTransaction(this IMessageSessionHolder sessionHolder, OrderRegisterMessage message, string orderAccount) { if (sessionHolder == null) { throw new ArgumentNullException("sessionHolder"); } if (message == null) { throw new ArgumentNullException("message"); } var board = ExchangeBoard.GetOrCreateBoard(message.SecurityId.BoardCode); var needDepoAccount = board.IsMicex || board.IsUxStock; if (needDepoAccount) { if (orderAccount.IsEmpty()) { throw new ArgumentException(LocalizedStrings.Str1848Params.Put(message.PortfolioName)); } } else { orderAccount = message.PortfolioName; } var transaction = new Transaction(TransactionTypes.Register, message); transaction .SetAccount(orderAccount) .SetSecurity(sessionHolder, message) .SetVolume((int)message.Volume); //20-ти символьное составное поле, может содержать код клиента и текстовый комментарий с тем же разделителем, что и при вводе заявки вручную. //для ртс код клиента не обязателен var clientCode = needDepoAccount ? message.PortfolioName : string.Empty; if (!message.Comment.IsEmpty()) { // http://www.quik.ru/forum/import/24383 var splitter = message.PortfolioName.Contains("/") ? "//" : "/"; clientCode = clientCode.IsEmpty() ? message.Comment : "{0}{1}{2}".Put(clientCode, splitter, message.Comment); if (clientCode.Length > 20) { clientCode = clientCode.Remove(20); } } if (!clientCode.IsEmpty()) { transaction.SetClientCode(clientCode); } transaction.SetExpiryDate(message.TillDate); if (message.VisibleVolume != null && message.VisibleVolume != message.Volume) { return(transaction .SetAction(TransactionActions.Iceberg) .SetVisibleVolume((int)message.VisibleVolume) .SetInstruction("Цена", transaction.GetInstruction(Transaction.Price)) .SetInstruction("К/П", message.Side == Sides.Buy ? "Купля" : "Продажа") .SetInstruction("Тип", "Лимитная") .SetInstruction("Тип по цене", "по разным ценам") .SetInstruction("Тип по остатку", "поставить в очередь") .SetInstruction("Тип ввода значения цены", "По цене") .SetInstruction("Торговый счет", transaction.GetInstruction(Transaction.Account)) .RemoveInstruction(Transaction.Account) .SetInstruction("Инструмент", transaction.GetInstruction(Transaction.SecurityCode)) .RemoveInstruction(Transaction.SecurityCode) .SetInstruction("Лоты", transaction.GetInstruction(Transaction.Volume)) .RemoveInstruction(Transaction.Volume) .SetInstruction("Примечание", transaction.GetInstruction(Transaction.ClientCode)) .RemoveInstruction(Transaction.ClientCode)); } switch (message.OrderType) { case OrderTypes.Market: case OrderTypes.Limit: transaction .SetSide(message.Side) .SetType(message.OrderType) .SetAction(TransactionActions.NewOrder) .SetPrice(message.Price); var tif = message.TimeInForce ?? TimeInForce.PutInQueue; if (!(message.SecurityId.SecurityType == SecurityTypes.Future && tif == TimeInForce.PutInQueue)) { transaction.SetTimeInForce(tif); } break; case OrderTypes.Conditional: { var condition = (QuikOrderCondition)message.Condition; if (condition.ConditionOrderId != null && condition.ConditionOrderSide != null) { message.Side = condition.ConditionOrderSide.Value.Invert(); } transaction .SetSide(message.Side) .SetAction(TransactionActions.NewStopOrder) .SetStopPrice(condition.StopPrice ?? 0); if (message.Price != 0) { transaction.SetPrice(message.Price); } string stopOrderKind; string stopPriceCondition; switch (condition.Type) { case QuikOrderConditionTypes.LinkedOrder: stopOrderKind = TransactionStopOrderKinds.WithLinkedLimitOrder; transaction .SetLinkedOrderPrice(condition.LinkedOrderPrice ?? 0) .SetLinkedOrderCancel(condition.LinkedOrderCancel ?? false); stopPriceCondition = message.Side == Sides.Buy ? ">=" : "<="; break; case QuikOrderConditionTypes.OtherSecurity: var otherSec = condition.OtherSecurityId; if (otherSec == null) { throw new ArgumentException(); } stopOrderKind = TransactionStopOrderKinds.ConditionPriceByOtherSecurity; transaction.SetOtherSecurity(sessionHolder, (SecurityId)otherSec); stopPriceCondition = condition.StopPriceCondition == QuikStopPriceConditions.MoreOrEqual ? ">=" : "<="; break; case QuikOrderConditionTypes.StopLimit: stopPriceCondition = null; stopOrderKind = null; break; case QuikOrderConditionTypes.TakeProfit: stopPriceCondition = null; stopOrderKind = TransactionStopOrderKinds.TakeProfit; break; case QuikOrderConditionTypes.TakeProfitStopLimit: stopPriceCondition = null; stopOrderKind = TransactionStopOrderKinds.TakeProfitAndStopLimit; if (condition.ActiveTime != null) { transaction .SetIsActiveInTime(true) .SetActiveFrom(condition.ActiveTime.Min.UtcDateTime) .SetActiveTo(condition.ActiveTime.Max.UtcDateTime); } else { // http://stocksharp.com/forum/yaf_postsm25524_Nie-rabotaiet-razmieshchieniie-ordierov-po-ispolnieniiu.aspx // IS_ACTIVE_IN_TIME Признак действия заявки типа «Тэйк-профит и стоп-лимит» if (condition.ConditionOrderId == null) { transaction.SetIsActiveInTime(false); } } if (condition.IsMarketTakeProfit != null) { transaction.SetMarketTakeProfit((bool)condition.IsMarketTakeProfit); } if (condition.IsMarketStopLimit != null) { transaction.SetMarketStopLimit((bool)condition.IsMarketStopLimit); } if (condition.StopLimitPrice != null) { transaction.SetStopLimitPrice((decimal)condition.StopLimitPrice); } break; default: throw new ArgumentOutOfRangeException(); } if (condition.ConditionOrderId != null) { if (stopOrderKind.IsEmpty()) { stopOrderKind = TransactionStopOrderKinds.SimpleStopLimit; } stopOrderKind = TransactionStopOrderKinds.ActivatedByOrder + stopOrderKind; transaction .SetConditionOrderId((long)condition.ConditionOrderId) .SetConditionOrderUseMatchedBalance(condition.ConditionOrderUseMatchedBalance ?? false) .SetConditionOrderPartiallyMatched(condition.ConditionOrderPartiallyMatched ?? false); } if (condition.Type == QuikOrderConditionTypes.TakeProfit || condition.Type == QuikOrderConditionTypes.TakeProfitStopLimit) { if (condition.Offset != null) { transaction.SetOffset(condition.Offset); } if (condition.Spread != null) { transaction.SetSpread(condition.Spread); } } if (!stopOrderKind.IsEmpty()) { transaction.SetStopOrderKind(stopOrderKind); } if (!stopPriceCondition.IsEmpty()) { transaction.SetStopPriceCondition(stopPriceCondition); } break; } case OrderTypes.Repo: { var orderInfo = message.RepoInfo; transaction .SetAction(TransactionActions.NewRepoNegDeal) .SetSide(message.Side) .SetPrice(message.Price); if (orderInfo.BlockSecurities != null) { transaction.SetBlockSecurities((bool)orderInfo.BlockSecurities); } if (orderInfo.Partner != null) { transaction.SetPartner(orderInfo.Partner); } if (orderInfo.MatchRef != null) { transaction.SetMatchRef(orderInfo.MatchRef); } if (orderInfo.RefundRate != null) { transaction.SetRefundRate((int)orderInfo.RefundRate); } if (orderInfo.Rate != null) { transaction.SetRepoRate((int)orderInfo.Rate); } if (orderInfo.Value != null) { transaction.SetRepoValue((decimal)orderInfo.Value); } if (orderInfo.Term != null) { transaction.SetRepoTerm((int)orderInfo.Term); } if (orderInfo.SecondPrice != null) { transaction.SetSecondPrice((decimal)orderInfo.SecondPrice); } if (orderInfo.SettleCode != null) { transaction.SetSettleCode(orderInfo.SettleCode); } if (orderInfo.SettleDate != null) { transaction.SetSettleDate(orderInfo.SettleDate.Value.ToLocalTime(TimeHelper.Moscow)); } if (orderInfo.LowerDiscount != null) { transaction.SetLowerDiscount((int)orderInfo.LowerDiscount); } if (orderInfo.StartDiscount != null) { transaction.SetStartDiscount((int)orderInfo.StartDiscount); } if (orderInfo.UpperDiscount != null) { transaction.SetUpperDiscount((int)orderInfo.UpperDiscount); } break; } case OrderTypes.Rps: { var orderInfo = message.RpsInfo; transaction .SetAction(TransactionActions.NewNegDeal) .SetSide(message.Side) .SetPrice(message.Price); if (orderInfo.Partner != null) { transaction.SetPartner(orderInfo.Partner); } if (orderInfo.MatchRef != null) { transaction.SetMatchRef(orderInfo.MatchRef); } if (orderInfo.SettleCode != null) { transaction.SetSettleCode(orderInfo.SettleCode); } if (orderInfo.SettleDate != null) { transaction.SetSettleDate(orderInfo.SettleDate.Value.ToLocalTime(TimeHelper.Moscow)); } if (orderInfo.ForAccount != null) { transaction.SetForAccount(orderInfo.ForAccount); } transaction.SetCurrencyCode(orderInfo.CurrencyType.ToMicexCurrencyName()); break; } default: throw new NotSupportedException(LocalizedStrings.Str1849Params.Put(message.Type)); } return(transaction); }