internal static DateTimeOffset GetExpirationTime(this Security security, IExchangeInfoProvider provider) { if (security == null) { throw new ArgumentNullException(nameof(security)); } if (provider == null) { throw new ArgumentNullException(nameof(provider)); } if (security.ExpiryDate == null) { throw new ArgumentException(LocalizedStrings.Str709Params.Put(security.Id), nameof(security)); } var expDate = security.ExpiryDate.Value; if (expDate.TimeOfDay == TimeSpan.Zero) { var board = provider.GetOrCreateBoard(security.ToSecurityId().BoardCode); expDate += board.ExpiryTime; } return(expDate); }
///// <summary> ///// Reset state. ///// </summary> //public override void Reset() //{ // base.Reset(); // _timeoutInfos.Clear(); //} /// <summary> /// To create a new candle. /// </summary> /// <param name="message">Market-data message (uses as a subscribe/unsubscribe in outgoing case, confirmation event in incoming case).</param> /// <param name="currentCandle">The current candle.</param> /// <param name="value">Data with which a new candle should be created.</param> /// <returns>Created candle.</returns> protected override TimeFrameCandleMessage CreateCandle(MarketDataMessage message, TimeFrameCandleMessage currentCandle, ICandleBuilderSourceValue value) { var timeFrame = (TimeSpan)message.Arg; var board = _exchangeInfoProvider.GetOrCreateBoard(message.SecurityId.BoardCode); var bounds = timeFrame.GetCandleBounds(value.Time, board, board.WorkingTime); if (value.Time < bounds.Min) { return(null); } var openTime = bounds.Min; var candle = FirstInitCandle(message, new TimeFrameCandleMessage { TimeFrame = timeFrame, OpenTime = openTime, HighTime = openTime, LowTime = openTime, CloseTime = openTime, // реальное окончание свечи определяет по последней сделке }, value); return(candle); }
private void ProcessMarketDataMessage(MarketDataMessage msg) { if (msg.IsSubscribe) { if (msg.IsBack) { if (_seriesInfosByTransactions.ContainsKey(msg.TransactionId)) { base.SendInMessage(msg); return; } } var info = new SeriesInfo { MarketDataMessage = (MarketDataMessage)msg.Clone(), LastTime = msg.From, Board = !msg.SecurityId.BoardCode.IsEmpty() ? _exchangeInfoProvider.GetOrCreateBoard(msg.SecurityId.BoardCode) : ExchangeBoard.Test }; _seriesInfos .SafeAdd(msg.SecurityId) .Add(info); _seriesInfosByDates .Add(new KeyValuePair <DateTimeOffset, SeriesInfo>(msg.To ?? DateTimeOffset.MaxValue, info)); _series .SafeAdd(Tuple.Create(msg.SecurityId, msg.DataType, msg.Arg)) .Add(info); Subscribe(info, false); } else { var subscriptions = _seriesInfos.TryGetValue(msg.SecurityId); if (subscriptions == null) { return; } var removed = subscriptions.RemoveWhere(s => s.MarketDataMessage.TransactionId == msg.OriginalTransactionId); foreach (var info in removed) { UnSubscribe(info, false); } } }
private Security InitSecurity(SecurityId securityId, IExchangeInfoProvider exchangeInfoProvider) { var id = securityId.ToStringId(); var security = _entityRegistry.Securities.ReadById(id); if (security != null) { return(security); } security = new Security { Id = id, Code = securityId.SecurityCode, Board = exchangeInfoProvider.GetOrCreateBoard(securityId.BoardCode), Type = securityId.SecurityType, }; _entityRegistry.Securities.Save(security); this.AddInfoLog(LocalizedStrings.Str2871Params.Put(id)); return(security); }
/// <inheritdoc /> protected override void OnInnerAdapterNewOutMessage(Message message) { switch (message.Type) { case MessageTypes.Security: { var secMsg = (SecurityMessage)message; var security = _securityStorage.LookupById(secMsg.SecurityId); if (security == null) { security = secMsg.ToSecurity(_exchangeInfoProvider); } else { security.ApplyChanges(secMsg, _exchangeInfoProvider, OverrideSecurityData); } _securityStorage.Save(security, OverrideSecurityData); break; } case MessageTypes.Board: { var boardMsg = (BoardMessage)message; var board = _exchangeInfoProvider.GetExchangeBoard(boardMsg.Code); if (board == null) { board = _exchangeInfoProvider.GetOrCreateBoard(boardMsg.Code, code => { var exchange = _exchangeInfoProvider.GetExchange(boardMsg.ExchangeCode) ?? boardMsg.ToExchange(new Exchange { Name = boardMsg.ExchangeCode }); return(new ExchangeBoard { Code = code, Exchange = exchange }); }); } board.ApplyChanges(boardMsg); _exchangeInfoProvider.Save(board.Exchange); _exchangeInfoProvider.Save(board); break; } case MessageTypes.Portfolio: { var portfolioMsg = (PortfolioMessage)message; if (portfolioMsg.Error != null) { break; } var portfolio = _positionStorage.GetPortfolio(portfolioMsg.PortfolioName) ?? new Portfolio { Name = portfolioMsg.PortfolioName }; portfolioMsg.ToPortfolio(portfolio, _exchangeInfoProvider); _positionStorage.Save(portfolio); break; } case MessageTypes.PositionChange: { var positionMsg = (PositionChangeMessage)message; if (positionMsg.IsMoney()) { var portfolio = _positionStorage.GetPortfolio(positionMsg.PortfolioName) ?? new Portfolio { Name = positionMsg.PortfolioName }; portfolio.ApplyChanges(positionMsg, _exchangeInfoProvider); _positionStorage.Save(portfolio); } else { var position = GetPosition(positionMsg.SecurityId, positionMsg.PortfolioName); if (position == null) { break; } if (!positionMsg.DepoName.IsEmpty()) { position.DepoName = positionMsg.DepoName; } if (positionMsg.LimitType != null) { position.LimitType = positionMsg.LimitType; } if (!positionMsg.Description.IsEmpty()) { position.Description = positionMsg.Description; } position.ApplyChanges(positionMsg); _positionStorage.Save(position); } break; } } base.OnInnerAdapterNewOutMessage(message); }
public AllSecurityMarketDataStorage(Security security, object arg, Func <T, DateTimeOffset> getTime, Func <T, Security> getSecurity, Func <Security, IMarketDataDrive, IMarketDataStorage <T> > getStorage, IMarketDataStorageDrive drive, IExchangeInfoProvider exchangeInfoProvider) { if (security == null) { throw new ArgumentNullException(nameof(security)); } if (getTime == null) { throw new ArgumentNullException(nameof(getTime)); } if (getSecurity == null) { throw new ArgumentNullException(nameof(getSecurity)); } if (getStorage == null) { throw new ArgumentNullException(nameof(getStorage)); } if (drive == null) { throw new ArgumentNullException(nameof(drive)); } if (exchangeInfoProvider == null) { throw new ArgumentNullException(nameof(exchangeInfoProvider)); } _security = security; _exchangeInfoProvider = exchangeInfoProvider; _getTime = getTime; _arg = arg; Drive = drive; _basket = new BasketMarketDataStorage <T>(); var id = security.Id.ToSecurityId(); var code = id.SecurityCode; var securities = InteropHelper .GetDirectories(Path.Combine(Drive.Drive.Path, code.Substring(0, 1)), code + "*") .Select(p => Path.GetFileName(p).FolderNameToSecurityId()) .Select(s => { var idInfo = s.ToSecurityId(); var clone = security.Clone(); clone.Id = s; clone.Board = _exchangeInfoProvider.GetOrCreateBoard(idInfo.BoardCode); return(clone); }); foreach (var sec in securities) { _basket.InnerStorages.Add(getStorage(sec, Drive.Drive)); } }
/// <summary> /// Synchronize securities with storage. /// </summary> /// <param name="drives">Storage drives.</param> /// <param name="securityStorage">Securities meta info storage.</param> /// <param name="exchangeInfoProvider">Exchanges and trading boards provider.</param> /// <param name="newSecurity">The handler through which a new instrument will be passed.</param> /// <param name="updateProgress">The handler through which a progress change will be passed.</param> /// <param name="logsReceiver">Logs receiver.</param> /// <param name="isCancelled">The handler which returns an attribute of search cancel.</param> public static void SynchronizeSecurities(this IEnumerable <IMarketDataDrive> drives, ISecurityStorage securityStorage, IExchangeInfoProvider exchangeInfoProvider, Action <Security> newSecurity, Action <int, int> updateProgress, Func <bool> isCancelled, ILogReceiver logsReceiver) { if (drives == null) { throw new ArgumentNullException(nameof(drives)); } if (securityStorage == null) { throw new ArgumentNullException(nameof(securityStorage)); } if (exchangeInfoProvider == null) { throw new ArgumentNullException(nameof(exchangeInfoProvider)); } if (newSecurity == null) { throw new ArgumentNullException(nameof(newSecurity)); } if (updateProgress == null) { throw new ArgumentNullException(nameof(updateProgress)); } if (isCancelled == null) { throw new ArgumentNullException(nameof(isCancelled)); } if (logsReceiver == null) { throw new ArgumentNullException(nameof(logsReceiver)); } var securityPaths = new List <string>(); var progress = 0; foreach (var dir in drives.Select(drive => drive.Path).Distinct()) { foreach (var letterDir in InteropHelper.GetDirectories(dir)) { if (isCancelled()) { break; } var name = Path.GetFileName(letterDir); if (name == null || name.Length != 1) { continue; } securityPaths.AddRange(InteropHelper.GetDirectories(letterDir)); } if (isCancelled()) { break; } } if (isCancelled()) { return; } // кол-во проходов по директории для создания инструмента var iterCount = securityPaths.Count; updateProgress(0, iterCount); var securities = securityStorage.LookupAll().ToDictionary(s => s.Id, s => s, StringComparer.InvariantCultureIgnoreCase); foreach (var securityPath in securityPaths) { if (isCancelled()) { break; } var securityId = Path.GetFileName(securityPath).FolderNameToSecurityId(); var isNew = false; var security = securities.TryGetValue(securityId); 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 id = securityId.ToSecurityId(); 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 = id.SecurityCode, Code = id.SecurityCode, Board = exchangeInfoProvider.GetOrCreateBoard(id.BoardCode), }; securities.Add(securityId, security); securityStorage.Save(security, false); newSecurity(security); isNew = true; } } updateProgress(progress++, iterCount); if (isNew) { logsReceiver.AddInfoLog(LocalizedStrings.Str2930Params, security); } } }
/// <summary> /// To copy fields of the current instrument to <paramref name="security" />. /// </summary> /// <param name="security">Security.</param> /// <param name="exchangeInfoProvider">Exchanges and trading boards provider.</param> public void FillTo(Security security, IExchangeInfoProvider exchangeInfoProvider) { if (security == null) { throw new ArgumentNullException(nameof(security)); } if (exchangeInfoProvider == null) { throw new ArgumentNullException(nameof(exchangeInfoProvider)); } if (security.ShortName.IsEmpty()) { security.ShortName = ShortName; } security.Name = Name; security.Code = Code; var board = Board; if (board.CompareIgnoreCase("RFUD")) { board = "FORTS"; } security.Board = exchangeInfoProvider.GetOrCreateBoard(board); if (security.Multiplier == null) { security.Multiplier = Multiplier; } if (security.Decimals != null) { security.Decimals = Decimals; } if (security.PriceStep == null) { security.PriceStep = PriceStep; if (security.Decimals == null && PriceStep != null) { security.Decimals = PriceStep.Value.GetCachedDecimals(); } } if (security.Currency == null) { security.Currency = Currency.FromMicexCurrencyName(); } if (security.ExternalId.Isin.IsEmpty()) { var externalId = security.ExternalId; externalId.Isin = Isin; security.ExternalId = externalId; } if (IssueDate != null) { security.IssueDate = IssueDate.Value.ApplyTimeZone(TimeHelper.Moscow); } if (IssueSize != null) { security.IssueSize = IssueSize; } if (LastDate != null) { security.ExpiryDate = LastDate.Value.ApplyTimeZone(TimeHelper.Moscow); } if (!Asset.IsEmpty()) { security.UnderlyingSecurityId = Asset + "@" + security.Board.Code; } var secType = GetSecurityType(); if (secType != null) { security.Type = secType; } }
public static Transaction CreateRegisterTransaction(this OrderRegisterMessage message, IExchangeInfoProvider exchangeInfoProvider, /*string orderAccount,*/ IDictionary <string, RefPair <SecurityTypes, string> > securityClassInfo, bool singleSlash) { if (securityClassInfo == null) { throw new ArgumentNullException(nameof(securityClassInfo)); } if (message == null) { throw new ArgumentNullException(nameof(message)); } var boardCode = message.SecurityId.BoardCode; if (boardCode?.EndsWith("emu", StringComparison.InvariantCultureIgnoreCase) == true) { boardCode = boardCode.Substring(0, boardCode.Length - 3); } var board = exchangeInfoProvider.GetOrCreateBoard(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(message.PortfolioName) .SetSecurity(message, securityClassInfo) .SetVolume((int)message.Volume); //20-ти символьное составное поле, может содержать код клиента и текстовый комментарий с тем же разделителем, что и при вводе заявки вручную. //для ртс код клиента не обязателен var clientCode = needDepoAccount ? message.ClientCode : string.Empty; if (!message.Comment.IsEmpty()) { // http://www.quik.ru/forum/import/24383 //var splitter = message.PortfolioName.Contains("/") ? "//" : "/"; // https://forum.quik.ru/forum10/topic1218/ var splitter = singleSlash ? "/" : "//"; 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); } if (!message.BrokerCode.IsEmpty()) { transaction.SetFirmId(message.BrokerCode); } 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.Value) .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((SecurityId)otherSec, securityClassInfo); 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); }