private void ProcessSecurityLookupMessage(SecurityLookupMessage message) { var instruments = _restClient.GetInstruments(GetAccountId(), message.SecurityId.IsDefault() ? ArrayHelper.Empty <string>() : new[] { message.SecurityId.ToOanda() }); foreach (var instrument in instruments) { var secId = instrument.Code.ToSecurityId(); SendOutMessage(new SecurityMessage { OriginalTransactionId = message.TransactionId, SecurityId = secId, SecurityType = SecurityTypes.Currency, Name = instrument.DisplayName, PriceStep = 0.000001m }); if (instrument.Halted) { SendOutMessage(new Level1ChangeMessage { ServerTime = CurrentTime.Convert(TimeZoneInfo.Utc), SecurityId = secId, }.Add(Level1Fields.State, SecurityStates.Stoped)); } } SendOutMessage(new SecurityLookupResultMessage { OriginalTransactionId = message.TransactionId }); }
private void OnPositionsResponse(PositionsResponse response) { foreach (var pos in response.MoneyPositions.GroupBy(p => p.Client)) { SendOutMessage( this.CreatePortfolioChangeMessage(pos.Key) .Add(PositionChangeTypes.BeginValue, pos.Sum(p => p.SaldoIn)) .Add(PositionChangeTypes.CurrentValue, pos.Sum(p => p.Saldo)) .Add(PositionChangeTypes.Commission, pos.Sum(p => p.Commission))); } foreach (var pos in response.SecPositions) { SendOutMessage( new PositionChangeMessage { PortfolioName = pos.Client, SecurityId = new SecurityId { Native = pos.SecId }, DepoName = pos.Register, ServerTime = CurrentTime.Convert(TimeHelper.Moscow), } .Add(PositionChangeTypes.BeginValue, pos.SaldoIn) .Add(PositionChangeTypes.CurrentValue, pos.Saldo) .Add(PositionChangeTypes.BlockedValue, pos.SaldoMin)); } foreach (var fortsMoney in response.FortsMoneys) { SendOutMessage( this .CreatePortfolioChangeMessage(fortsMoney.Client) .Add(PositionChangeTypes.BeginValue, fortsMoney.Free) .Add(PositionChangeTypes.CurrentValue, fortsMoney.Current) .Add(PositionChangeTypes.BlockedValue, fortsMoney.Blocked) .Add(PositionChangeTypes.VariationMargin, fortsMoney.VarMargin)); } foreach (var pos in response.FortsPositions) { SendOutMessage(this .CreatePositionChangeMessage(pos.Client, new SecurityId { Native = pos.SecId }) .Add(PositionChangeTypes.BeginValue, (decimal)pos.StartNet) .Add(PositionChangeTypes.CurrentValue, (decimal)pos.TotalNet) .Add(PositionChangeTypes.VariationMargin, pos.VarMargin)); } //foreach (var fortsCollaterals in response.FortsCollateralses) //{ //} //foreach (var spotLimit in response.SpotLimits) //{ //} }
private void OnSessionOrderBookStatusChanged(OrderBookStatusEvent orderBookStatusEvent) { SecurityStates state; switch (orderBookStatusEvent.Status) { case OrderBookStatus.New: case OrderBookStatus.Opened: state = SecurityStates.Trading; break; case OrderBookStatus.Suspended: case OrderBookStatus.Closed: case OrderBookStatus.Settled: case OrderBookStatus.Withdrawn: state = SecurityStates.Stoped; break; default: throw new ArgumentOutOfRangeException(); } SendOutMessage( new Level1ChangeMessage { SecurityId = new SecurityId { Native = orderBookStatusEvent.InstrumentId }, ServerTime = CurrentTime.Convert(TimeZoneInfo.Utc), } .Add(Level1Fields.State, state)); }
private void OnSecuritiesResponse(SecuritiesResponse response) { foreach (var security in response.Securities) { var securityId = new SecurityId { Native = security.SecId, SecurityCode = security.SecCode, BoardCode = security.Board.FixBoardName(), }; SendOutMessage(new SecurityMessage { Name = security.ShortName, SecurityId = securityId, Multiplier = security.LotSize, PriceStep = security.MinStep, Decimals = security.Decimals, ShortName = security.ShortName, SecurityType = security.Type.FromTransaq(), }); SendOutMessage( new Level1ChangeMessage { SecurityId = securityId, ServerTime = CurrentTime.Convert(TimeHelper.Moscow), } .Add(Level1Fields.State, security.Active ? SecurityStates.Trading : SecurityStates.Stoped) .TryAdd(Level1Fields.StepPrice, security.PointCost)); } }
private void OnSessionOrderExecuted(Execution execution) { var transactionId = TryParseTransactionId(execution.Order.InstructionId); if (transactionId == null) { return; } SendOutMessage(new ExecutionMessage { SecurityId = new SecurityId { Native = execution.Order.InstrumentId }, OriginalTransactionId = transactionId.Value, TradeId = execution.ExecutionId, TradePrice = execution.Price, TradeVolume = execution.Quantity.Abs(), ExecutionType = ExecutionTypes.Transaction, Side = execution.Order.Quantity > 0 ? Sides.Buy : Sides.Sell, Commission = execution.Order.Commission, ServerTime = CurrentTime.Convert(TimeZoneInfo.Utc), HasTradeInfo = true, }); }
private void OnQuotationsResponse(QuotationsResponse response) { foreach (var quote in response.Quotations) { var message = new Level1ChangeMessage { SecurityId = new SecurityId { Native = quote.SecId }, ServerTime = CurrentTime.Convert(TimeHelper.Moscow), }; message.TryAdd(Level1Fields.AccruedCouponIncome, quote.AccruedIntValue); message.TryAdd(Level1Fields.OpenPrice, quote.Open); message.TryAdd(Level1Fields.HighPrice, quote.High); message.TryAdd(Level1Fields.LowPrice, quote.Low); message.TryAdd(Level1Fields.ClosePrice, quote.ClosePrice); message.TryAdd(Level1Fields.BidsCount, quote.BidsCount); message.TryAdd(Level1Fields.BidsVolume, (decimal?)quote.BidsVolume); message.TryAdd(Level1Fields.AsksCount, quote.AsksCount); message.TryAdd(Level1Fields.AsksVolume, (decimal?)quote.AsksVolume); message.TryAdd(Level1Fields.HighBidPrice, quote.HighBid); message.TryAdd(Level1Fields.LowAskPrice, quote.LowAsk); message.TryAdd(Level1Fields.Yield, quote.Yield); message.TryAdd(Level1Fields.MarginBuy, quote.BuyDeposit); message.TryAdd(Level1Fields.MarginSell, quote.SellDeposit); message.TryAdd(Level1Fields.HistoricalVolatility, quote.Volatility); message.TryAdd(Level1Fields.TheorPrice, quote.TheoreticalPrice); message.TryAdd(Level1Fields.Change, quote.Change); message.TryAdd(Level1Fields.Volume, (decimal?)quote.VolToday); message.TryAdd(Level1Fields.StepPrice, quote.PointCost); message.TryAdd(Level1Fields.OpenInterest, (decimal?)quote.OpenInterest); message.TryAdd(Level1Fields.TradesCount, quote.TradesCount); if (quote.Status != null) { message.Add(Level1Fields.State, quote.Status.Value.FromTransaq()); } // Transaq передает только изменения (например, передать только цену сделки, если объем при этом не изменился) message.TryAdd(Level1Fields.LastTradePrice, quote.LastTradePrice); message.TryAdd(Level1Fields.LastTradeVolume, (decimal?)quote.LastTradeVolume); if (quote.LastTradeTime != null) { message.Add(Level1Fields.LastTradeTime, quote.LastTradeTime.Value.ToDto()); } message.TryAdd(Level1Fields.BestBidPrice, quote.BestBidPrice); message.TryAdd(Level1Fields.BestBidVolume, (decimal?)quote.BestBidVolume); message.TryAdd(Level1Fields.BestAskPrice, quote.BestAskPrice); message.TryAdd(Level1Fields.BestAskVolume, (decimal?)quote.BestAskVolume); SendOutMessage(message); } }
private void SessionOnUserMessage(OEC.API.User user, string message) { SendOutMessage(new Messages.NewsMessage { Source = user.Name, Headline = message, ServerTime = CurrentTime.Convert(TimeHelper.Est) }); }
private void SessionOnNewsMessage(string channel, string message) { SendOutMessage(new Messages.NewsMessage { BoardCode = channel, Headline = message, ServerTime = CurrentTime.Convert(TimeHelper.Est) }); }
private void OnNewsBodyResponse(NewsBodyResponse response) { SendOutMessage(new NewsMessage { Id = response.Id.To <string>(), Story = response.Text, ServerTime = CurrentTime.Convert(TimeHelper.Moscow) }); }
private void SessionOnNewOrderBook(OrderBook book) { SendOutMessage(new QuoteChangeMessage { SecurityId = _btcUsd, Bids = book.Bids.Select(b => b.ToStockSharp(Sides.Buy)), Asks = book.Asks.Select(b => b.ToStockSharp(Sides.Sell)), ServerTime = CurrentTime.Convert(TimeZoneInfo.Utc), }); }
private void OnNewsHeaderResponse(NewsHeaderResponse response) { SendOutMessage(new NewsMessage { Source = response.Source, Headline = response.Title, Id = response.Id.To <string>(), Story = response.Text, ServerTime = response.TimeStamp?.ToDto() ?? CurrentTime.Convert(TimeHelper.Moscow), }); }
private void SessionOnNewTrade(Trade trade) { SendOutMessage(new ExecutionMessage { ExecutionType = ExecutionTypes.Tick, SecurityId = _btcUsd, TradeId = trade.Id, TradePrice = (decimal)trade.Price, TradeVolume = (decimal)trade.Amount, ServerTime = CurrentTime.Convert(TimeZoneInfo.Utc), }); }
private void OnProcessQuotes(string where, string[] quotes) { // paper_no нужно парсить из условия where, так как в поле paper_no передается всегда 0 var paperNo = where.Split('=')[1].Trim().To <int>(); var f = Wrapper.FieldsDepth; var bids = new List <QuoteChange>(); var asks = new List <QuoteChange>(); foreach (var quoteStr in quotes) { var cols = quoteStr.ToColumns(); var sellQty = f.SellQty.GetValue(cols); var price = f.Price.GetValue(cols); var buyQty = f.BuyQty.GetValue(cols); if (sellQty == 0 && buyQty == 0) { // If the sellQty and buyQty are 0 - that is our limit order // which is not a part of the market depth. Just skip it. continue; } QuoteChange quote; if (sellQty == 0) { quote = new QuoteChange(Sides.Buy, price, buyQty); bids.Insert(0, quote); } else { quote = new QuoteChange(Sides.Sell, price, sellQty); asks.Add(quote); } } if (bids.Count > 0 || asks.Count > 0) { SendOutMessage(new QuoteChangeMessage { Bids = bids, Asks = asks, SecurityId = new SecurityId { Native = paperNo }, IsSorted = true, ServerTime = CurrentTime.Convert(TimeHelper.Moscow), }); } }
private void OnMessagesResponse(MessagesResponse response) { foreach (var message in response.Messages) { SendOutMessage(new NewsMessage { Source = message.From, Headline = message.Text, Story = message.Text, ServerTime = message.Date?.ToDto() ?? CurrentTime.Convert(TimeHelper.Moscow), }); } }
private void OnQuoteChanged(string smartId, int row, int rowCount, decimal?bidPrice, decimal?bidVolume, decimal?askPrice, decimal?askVolume) { //Debug.Write("Row = " + row + " Bid = " + bidPrice + " BidVolume = " + bidVolume + " Ask = " + askPrice + " AskVolume = " + askVolume); var secId = new SecurityId { Native = smartId }; var tempDepth = _tempDepths.SafeAdd(secId, key => Tuple.Create(new List <QuoteChange>(), new List <QuoteChange>())); var bestQuotes = _bestQuotes.SafeAdd(secId); try { if (bidPrice > 0) { tempDepth.Item1.Add(new QuoteChange(Sides.Buy, bidPrice.Value, bidVolume ?? 0)); if (row == 0) { bestQuotes.First = Tuple.Create(bidPrice.Value, bidVolume ?? 0); } } if (askPrice > 0) { tempDepth.Item2.Add(new QuoteChange(Sides.Sell, askPrice.Value, askVolume ?? 0)); if (row == 0) { bestQuotes.Second = Tuple.Create(askPrice.Value, askVolume ?? 0); } } } finally { if ((row + 1) == rowCount) { SendOutMessage(new QuoteChangeMessage { Bids = tempDepth.Item1.ToArray(), Asks = tempDepth.Item2.ToArray(), SecurityId = secId, ServerTime = CurrentTime.Convert(TimeHelper.Moscow), }); tempDepth.Item1.Clear(); tempDepth.Item2.Clear(); } } }
private void OnQuotesResponse(QuotesResponse response) { foreach (var group in response.Quotes.GroupBy(q => q.SecId)) { var tuple = _quotes.SafeAdd(group.Key, key => Tuple.Create(new Dictionary <decimal, decimal>(), new Dictionary <decimal, decimal>())); foreach (var quote in group) { if (quote.Price == 0) { continue; } if (quote.Buy != null) { if (quote.Buy == -1) { tuple.Item1.Remove(quote.Price); } else { tuple.Item1[quote.Price] = (decimal)quote.Buy; } } if (quote.Sell != null) { if (quote.Sell == -1) { tuple.Item2.Remove(quote.Price); } else { tuple.Item2[quote.Price] = (decimal)quote.Sell; } } } SendOutMessage(new QuoteChangeMessage { SecurityId = new SecurityId { Native = group.Key }, Bids = tuple.Item1.Select(p => new QuoteChange(Sides.Buy, p.Key, p.Value)).ToArray(), Asks = tuple.Item2.Select(p => new QuoteChange(Sides.Sell, p.Key, p.Value)).ToArray(), ServerTime = CurrentTime.Convert(TimeHelper.Moscow), }); } }
private void OnMessagesResponse(MessagesResponse response) { foreach (var message in response.Messages) { SendOutMessage(new NewsMessage { Source = message.From, Headline = message.Text, Story = message.Text, ServerTime = message.Date == null ? CurrentTime.Convert(TimeHelper.Moscow) : message.Date.Value.ApplyTimeZone(TimeHelper.Moscow), }); } }
private void OnSecInfoResponse(SecInfoResponse response) { var securityId = new SecurityId { Native = response.SecId, SecurityCode = response.SecCode, BoardCode = _boards[response.Market], }; SendOutMessage(new SecurityMessage { SecurityId = securityId, ExpiryDate = response.MatDate?.ApplyTimeZone(TimeHelper.Moscow), OptionType = response.PutCall?.FromTransaq(), }); var l1Msg = new Level1ChangeMessage { SecurityId = new SecurityId { Native = response.SecId }, ServerTime = CurrentTime.Convert(TimeHelper.Moscow), }; l1Msg.TryAdd(Level1Fields.MinPrice, response.MinPrice); l1Msg.TryAdd(Level1Fields.MaxPrice, response.MaxPrice); var marginBuy = response.BuyDeposit; if (marginBuy == null || marginBuy == 0m) { marginBuy = response.BgoBuy; } var marginSell = response.SellDeposit; if (marginSell == null || marginSell == 0m) { marginSell = response.BgoC; } l1Msg.TryAdd(Level1Fields.MarginBuy, marginBuy); l1Msg.TryAdd(Level1Fields.MarginSell, marginSell); SendOutMessage(l1Msg); }
private void ProcessOrderCancel(OrderCancelMessage cancelMsg) { if (cancelMsg.OrderId == null) { throw new InvalidOperationException(LocalizedStrings.Str2252Params.Put(cancelMsg.OrderTransactionId)); } var isOk = _httpClient.CancelOrder(cancelMsg.OrderId.Value); SendOutMessage(new ExecutionMessage { ServerTime = CurrentTime.Convert(TimeZoneInfo.Utc), ExecutionType = ExecutionTypes.Transaction, OriginalTransactionId = cancelMsg.TransactionId, OrderState = isOk ? OrderStates.Done : OrderStates.Failed, Error = isOk ? null : new InvalidOperationException(LocalizedStrings.Str3300), }); }
private IEnumerable <Message> ToSecurityFundamentalMessages(string value) { var parts = value.SplitByComma(); var pe = parts[2].To <decimal?>(); var beta = parts[26].To <decimal?>(); var precision = parts[39].To <int>(); var sic = parts[40].To <int?>(); var historicalVolatility = parts[41].To <decimal?>(); var securityType = parts[42].To <int>(); var listedMarket = parts[43].To <int>(); var maturityDate = parts[49].TryToDateTime("MM/dd/yyyy").ToEst(); var expirationDate = parts[51].TryToDateTime("MM/dd/yyyy").ToEst(); var strikePrice = parts[52].To <decimal?>(); var naics = parts[53].To <int?>(); var exchangeRoot = parts[54]; var secId = CreateSecurityId(parts[0], listedMarket); yield return(new SecurityMessage { SecurityId = secId, Decimals = precision, Strike = strikePrice ?? 0, ExpiryDate = expirationDate ?? maturityDate, SecurityType = _securityTypes[securityType], UnderlyingSecurityCode = exchangeRoot, ExtensionInfo = new Dictionary <object, object> { { "SIC", sic }, { "NAICS", naics }, } }); yield return(new Level1ChangeMessage { SecurityId = secId, ServerTime = CurrentTime.Convert(TimeHelper.Est) } .TryAdd(Level1Fields.HistoricalVolatility, historicalVolatility) .TryAdd(Level1Fields.Beta, beta) .TryAdd(Level1Fields.PriceEarnings, pe)); }
private void ProcessLevel1() { var currTime = CurrentTime; if ((currTime - _prevLevel1Time) < _level1Interval) { return; } _prevLevel1Time = currTime; var btcUsd = _httpClient.RequestBtcUsd(); if (btcUsd != null) { SendOutMessage(new Level1ChangeMessage { SecurityId = _btcUsd, ServerTime = btcUsd.Time.ApplyTimeZone(TimeZoneInfo.Utc) } .TryAdd(Level1Fields.HighBidPrice, (decimal)btcUsd.High) .TryAdd(Level1Fields.LowAskPrice, (decimal)btcUsd.Low) .TryAdd(Level1Fields.VWAP, (decimal)btcUsd.VWAP) .TryAdd(Level1Fields.LastTradePrice, (decimal)btcUsd.Last) .TryAdd(Level1Fields.Volume, (decimal)btcUsd.Volume) .TryAdd(Level1Fields.BestBidPrice, (decimal)btcUsd.Bid) .TryAdd(Level1Fields.BestAskPrice, (decimal)btcUsd.Ask)); } var eurUsd = _httpClient.RequestEurUsd(); if (eurUsd != null) { SendOutMessage(new Level1ChangeMessage { SecurityId = _eurUsd, ServerTime = CurrentTime.Convert(TimeZoneInfo.Utc), } .TryAdd(Level1Fields.BestBidPrice, (decimal)eurUsd.Buy) .TryAdd(Level1Fields.BestAskPrice, (decimal)eurUsd.Sell)); } }
private void OnSessionInstructionRejected(InstructionRejectedEvent evt) { var transactionId = TryParseTransactionId(evt.InstructionId); if (transactionId == null) { return; } SendOutMessage(new ExecutionMessage { ExecutionType = ExecutionTypes.Order, SecurityId = new SecurityId { Native = evt.InstrumentId }, OriginalTransactionId = transactionId.Value, OrderState = OrderStates.Failed, Error = new InvalidOperationException(evt.Reason), PortfolioName = evt.AccountId.To <string>(), ServerTime = CurrentTime.Convert(TimeZoneInfo.Utc) }); }
private void OnSecurityChanged(string smartId, Tuple <decimal?, decimal?, DateTime> lastTrade, decimal?open, decimal?high, decimal?low, decimal?close, decimal?volume, QuoteChange bid, QuoteChange ask, decimal?openInt, Tuple <decimal?, decimal?> goBuySell, Tuple <decimal?, decimal?> goBase, Tuple <decimal?, decimal?> limits, int tradingStatus, Tuple <decimal?, decimal?> volatTheorPrice) { var secId = new SecurityId { Native = smartId }; var message = new Level1ChangeMessage { SecurityId = secId, ExtensionInfo = new Dictionary <object, object> { { SmartComExtensionInfoHelper.SecurityOptionsMargin, goBase.Item1 }, { SmartComExtensionInfoHelper.SecurityOptionsSyntheticMargin, goBase.Item2 } }, ServerTime = CurrentTime.Convert(TimeHelper.Moscow), }; message.TryAdd(Level1Fields.LastTradePrice, lastTrade.Item1); message.TryAdd(Level1Fields.LastTradeVolume, lastTrade.Item2); message.Add(Level1Fields.LastTradeTime, lastTrade.Item3.ApplyTimeZone(TimeHelper.Moscow)); var prevQuotes = _bestQuotes.TryGetValue(secId); if (bid.Price != 0) { message.Add(Level1Fields.BestBidPrice, bid.Price); if (prevQuotes != null && prevQuotes.First != null && prevQuotes.First.Item1 == bid.Price) { message.Add(Level1Fields.BestBidVolume, prevQuotes.First.Item2); } } if (ask.Price != 0) { message.Add(Level1Fields.BestAskPrice, ask.Price); if (prevQuotes != null && prevQuotes.Second != null && prevQuotes.Second.Item1 == ask.Price) { message.Add(Level1Fields.BestAskVolume, prevQuotes.Second.Item2); } } message.TryAdd(Level1Fields.BidsVolume, bid.Volume); message.TryAdd(Level1Fields.AsksVolume, ask.Volume); message.TryAdd(Level1Fields.OpenPrice, open); message.TryAdd(Level1Fields.LowPrice, low); message.TryAdd(Level1Fields.HighPrice, high); message.TryAdd(Level1Fields.ClosePrice, close); message.TryAdd(Level1Fields.MinPrice, limits.Item1); message.TryAdd(Level1Fields.MaxPrice, limits.Item2); message.TryAdd(Level1Fields.MarginBuy, goBuySell.Item1); message.TryAdd(Level1Fields.MarginSell, goBuySell.Item2); message.TryAdd(Level1Fields.OpenInterest, openInt); message.TryAdd(Level1Fields.ImpliedVolatility, volatTheorPrice.Item1); message.TryAdd(Level1Fields.TheorPrice, volatTheorPrice.Item2); message.TryAdd(Level1Fields.Volume, volume); message.Add(Level1Fields.State, tradingStatus == 0 ? SecurityStates.Trading : SecurityStates.Stoped); SendOutMessage(message); }
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; }
private void OnSessionOrderChanged(LmaxOrder lmaxOrder) { var transactionId = TryParseTransactionId(lmaxOrder.InstructionId); if (transactionId == null) { return; } LmaxOrderCondition condition = null; decimal price = 0; OrderTypes orderType; switch (lmaxOrder.OrderType) { case OrderType.MARKET: orderType = OrderTypes.Market; break; case OrderType.LIMIT: orderType = OrderTypes.Limit; if (lmaxOrder.LimitPrice == null) { throw new ArgumentException(LocalizedStrings.Str3394Params.Put(transactionId), nameof(lmaxOrder)); } price = (decimal)lmaxOrder.LimitPrice; break; case OrderType.STOP_ORDER: case OrderType.STOP_LOSS_MARKET_ORDER: case OrderType.STOP_PROFIT_LIMIT_ORDER: orderType = OrderTypes.Conditional; if (lmaxOrder.StopPrice == null) { throw new ArgumentException(LocalizedStrings.Str3395Params.Put(transactionId), nameof(lmaxOrder)); } price = (decimal)lmaxOrder.StopPrice; condition = new LmaxOrderCondition { StopLossOffset = lmaxOrder.StopLossOffset, TakeProfitOffset = lmaxOrder.StopProfitOffset, }; break; case OrderType.CLOSE_OUT_ORDER_POSITION: case OrderType.CLOSE_OUT_POSITION: case OrderType.SETTLEMENT_ORDER: case OrderType.OFF_ORDERBOOK: case OrderType.REVERSAL: case OrderType.UNKNOWN: orderType = OrderTypes.Execute; break; default: throw new ArgumentOutOfRangeException(); } DateTimeOffset?expiryDate = null; var tif = StockSharpTimeInForce.PutInQueue; switch (lmaxOrder.TimeInForce) { case LmaxTimeInForce.FillOrKill: tif = StockSharpTimeInForce.MatchOrCancel; break; case LmaxTimeInForce.ImmediateOrCancel: tif = StockSharpTimeInForce.CancelBalance; break; case LmaxTimeInForce.GoodForDay: expiryDate = DateTime.Today.ApplyTimeZone(TimeZoneInfo.Utc); break; case LmaxTimeInForce.GoodTilCancelled: break; case LmaxTimeInForce.Unknown: throw new NotSupportedException(LocalizedStrings.Str3396Params.Put(lmaxOrder.TimeInForce, transactionId.Value, lmaxOrder.OrderId)); default: throw new InvalidOperationException(LocalizedStrings.Str3397Params.Put(lmaxOrder.TimeInForce, transactionId.Value, lmaxOrder.OrderId)); } var msg = new ExecutionMessage { SecurityId = new SecurityId { Native = lmaxOrder.InstrumentId }, OriginalTransactionId = transactionId.Value, OrderType = orderType, OrderPrice = price, Condition = condition, OrderVolume = lmaxOrder.Quantity.Abs(), Side = lmaxOrder.Quantity > 0 ? Sides.Buy : Sides.Sell, Balance = lmaxOrder.Quantity - lmaxOrder.FilledQuantity, PortfolioName = lmaxOrder.AccountId.To <string>(), TimeInForce = tif, ExpiryDate = expiryDate, OrderStringId = lmaxOrder.OrderId, ExecutionType = ExecutionTypes.Transaction, Commission = lmaxOrder.Commission, ServerTime = CurrentTime.Convert(TimeZoneInfo.Utc), HasOrderInfo = true, }; msg.OrderState = lmaxOrder.CancelledQuantity > 0 ? OrderStates.Done : (msg.Balance == 0 ? OrderStates.Done : OrderStates.Active); //msg.Action = lmaxOrder.CancelledQuantity > 0 // ? ExecutionActions.Canceled // : (lmaxOrder.FilledQuantity == 0 ? ExecutionActions.Registered : ExecutionActions.Matched); SendOutMessage(msg); }
private void SearchSecurities(string secCode, long transactionId, ICollection <Instrument> instruments, bool hasMoreResults) { if (secCode.IsEmpty()) { throw new ArgumentNullException(nameof(secCode), LocalizedStrings.Str3391); } if (instruments == null) { throw new ArgumentNullException(nameof(instruments)); } foreach (var instrument in instruments) { SecurityTypes type; var typeName = instrument.Underlying.AssetClass.ToUpperInvariant(); switch (typeName) { case "COMMODITY": type = SecurityTypes.Commodity; break; case "CURRENCY": type = SecurityTypes.Currency; break; case "INDEX": type = SecurityTypes.Index; break; default: SendOutError(LocalizedStrings.Str2140Params.Put(typeName)); continue; } var securityId = new SecurityId { SecurityCode = instrument.Underlying.Symbol, BoardCode = ExchangeBoard.Lmax.Code, Native = instrument.Id }; SendOutMessage(new SecurityMessage { SecurityId = securityId, Name = instrument.Name, PriceStep = instrument.OrderBook.PriceIncrement, VolumeStep = instrument.OrderBook.QuantityIncrement, Multiplier = instrument.Contract.ContractSize, Currency = instrument.Contract.Currency.To <CurrencyTypes>(), ExpiryDate = instrument.Calendar.ExpiryTime == null ? (DateTimeOffset?)null : instrument.Calendar.ExpiryTime.Value.ApplyTimeZone(TimeZoneInfo.Utc), SecurityType = type, OriginalTransactionId = transactionId, }); SendOutMessage( new Level1ChangeMessage { SecurityId = securityId, ServerTime = CurrentTime.Convert(TimeZoneInfo.Utc), } .TryAdd(Level1Fields.StepPrice, instrument.Contract.UnitPrice)); } if (hasMoreResults) { _session.SearchInstruments(new SearchRequest(secCode, instruments.Count), (i, h) => SearchSecurities(secCode, transactionId, i, h), CreateErrorHandler("SearchInstruments")); } else { SendOutMessage(new SecurityLookupResultMessage { OriginalTransactionId = transactionId }); } }
private IEnumerable <Message> ToSecurityUpdateMessage(string value) { var parts = value.SplitByComma(); var index = 0; var secCode = parts[index++]; var exchangeId = int.Parse(parts[index++], NumberStyles.HexNumber); var tradeBoard = parts[index++].To <int?>(); var bidBoard = parts[index++].To <int?>(); var askBoard = parts[index++].To <int?>(); var l1Messages = new[] { exchangeId, tradeBoard, bidBoard, askBoard } .Where(id => id != null) .Select(id => id.Value) .Distinct() .ToDictionary(boardId => boardId, boardId => new Level1ChangeMessage { SecurityId = CreateSecurityId(secCode, boardId) }); DateTime?lastTradeDate = null; TimeSpan?lastTradeTime = null; decimal? lastTradePrice = null; decimal? lastTradeVolume = null; long? lastTradeId = null; var types = new HashSet <Level1Fields>(Enumerator.GetValues <Level1Fields>()); var messageContentsIndex = Level1Columns.IndexOf(Level1ColumnRegistry.MessageContents); if (messageContentsIndex != -1) { types.Exclude(parts[messageContentsIndex + index]); } if (tradeBoard == null) { types.Remove(Level1Fields.LastTradeId); types.Remove(Level1Fields.LastTradeTime); types.Remove(Level1Fields.LastTradePrice); types.Remove(Level1Fields.LastTradeVolume); } if (bidBoard == null) { types.Remove(Level1Fields.BestBidTime); types.Remove(Level1Fields.BestBidPrice); types.Remove(Level1Fields.BestBidVolume); } if (askBoard == null) { types.Remove(Level1Fields.BestAskTime); types.Remove(Level1Fields.BestAskPrice); types.Remove(Level1Fields.BestAskVolume); } foreach (var column in Level1Columns) { var colValue = parts[index++]; if (colValue.IsEmpty()) { continue; } //colValue = colValue.To(column.Type); switch (column.Field) { case IQFeedLevel1Column.DefaultField: { var typedColValue = column.Convert(colValue); if (typedColValue != null) { l1Messages[exchangeId].AddValue(column.Name, typedColValue); } break; } case Level1Fields.LastTradeId: if (types.Contains(column.Field)) { lastTradeId = colValue.To <long?>(); if (lastTradeId != null && lastTradeId != 0) { l1Messages[tradeBoard.Value].Add(column.Field, lastTradeId.Value); } } break; case Level1Fields.LastTradeTime: if (types.Contains(column.Field)) { if (column == Level1ColumnRegistry.LastDate) { lastTradeDate = colValue.TryToDateTime(column.Format); } else if (column == Level1ColumnRegistry.LastTradeTime) { lastTradeTime = column.ConvertToTimeSpan(colValue); } if (lastTradeDate.HasValue && lastTradeTime.HasValue) { var l1Msg = l1Messages[tradeBoard.Value]; l1Msg.ServerTime = (lastTradeDate.Value + lastTradeTime.Value).ApplyTimeZone(TimeHelper.Est); l1Msg.Add(Level1Fields.LastTradeTime, l1Msg.ServerTime); } } break; case Level1Fields.LastTradePrice: case Level1Fields.LastTradeVolume: if (types.Contains(column.Field)) { var decValue = colValue.To <decimal?>(); l1Messages[tradeBoard.Value].TryAdd(column.Field, decValue); if (column == Level1ColumnRegistry.LastTradePrice) { lastTradePrice = decValue; } else // if (column == SessionHolder.Level1ColumnRegistry.LastTradeVolume) { lastTradeVolume = decValue; } } break; case Level1Fields.BestBidTime: if (types.Contains(column.Field)) { var typedColValue = column.ConvertToTimeSpan(colValue); if (typedColValue != null) { var l1Msg = l1Messages[bidBoard.Value]; l1Msg.ServerTime = (DateTime.Today + typedColValue.Value).ApplyTimeZone(TimeHelper.Est); l1Msg.Add(Level1Fields.BestBidTime, l1Msg.ServerTime); } } break; case Level1Fields.BestBidPrice: case Level1Fields.BestBidVolume: if (types.Contains(column.Field)) { l1Messages[bidBoard.Value].TryAdd(column.Field, colValue.To <decimal?>()); } break; case Level1Fields.BestAskTime: if (types.Contains(column.Field)) { var typedColValue = column.ConvertToTimeSpan(colValue); if (typedColValue != null) { var l1Msg = l1Messages[askBoard.Value]; l1Msg.ServerTime = (DateTime.Today + typedColValue.Value).ApplyTimeZone(TimeHelper.Est); l1Msg.Add(Level1Fields.BestAskTime, l1Msg.ServerTime); } } break; case Level1Fields.BestAskPrice: case Level1Fields.BestAskVolume: if (types.Contains(column.Field)) { l1Messages[askBoard.Value].TryAdd(column.Field, colValue.To <decimal?>()); } break; case Level1Fields.OpenInterest: case Level1Fields.OpenPrice: case Level1Fields.HighPrice: case Level1Fields.LowPrice: case Level1Fields.ClosePrice: case Level1Fields.SettlementPrice: case Level1Fields.VWAP: if (types.Contains(column.Field)) { l1Messages[exchangeId].TryAdd(column.Field, colValue.To <decimal?>()); } break; default: if (types.Contains(column.Field)) { var typedColValue = column.Convert(colValue); if (typedColValue != null) { l1Messages[exchangeId].Add(column.Field, typedColValue); } } break; } } foreach (var l1Msg in l1Messages.Values) { if (l1Msg.Changes.Count <= 0) { continue; } yield return(new SecurityMessage { SecurityId = l1Msg.SecurityId }); if (l1Msg.ServerTime.IsDefault()) { l1Msg.ServerTime = CurrentTime.Convert(TimeHelper.Est); } yield return(l1Msg); } if (!types.Contains(Level1Fields.LastTrade) || !lastTradeDate.HasValue || !lastTradeTime.HasValue || !lastTradeId.HasValue || !lastTradePrice.HasValue || !lastTradeVolume.HasValue) { yield break; } yield return(new ExecutionMessage { SecurityId = l1Messages[tradeBoard.Value].SecurityId, TradeId = lastTradeId.Value, ServerTime = (lastTradeDate.Value + lastTradeTime.Value).ApplyTimeZone(TimeHelper.Est), TradePrice = lastTradePrice.Value, Volume = lastTradeVolume.Value, ExecutionType = ExecutionTypes.Tick, }); }
private void ProcessSubscriptions() { if (_subscribedLevel1.Count > 0) { var tickerReply = _client.GetTickers(_subscribedLevel1.Cache.Select(id => id.SecurityCode.ToBtceCode())); foreach (var ticker in tickerReply.Items.Values) { var l1Msg = new Level1ChangeMessage { SecurityId = new SecurityId { SecurityCode = ticker.Instrument.ToStockSharpCode(), BoardCode = _boardCode, }, ServerTime = ticker.Timestamp.ApplyTimeZone(TimeHelper.Moscow) } .TryAdd(Level1Fields.Volume, (decimal)ticker.Volume) .TryAdd(Level1Fields.HighPrice, (decimal)ticker.HighPrice) .TryAdd(Level1Fields.LowPrice, (decimal)ticker.LowPrice) .TryAdd(Level1Fields.LastTradePrice, (decimal)ticker.LastPrice) // BTCE транслирует потенциальные цену для покупки и продажи .TryAdd(Level1Fields.BestBidPrice, (decimal)ticker.Ask) .TryAdd(Level1Fields.BestAskPrice, (decimal)ticker.Bid) .TryAdd(Level1Fields.AveragePrice, (decimal)ticker.AveragePrice); if (l1Msg.Changes.Count > 0) { SendOutMessage(l1Msg); } } } if (_subscribedDepths.Count > 0) { foreach (var group in _subscribedDepths.CachedPairs.GroupBy(p => p.Value)) { var depthReply = _client.GetDepths(group.Key, group.Select(p => p.Key).Select(id => id.SecurityCode.ToBtceCode())); foreach (var pair in depthReply.Items) { SendOutMessage(new QuoteChangeMessage { SecurityId = new SecurityId { SecurityCode = pair.Key.ToStockSharpCode(), BoardCode = _boardCode, }, Bids = pair.Value.Bids.Select(vp => vp.ToStockSharp(Sides.Buy)).ToArray(), Asks = pair.Value.Asks.Select(vp => vp.ToStockSharp(Sides.Sell)).ToArray(), ServerTime = CurrentTime.Convert(TimeHelper.Moscow), }); } } } if (_subscribedTicks.Count > 0) { var tradeReply = _client.GetTrades(_tickCount, _subscribedTicks.Cache.Select(id => id.SecurityCode.ToBtceCode())); // меняем на глубину 50 _tickCount = 50; foreach (var pair in tradeReply.Items) { foreach (var trade in pair.Value.OrderBy(t => t.Id)) { if (_lastTickId >= trade.Id) { continue; } _lastTickId = trade.Id; SendOutMessage(new ExecutionMessage { SecurityId = new SecurityId { SecurityCode = pair.Key.ToStockSharpCode(), BoardCode = _boardCode, }, ExecutionType = ExecutionTypes.Tick, TradePrice = (decimal)trade.Price, Volume = (decimal)trade.Volume, TradeId = trade.Id, ServerTime = trade.Timestamp.ApplyTimeZone(TimeHelper.Moscow), OriginSide = trade.Side.ToStockSharp() }); } } } }
private IEnumerable <Message> ParseMessages(IQFeedWrapper feed, string str, MessageTypes type, long requestId) { switch (type) { case ExtendedMessageTypes.System: yield return(new IQFeedSystemMessage(feed, str)); break; case ExtendedMessageTypes.SecurityType: { var parts = str.SplitByComma(); yield return(new IQFeedSecurityTypeMessage(parts[0].To <int>(), parts[1], parts[2])); break; } case ExtendedMessageTypes.ListedMarket: { var parts = str.SplitByComma(); yield return(new IQFeedListedMarketMessage(parts[0].To <int>(), parts[1], parts[2])); break; } case ExtendedMessageTypes.Data: yield return(new IQFeedDataMessage(str)); break; case ExtendedMessageTypes.End: yield return(new IQFeedEndMessage()); break; case MessageTypes.Time: yield return(new TimeMessage { ServerTime = str.ToDateTime("yyyyMMdd HH:mm:ss").ApplyTimeZone(TimeHelper.Est) }); break; case MessageTypes.Security: { var parts = str.SplitByComma(); yield return(new SecurityMessage { SecurityId = CreateSecurityId(parts[0], parts[1].To <int>()), Name = parts[3], OriginalTransactionId = requestId, SecurityType = _securityTypes[parts[2].To <int>()], }); break; } case ExtendedMessageTypes.Fundamental: { foreach (var result in ToSecurityFundamentalMessages(str)) { yield return(result); } break; } case MessageTypes.Level1Change: { foreach (var result in ToSecurityUpdateMessage(str)) { yield return(result); } break; } case MessageTypes.Execution: { yield return(ToLevel1(str, _secIds[requestId])); break; } case MessageTypes.News: yield return(ToNewsMessage(str)); break; case ExtendedMessageTypes.NewsStory: { yield return(new NewsMessage { Id = _newsIds[requestId], Story = str.StripBrackets("<BEGIN>", "<END>"), ServerTime = CurrentTime.Convert(TimeHelper.Est) }); break; } case MessageTypes.CandleTimeFrame: case MessageTypes.CandleTick: case MessageTypes.CandleVolume: case ExtendedMessageTypes.HistoryExtraDayCandle: { var parts = str.SplitByComma(); var tuple = _candleParsers[requestId]; var candleMsg = tuple.Item1(parts); candleMsg.OriginalTransactionId = requestId; candleMsg.SecurityId = _secIds[requestId]; if (tuple.Item2 is TimeSpan) { var tf = (TimeSpan)tuple.Item2; if (tf == TimeSpan.FromDays(1)) { candleMsg.OpenTime = candleMsg.CloseTime; candleMsg.CloseTime = candleMsg.OpenTime.EndOfDay(); } else // if (tf == TimeSpan.FromDays(7) || tf.Ticks == TimeHelper.TicksPerMonth) { candleMsg.CloseTime -= TimeSpan.FromTicks(1); candleMsg.OpenTime = tf.GetCandleBounds(candleMsg.CloseTime.ToLocalTime(TimeHelper.Est)).Min; } } else { candleMsg.OpenTime = candleMsg.CloseTime; } yield return(candleMsg); break; } case MessageTypes.QuoteChange: { var l1Msg = ToLevel2(str); if (l1Msg != null) { yield return(l1Msg); } break; } case MessageTypes.Error: yield return(new ErrorMessage { Error = new InvalidOperationException(str) }); break; default: throw new InvalidOperationException(LocalizedStrings.Str2142Params.Put(type)); } }