public InstrumentModel GetInstrument(string epic) { var market = Instruments.FirstOrDefault(m => m.Epic == epic); if (market == null) { var detail = GetMarketDetails(epic); market = new InstrumentModel(); market.DealingRuleData = detail.dealingRules; market.InstrumentData = detail.instrument; market.SnapshotData = detail.snapshot; market.Epic = epic; market.InstrumentName = market.InstrumentData.name; market.Offer = market.SnapshotData.offer; market.Bid = market.SnapshotData.bid; market.High = market.SnapshotData.high; market.Low = market.SnapshotData.low; Instruments.Add(market); SubscribeL1WatchlistPrices(); } return(market); }
private void Client_ExecutionsError(object sender, InstrumentIdErrorEventArgs e) { var i = Instruments.FirstOrDefault(m => m.Id == e.InstrumentId); if (i != null) { i.LastError = (e.Exception.GetBaseException() ?? e.Exception).Message; } }
private void StartLoad() { try { IsConnected = _bitmexApiSocketService.Connect(); } catch (Exception e) { MessageBox.Show(e.Message); } if (IsConnected) { _bitmexApiSocketService.Subscribe(BitmexApiSubscriptionInfo <IEnumerable <InstrumentDto> > .Create(SubscriptionType.instrument, dtos => { foreach (var instrumentDto in dtos) { lock (_syncObj) { var existing = Instruments.FirstOrDefault(a => a.Symbol == instrumentDto.Symbol); if (existing != null) { Mapper.Map <InstrumentDto, InstrumentModel>(instrumentDto, existing); } else { Instruments.Add(Mapper.Map <InstrumentDto, InstrumentModel>(instrumentDto)); } } } })); _bitmexApiSocketService.Subscribe(BitmexApiSubscriptionInfo <IEnumerable <OrderDto> > .Create(SubscriptionType.order, dtos => { foreach (var order in dtos) { lock (_syncObjOrders) { var existing = OrderUpdates.FirstOrDefault(a => a.OrderId == order.OrderId); if (existing != null) { Mapper.Map <OrderDto, OrderUpdateModel>(order, existing); } else { OrderUpdates.Add(Mapper.Map <OrderDto, OrderUpdateModel>(order)); } } OnPropertyChanged(nameof(OrderUpdates)); } })); } }
private void Client_PositionsReceived(object sender, CollectionReceivedEventArgs <Position> e) { var i = Instruments.FirstOrDefault(m => m.Id == e.Data[0].InstrumentId); if (i != null) { i.LastError = null; lock (Positions) { foreach (var m in e.Data) { Positions.Add(new PositionEntry(e.Action, i, m)); } const int MAX = 100; while (Positions.Count > 100) { Positions.RemoveAt(Positions.Count - 1 - MAX); } } lock (ActivePositions) { // 対象のInstrumentのポジションのみを対象に副作用を与える var activePositions = ActivePositions.Where(p => p.Instrument.Id.Equals(i.Id)).ToList(); if (e.Action == NotifyCollectionChangedAction.Add || e.Action == NotifyCollectionChangedAction.Replace) { // Add,Replace が来たらスナップショット受信とみなして入れ替える foreach (var ap in activePositions) { ActivePositions.Remove(ap); } foreach (var m in e.Data) { ActivePositions.Add(new PositionEntry(e.Action, i, m)); } } else if (e.Action == NotifyCollectionChangedAction.Remove || e.Action == NotifyCollectionChangedAction.Reset) { // Remove,Reset が来たらポジションが全て決済されたとみなして削除する foreach (var ap in activePositions) { ActivePositions.Remove(ap); } } else if (e.Action == NotifyCollectionChangedAction.Move) { } } } }
// TODO: wamp sends strange tickprices with ask=bid, temporary switch to direct rabbitmq connection // private void StartWampConnection() // { // var wampSettings = new WampSubscriberSettings() // { // Address = Config.WampEndpoint.Url, // Realm = Config.WampEndpoint.PricesRealm, // Topics = Instruments.SelectMany(i => new string[] { // String.Format(Config.WampEndpoint.PricesTopic, i.Name.ToLowerInvariant(), "ask", "sec"), // String.Format(Config.WampEndpoint.PricesTopic, i.Name.ToLowerInvariant(), "bid", "sec") }).ToArray() // }; // // this.wampSubscriber = new WampSubscriber<Candle>(wampSettings, this.LykkeLog) // .Subscribe(HandlePrice); // // this.wampSubscriber.Start(); // } /// <summary> /// Called on incoming prices /// </summary> /// <param name="candle">Incoming candlestick</param> /// <remarks>Can be called simultaneously from multiple threads</remarks> private async Task HandlePrice(Candle candle) { var instrument = Instruments.FirstOrDefault(i => string.Equals(i.Name, candle.Asset, StringComparison.InvariantCultureIgnoreCase)); if (instrument != null) { var tickPrice = new TickPrice( instrument, candle.Timestamp, ask: candle.L, bid: candle.H); await _tickPriceHandler.Handle(tickPrice); } }
private void PopulateJobs() { var dataUpdateJobKeys = _scheduler.GetJobKeys(GroupMatcher <JobKey> .AnyGroup()); foreach (JobKey job in dataUpdateJobKeys) { IJobDetail jobDetails = _scheduler.GetJobDetail(job); if (job.Group == JobTypes.DataUpdate) { try { var jd = JsonConvert.DeserializeObject <DataUpdateJobSettings>((string)jobDetails.JobDataMap["settings"]); if (jd.InstrumentID.HasValue) { jd.Instrument = Instruments.FirstOrDefault(x => x.ID == jd.InstrumentID.Value); } if (jd.TagID.HasValue) { jd.Tag = Tags.FirstOrDefault(x => x.ID == jd.TagID.Value); } Jobs.Add(new DataUpdateJobViewModel(jd, _scheduler)); } catch (Exception e) { _logger.Error(e, "Failed to deserialize data update job"); } } else if (job.Group == JobTypes.EconomicRelease) { try { var jd = JsonConvert.DeserializeObject <EconomicReleaseUpdateJobSettings>((string)jobDetails.JobDataMap["settings"]); Jobs.Add(new EconomicReleaseUpdateJobViewModel(jd, _scheduler)); } catch (Exception e) { _logger.Error(e, "Failed to deserialize economic release update job"); } } } }
private void Client_ExecutionsReceived(object sender, CollectionReceivedEventArgs <Execution> e) { var i = Instruments.FirstOrDefault(m => m.Id == e.Data[0].InstrumentId); if (i != null) { i.LastError = null; lock (Executions) { foreach (var m in e.Data) { Executions.Add(new ExecutionEntry(e.Action, i, m)); } const int MAX = 100; while (Executions.Count > 100) { Executions.RemoveAt(Executions.Count - 1 - MAX); } } } }
private void BitFlyer_ChildOrdersReceived(object sender, CollectionReceivedEventArgs <BitFlyerChildOrder> e) { var i = Instruments.FirstOrDefault(m => m.Id == e.Data[0].InstrumentId); if (i != null) { i.LastError = null; lock (ChildOrders) { foreach (var m in e.Data) { ChildOrders.Add(new ChildOrderEntry(e.Action, i, m)); } const int MAX = 100; while (ChildOrders.Count > 100) { ChildOrders.RemoveAt(ChildOrders.Count - 1 - MAX); } } } }
private async Task HandleOrderBook(OrderBook orderBook) { var instrument = Instruments.FirstOrDefault(x => string.Compare(x.Name, orderBook.AssetPair, StringComparison.InvariantCultureIgnoreCase) == 0); if (instrument == null && Config.UseSupportedCurrencySymbolsAsFilter == false) { instrument = new Instrument(Name, orderBook.AssetPair); } if (instrument != null) { if (orderBook.Prices.Any()) { decimal bestBid = 0; decimal bestAsk = 0; if (orderBook.IsBuy) { _lastBids[instrument.Name] = bestBid = orderBook.Prices.Select(x => x.Price).OrderByDescending(x => x).First(); bestAsk = _lastAsks.ContainsKey(instrument.Name) ? _lastAsks[instrument.Name] : 0; } else { _lastAsks[instrument.Name] = bestAsk = orderBook.Prices.Select(x => x.Price).OrderBy(x => x).First(); bestBid = _lastBids.ContainsKey(instrument.Name) ? _lastBids[instrument.Name] : 0; } if (bestBid > 0 && bestAsk > 0) { var tickPrice = new TickPrice(instrument, orderBook.Timestamp, bestAsk, bestBid); await _tickPriceHandler.Handle(tickPrice); await _orderBookHandler.Handle(orderBook); } } } }
private void StartLoad() { try { IsConnected = _bitmexApiSocketService.Connect(); } catch (Exception e) { MessageBox.Show(e.Message); } if (IsConnected) { _bitmexApiSocketService.Subscribe(BitmetSocketSubscriptions.CreateInstrumentSubsription( message => { foreach (var instrumentDto in message.Data) { lock (_syncObj) { var existing = Instruments.FirstOrDefault(a => a.Symbol == instrumentDto.Symbol); if (existing != null && message.Action == BitmexActions.Update) { Mapper.Map <InstrumentDto, InstrumentModel>(instrumentDto, existing); } else if (message.Action != BitmexActions.Partial && message.Action != BitmexActions.Delete) { Instruments.Add(Mapper.Map <InstrumentDto, InstrumentModel>(instrumentDto)); } } } })); _bitmexApiSocketService.Subscribe(BitmetSocketSubscriptions.CreateOrderSubsription( message => { foreach (var order in message.Data) { lock (_syncObjOrders) { var existing = OrderUpdates.FirstOrDefault(a => a.OrderId == order.OrderId); if (existing != null && message.Action == BitmexActions.Update) { Mapper.Map <OrderDto, OrderUpdateModel>(order, existing); } else if (message.Action != BitmexActions.Partial && message.Action != BitmexActions.Delete) { OrderUpdates.Add(Mapper.Map <OrderDto, OrderUpdateModel>(order)); } } OnPropertyChanged(nameof(OrderUpdates)); } })); _bitmexApiSocketService.Subscribe(BitmetSocketSubscriptions.CreateOrderBook10Subsription( message => { foreach (var dto in message.Data) { if (dto.Symbol != "XBTUSD") { continue; } lock (_syncObjOrderBook10) { OrderBook10 = dto.Asks.Select(a => new OrderBookModel { Direction = "Sell", Price = a[0], Size = a[1] }) .Union(dto.Asks.Select(a => new OrderBookModel { Direction = "Buy", Price = a[0], Size = a[1] })).ToList(); } OnPropertyChanged(nameof(OrderBook10)); } })); _bitmexApiSocketService.Subscribe(BitmetSocketSubscriptions.CreateOrderBookL2Subsription( message => { foreach (var dto in message.Data) { if (dto.Symbol != "XBTUSD") { continue; } lock (_syncObjOrderBookL2) { if (message.Action == BitmexActions.Insert || message.Action == BitmexActions.Partial) { OrderBookL2.Add(Mapper.Map <OrderBookDto, OrderBookModel>(dto)); } if (message.Action == BitmexActions.Delete) { var existing = OrderBookL2.FirstOrDefault(a => a.Id == dto.Id); if (existing != null) { OrderBookL2.Remove(existing); } } if (message.Action == BitmexActions.Update) { var existing = OrderBookL2.FirstOrDefault(a => a.Id == dto.Id); if (existing == null) { OrderBookL2.Add(Mapper.Map <OrderBookDto, OrderBookModel>(dto)); } else { Mapper.Map <OrderBookDto, OrderBookModel>(dto, existing); } } } OnPropertyChanged(nameof(OrderBook10)); } })); } }