protected virtual OrderBookEntry GetAvailableToBuy(double maxBuy) { OrderBookEntry res = new OrderBookEntry(); double maxDeposit = ApplyFee(MaxActualBuyDeposit); lock (Ticker.OrderBook.Asks) { for (int i = 0; i < Ticker.OrderBook.Asks.Count; i++) { OrderBookEntry entry = Ticker.OrderBook.Asks[i]; if (maxBuy != 0 && entry.Value > maxBuy) { break; } res.Value = entry.Value; double amount = maxDeposit / entry.Value; if (amount > entry.Amount) { amount = entry.Amount; } res.Amount += amount; maxDeposit -= amount * entry.Value; if (maxDeposit == 0) { break; } } } return(res); }
private static void OnOrderBookChanged(object sender, OrderBookEventArgs e) { Ticker t = ((OrderBook)sender).Owner; OrderBookEntry ask = t.OrderBook.Asks[0]; OrderBookEntry bid = t.OrderBook.Bids[0]; }
private void InsertOrderHistoryEntry( decimal filledQty, OrderBookEntry orderToClose, OrderStatus status, DateTime closeTime) { OrderHistory.InsertOne( new OrderHistoryEntry { CreateTime = orderToClose.EntryTime, CloseTime = closeTime, User = orderToClose.User, AccountId = orderToClose.AccountId, Instrument = orderToClose.Instrument, Qty = orderToClose.Qty, Side = orderToClose.Side, // Closed limit order Type = OrderType.Limit, // The entire order quantity was filled FilledQty = filledQty, LimitPrice = orderToClose.LimitPrice, StopPrice = null, // TODO from stop loss and take profit //ChildrenIds DurationType = orderToClose.DurationType, Duration = orderToClose.Duration, Status = status, } ); }
public override bool UpdateOrderBook(TickerBase ticker) { string address = string.Format("https://yobit.net/api/3/depth/{0}?depth={1}", Uri.EscapeDataString(ticker.CurrencyPair), OrderBook.Depth); string text = ((TickerBase)ticker).DownloadString(address); if (string.IsNullOrEmpty(text)) { return(false); } Dictionary <string, object> res2 = null; lock (JsonParser) { res2 = JsonParser.Parse(text) as Dictionary <string, object>; if (res2 == null) { return(false); } } res2 = (Dictionary <string, object>)res2[ticker.CurrencyPair]; List <object> bids = (List <object>)res2["bids"]; List <object> asks = (List <object>)res2["asks"]; ticker.OrderBook.GetNewBidAsks(); int index = 0; OrderBookEntry[] list = ticker.OrderBook.Bids; foreach (List <object> item in bids) { OrderBookEntry entry = list[index]; entry.ValueString = (string)item.First(); entry.AmountString = (string)item.Last(); index++; if (index >= list.Length) { break; } } index = 0; list = ticker.OrderBook.Asks; foreach (List <object> item in asks) { OrderBookEntry entry = list[index]; entry.ValueString = (string)item.First(); entry.AmountString = (string)item.Last(); index++; if (index >= list.Length) { break; } } ticker.OrderBook.UpdateEntries(); ticker.OrderBook.RaiseOnChanged(new OrderBookUpdateInfo() { Action = OrderBookUpdateType.RefreshAll }); return(true); }
public void RunPriceLevelDelete(string pair, OrderBookEntry[] bids, OrderBookEntry[] asks) { if (OrderBooks.ContainsKey(pair)) { OrderBookDictionary dic = OrderBooks[pair]; foreach (OrderBookEntry bid in bids) { if (dic.Entries.ContainsKey(bid.id)) { OrderBookEntry entry = dic.Entries[bid.id]; dic.Entries.Remove(bid.id); } //else // throw new Exception(string.Format("Could not find price level for pair {0} with id {1}", pair, bid.id)); } foreach (OrderBookEntry ask in asks) { if (dic.Entries.ContainsKey(ask.id)) { OrderBookEntry entry = dic.Entries[ask.id]; dic.Entries.Remove(ask.id); } //else // throw new Exception(string.Format("Could not find price level for pair {0} with id {1}", pair, ask.id)); } } else { throw new Exception(string.Format("Unknown Error: Order Book not found in memory for pair {0}", pair)); } }
public void RunPriceLevelUpdate(string pair, OrderBookEntry[] bids, OrderBookEntry[] asks) { if (OrderBooks.ContainsKey(pair)) { OrderBookDictionary dic = OrderBooks[pair]; foreach (OrderBookEntry bid in bids) { if (dic.Entries.ContainsKey(bid.id)) { OrderBookEntry entry = dic.Entries[bid.id]; entry.size = bid.size; } //else // throw new Exception(string.Format("Could not find price level for pair {0} with id {1}", pair, bid.id)); } foreach (OrderBookEntry ask in asks) { if (dic.Entries.ContainsKey(ask.id)) { OrderBookEntry entry = dic.Entries[ask.id]; Console.WriteLine(string.Format("ASK UPDATE SIZE={0} PRICE={1}", ask.size.ToString("##.##"), entry.price.ToString("##.########"))); entry.size = ask.size; } //else // throw new Exception(string.Format("Could not find price level for pair {0} with id {1}", pair, ask.id)); } } else { throw new Exception(string.Format("Unknown Error: Order Book not found in memory for pair {0}", pair)); } }
protected virtual OrderBookEntry GetAvailableToSell(double minSell) { OrderBookEntry res = new OrderBookEntry(); double maxDeposit = ApplyFee(MaxActualSellDeposit); res.Amount = maxDeposit; lock (Ticker.OrderBook.Bids) { for (int i = 0; i < Ticker.OrderBook.Bids.Count; i++) { OrderBookEntry entry = Ticker.OrderBook.Bids[i]; if (minSell != 0 && entry.Value < minSell) { break; } res.Value = entry.Value; res.Amount += entry.Amount; maxDeposit -= entry.Amount; if (maxDeposit <= 0) { break; } } } res.Amount = Math.Min(res.Amount, ApplyFee(MaxActualSellDeposit)); return(res); }
public BitmexMarketDataOrderBookEntryWrapper(string pAction, OrderBookEntry pOrderBookEntry, bool isBid) { action = pAction; OrderBookEntry = pOrderBookEntry; IsBid = isBid; }
public void ShortSellTest() { //OrderList = new Dictionary<string, int>(); //OrderList.Add("000768", 1000); //OrderList.Add("600893", 600); //OrderList.Add("300070", 1200); //OrderList.Add("300024", 1000); //OrderList.Add("300124", 700); //OrderList.Add("300058", 800); //OrderList.Add("300002", 1000); //OrderList.Add("300003", 800); if (OrderList == null) { return; } foreach (KeyValuePair <string, int> kvp in OrderList) { try { SingleStockData sd = dataDict[kvp.Key]; FIXApi.OrderBookEntry entry = new OrderBookEntry(); entry.strategies = TradingStrategies.StockTrending; entry.action = OrderAction.ShortSell; entry.type = FIXApi.OrderType.CreditMarginSell; entry.ticker = kvp.Key; entry.quantityListed = kvp.Value; int tCount = 0; while (sd.AskPrices[0] == 0) { tCount++; Thread.Sleep(100); if (tCount > 100) { break; } } if (sd.AskPrices[0] == 0) { continue; } entry.priceListed = sd.AskPrices[0]; Thread orderThread = new Thread(new ParameterizedThreadStart(tc.OrderSender_StockTrending)); orderThread.IsBackground = true; orderThread.Start(entry); } catch (Exception ex) { strListLog.Add(ex.Message); } } }
public void GetOrderBook(BittrexMarketInfo info, int depth) { Timer.Reset(); Timer.Start(); string address = string.Format("https://bittrex.com/api/v1.1/public/getorderbook?market={0}&type=both&depth={1}", Uri.EscapeDataString(info.MarketName), depth); string text = GetDownloadString(info, address); if (string.IsNullOrEmpty(text)) { return; } JObject res = (JObject)JsonConvert.DeserializeObject(text); foreach (JProperty prop in res.Children()) { if (prop.Name == "success") { if (prop.Value.Value <bool>() == false) { break; } } if (prop.Name == "message") { continue; } if (prop.Name == "result") { lock (info) { info.OrderBook.Clear(); JArray bids = ((JObject)prop.Value).Value <JArray>("buy"); JArray asks = ((JObject)prop.Value).Value <JArray>("sell"); foreach (JObject obj in bids) { OrderBookEntry e = new OrderBookEntry(); e.Value = obj.Value <double>("Rate"); e.Amount = obj.Value <double>("Quantity"); info.OrderBook.Bids.Add(e); } foreach (JObject obj in asks) { OrderBookEntry e = new OrderBookEntry(); e.Value = obj.Value <double>("Rate"); e.Amount = obj.Value <double>("Quantity"); info.OrderBook.Asks.Add(e); } } Timer.Stop(); Console.WriteLine(DateTime.Now.ToString("hh:mm:ss.fff") + " order book update. process time = " + Timer.ElapsedMilliseconds); } } info.OrderBook.RaiseOnChanged(new OrderBookUpdateInfo() { Action = OrderBookUpdateType.RefreshAll }); }
public void OrderBookEntry_constructor_test() { double price = 100; double volume = 10; OrderBookEntry entry = new OrderBookEntry(price, volume); Assert.AreEqual(price, entry.Price); Assert.AreEqual(volume, entry.Volume); }
private void UpdateOrderBook() { List <OrderBookRowData> list = new List <OrderBookRowData>(); lock (this.instrument.OrderBook.Ask.SyncRoot) { IEnumerator local_7 = this.instrument.OrderBook.Ask.GetEnumerator(); try { while (local_7.MoveNext()) { OrderBookEntry local_1 = (OrderBookEntry)local_7.Current; list.Insert(0, new OrderBookRowData(local_1.Price, new int?(), new int?(local_1.Size))); } } finally { IDisposable local_9 = local_7 as IDisposable; if (local_9 != null) { local_9.Dispose(); } } } lock (this.instrument.OrderBook.Bid.SyncRoot) { IEnumerator local_11 = this.instrument.OrderBook.Bid.GetEnumerator(); try { while (local_11.MoveNext()) { OrderBookEntry local_2 = (OrderBookEntry)local_11.Current; list.Add(new OrderBookRowData(local_2.Price, new int?(local_2.Size), new int?())); } } finally { IDisposable local_13 = local_11 as IDisposable; if (local_13 != null) { local_13.Dispose(); } } } this.dgvBook.Columns["colPrice"].DefaultCellStyle.Format = this.instrument.PriceDisplay; int scrollingRowIndex = this.dgvBook.FirstDisplayedScrollingRowIndex; this.dgvBook.DataSource = (object)list; if (scrollingRowIndex < 0 || scrollingRowIndex >= this.dgvBook.Rows.Count) { return; } this.dgvBook.FirstDisplayedScrollingRowIndex = scrollingRowIndex; }
/** * getOrderBookExample * Get the market depth for specific market. */ public static void GetOrderBookExample() { /***Initialize the calling object*/ IdaxApiRestClient idaxApiRestClient = IdaxConfig.init(); /**Request parameter encapsulation**/ string symbol = IdaxApiConstants.ETH_BTC; /**Call remote interface**/ OrderBookEntry orderBook = idaxApiRestClient.getOrderBook(symbol); }
public OrderBookEntry GetOrderBookEntry(Wrapper wrapper) { OrderBookEntry entry = new OrderBookEntry(); entry.MDEntryType = (MDEntryType)wrapper.GetField(MarketDataOrderBookEntryFields.MDEntryType); entry.MDUpdateAction = (MDUpdateAction)wrapper.GetField(MarketDataOrderBookEntryFields.MDUpdateAction); entry.Symbol = (ValidateField(wrapper, MarketDataOrderBookEntryFields.Symbol) ? Convert.ToString(wrapper.GetField(MarketDataOrderBookEntryFields.Symbol)) : null); entry.MDEntrySize = (ValidateField(wrapper, MarketDataOrderBookEntryFields.MDEntrySize) ? Convert.ToDecimal(wrapper.GetField(MarketDataOrderBookEntryFields.MDEntrySize)) : 0); entry.MDEntryPx = (ValidateField(wrapper, MarketDataOrderBookEntryFields.MDEntryPx) ? Convert.ToDecimal(wrapper.GetField(MarketDataOrderBookEntryFields.MDEntryPx)) : 0); return(entry); }
private void button1_Click(object sender, EventArgs e) { //限价 //string tickerListStr = dc.LoadDataDict(); //dc.SetSubscription(tickerListStr, SubscriptionType.SUBSCRIPTION_SET); //while (dataDict.Count < 1000) // Thread.Sleep(1000); if (OrderClassList.Count == 0) { MessageBox.Show("无下单股票"); } foreach (OrderClass oclass in OrderClassList) { OrderBookEntry entry = new OrderBookEntry(); entry.Account = oclass.Account; //买卖方向 entry.action = (OrderAction)Enum.Parse(typeof(OrderAction), oclass.Direction); entry.orderTime = Convert.ToInt32(DateTime.Now.ToString("Hmmss")); entry.orderDate = Convert.ToInt32(DateTime.Now.ToString("yyyyMMdd")); entry.ticker = oclass.Ticker; entry.strategies = (TradingStrategies)Enum.Parse(typeof(TradingStrategies), oclass.Strategy); entry.quantityListed = oclass.Num; //限价 //entry.bMarket = false; //entry.priceListed = 10; //市价 entry.bMarket = true; entry.priceListed = 0; //模拟交易时使用资金账户买 if (Convert.ToString(entry.action).Contains("Buy")) { entry.type = OrderType.CashBuy; } else { entry.type = OrderType.CashSell; } Thread orderThread = new Thread(new ParameterizedThreadStart(ec.OrderRouter)); orderThread.IsBackground = true; orderThread.Start(entry); Thread.Sleep(100); } }
protected void Buy() { OrderBookEntry e = GetAvailableToBuy(BuyLevel); TradingResult res = MarketBuy(e.Value, e.Amount); if (res == null) { return; } BoughtTotal += res.Total; Earned -= res.Total + CalcFee(res.Total); MaxActualBuyDeposit -= res.Total + CalcFee(res.Total); MaxActualSellDeposit += res.Amount; }
protected void Sell() { OrderBookEntry e = GetAvailableToSell(SellLevel); TradingResult res = MarketSell(e.Value, e.Amount); if (res == null) { return; } SoldTotal += res.Amount; Earned += res.Total - CalcFee(res.Total); MaxActualBuyDeposit += res.Total; MaxActualSellDeposit -= res.Amount + CalcFee(res.Total); }
private void AssertMatchOrderQty( MatchOrderEventEntry matchOrder, OrderBookEntry actionOrder, OrderBookEntry targetOrder) { if (actionOrder != null && matchOrder.ActionOrderQtyRemaining != actionOrder.Qty - (actionOrder.FilledQty + matchOrder.Qty)) { throw new Exception( $"Integrity assertion failed! {nameof(MatchOrderEventEntry)} ID {matchOrder.Id} attempted to increase {nameof(targetOrder.FilledQty)} of action order ID {actionOrder.Id} from {actionOrder.FilledQty.ToString(CultureInfo.CurrentCulture)} by {matchOrder.Qty}, but that didn't add up to event entry-asserted value of {matchOrder.ActionOrderQtyRemaining.ToString(CultureInfo.CurrentCulture)}!"); } if (matchOrder.TargetOrderQtyRemaining != targetOrder.Qty - (targetOrder.FilledQty + matchOrder.Qty)) { throw new Exception( $"Integrity assertion failed! {nameof(MatchOrderEventEntry)} ID {matchOrder.Id} attempted to increase {nameof(targetOrder.FilledQty)} of target order ID {targetOrder.Id} from {targetOrder.FilledQty.ToString(CultureInfo.CurrentCulture)} by {matchOrder.Qty}, but that didn't add up to event entry-asserted value of {matchOrder.TargetOrderQtyRemaining.ToString(CultureInfo.CurrentCulture)}!"); } }
public NewOrder(SymbolInformation si, OrderBookEntry entry = null) : base(si) { if (entry != null) { Price = entry.Price; Quantity = entry.Quantity; Side = (entry.Side == TradeSide.Buy) ? TradeSide.Sell : TradeSide.Buy; } else { Price = si.PriceTicker.LastPrice.GetValueOrDefault(); } this.WhenAnyValue(x => x.Side).Subscribe(OrderSideDependantActions); this.WhenAnyValue(x => x.BalancePercent).Subscribe(y => CalcQuantity()); BalancePercent = 0.05; }
void OnUpdateOrderBook(Ticker ticker, byte[] bytes) { int startIndex = 0; string[] updateId = JSonHelper.Default.StartDeserializeObject(bytes, ref startIndex, OrderBookStartItems); const string bidString = "\"bids\":"; const string askString = "\"asks\":"; startIndex += bidString.Length + 1; List <string[]> jbids = JSonHelper.Default.DeserializeArrayOfArrays(bytes, ref startIndex, 3); startIndex += askString.Length + 1; List <string[]> jasks = JSonHelper.Default.DeserializeArrayOfArrays(bytes, ref startIndex, 3); List <OrderBookEntry> bids = ticker.OrderBook.Bids; List <OrderBookEntry> asks = ticker.OrderBook.Asks; List <OrderBookEntry> iasks = ticker.OrderBook.AsksInverted; bids.Clear(); asks.Clear(); iasks.Clear(); foreach (string[] item in jbids) { bids.Add(new OrderBookEntry() { ValueString = item[0], AmountString = item[1] }); } foreach (string[] item in jasks) { OrderBookEntry e = new OrderBookEntry() { ValueString = item[0], AmountString = item[1] }; asks.Add(e); iasks.Insert(0, e); } ticker.OrderBook.Updates.Clear(FastValueConverter.ConvertPositiveLong(updateId[0]) + 1); ticker.OrderBook.UpdateEntries(); ticker.OrderBook.RaiseOnChanged(new IncrementalUpdateInfo()); ticker.RaiseChanged(); }
public void Update(IEnumerable <UpdateDataItem> items, OrderBookSides side) { foreach (var entry in items) { if (side == OrderBookSides.Buy) { var updatedEntry = new OrderBookEntry(entry.Id, entry.Size, _bids[entry.Id].Price); _bids.TryUpdate(entry.Id, updatedEntry, _bids[entry.Id]); } else if (side == OrderBookSides.Sell) { var updatedEntry = new OrderBookEntry(entry.Id, entry.Size, _asks[entry.Id].Price); _asks.TryUpdate(entry.Id, updatedEntry, _asks[entry.Id]); } } }
bool OnUpdateOrderBook(Ticker ticker, byte[] bytes) { if (bytes == null) { return(false); } int startIndex = 0; // skip { List <string[]> items = JSonHelper.Default.DeserializeArrayOfObjects(bytes, ref startIndex, OrderBookItems); ticker.OrderBook.BeginUpdate(); try { List <OrderBookEntry> bids = ticker.OrderBook.Bids; List <OrderBookEntry> asks = ticker.OrderBook.Asks; List <OrderBookEntry> iasks = ticker.OrderBook.AsksInverted; for (int i = 0; i < items.Count; i++) { string[] item = items[i]; OrderBookEntry entry = new OrderBookEntry(); entry.Id = FastValueConverter.ConvertPositiveLong(item[1]); entry.ValueString = item[4]; entry.AmountString = item[3]; if (item[2][0] == 'S') { if (iasks != null) { iasks.Add(entry); } asks.Insert(0, entry); } else { bids.Add(entry); } } } finally { ticker.OrderBook.IsDirty = false; ticker.OrderBook.EndUpdate(); } return(true); }
public bool UpdateOrderBook(Ticker ticker, byte[] bytes, bool raiseChanged, int depth) { if (bytes == null) { return(false); } int startIndex = 0; List <string[]> items = JSonHelper.Default.DeserializeArrayOfArrays(bytes, ref startIndex, 3); ticker.OrderBook.GetNewBidAsks(); int bidIndex = 0, askIndex = 0; List <OrderBookEntry> bids = ticker.OrderBook.Bids; List <OrderBookEntry> asks = ticker.OrderBook.Asks; foreach (string[] item in items) { OrderBookEntry entry = null; if (item[2][0] == '-') { entry = asks[askIndex]; entry.Amount = -FastValueConverter.Convert(item[2]); askIndex++; } else { entry = bids[bidIndex]; entry.AmountString = item[2]; bidIndex++; } entry.ValueString = item[0]; if (bidIndex >= bids.Count || askIndex >= asks.Count) { break; } } ticker.OrderBook.UpdateEntries(); return(true); }
public bool OnUpdateOrderBook(Ticker ticker, byte[] bytes, bool raiseChanged, int depth) { if(bytes == null) return false; int startIndex = 0; List<string[]> items = JSonHelper.Default.DeserializeArrayOfArrays(bytes, ref startIndex, 3); ticker.OrderBook.BeginUpdate(); try { ticker.OrderBook.GetNewBidAsks(); int bidIndex = 0, askIndex = 0; List<OrderBookEntry> bids = ticker.OrderBook.Bids; List<OrderBookEntry> asks = ticker.OrderBook.Asks; for(int i = 0; i < items.Count; i++) { string[] item = items[i]; OrderBookEntry entry = null; if(item[2][0] == '-') { entry = asks[askIndex]; entry.Amount = -FastValueConverter.Convert(item[2]); askIndex++; } else { entry = bids[bidIndex]; entry.AmountString = item[2]; bidIndex++; } entry.ValueString = item[0]; if(bidIndex >= bids.Count || askIndex >= asks.Count) break; } } finally { ticker.OrderBook.IsDirty = false; ticker.OrderBook.EndUpdate(); } return true; }
public void PrevLockAll() { foreach (string ticker in dc.TickerList) { SingleStockData sd = dataDict[ticker]; FIXApi.OrderBookEntry entry = new OrderBookEntry(); entry.strategies = TradingStrategies.StockTrending; entry.action = OrderAction.PrevLock; entry.type = FIXApi.OrderType.CreditMarginSell; entry.ticker = ticker; entry.quantityListed = sd.Quantity; entry.priceListed = Math.Round(sd.PrevClose * 1.098, 2); //entry.orderTime = sd.BuyTime; //entry.orderDate = sd.DateStamp; Thread orderThread = new Thread(new ParameterizedThreadStart(tc.OrderSender_StockTrending)); orderThread.IsBackground = true; orderThread.Start(entry); Thread.Sleep(1000); //避免堵塞 } }
private static (decimal price, decimal above) GetBestCurrentPrice(OrderBook orderBook, OrderKind kind, decimal myCurPrice, decimal myVolume) { // Allowed cumulative volume percentage above our order const decimal allowAbove = 0.15m; decimal volumeAllowedAbove = myVolume * allowAbove; IReadOnlyList <OrderBookEntry> entries = kind == OrderKind.Buy ? orderBook.Bids : orderBook.Asks; int placeAbove = 0; while (true) { OrderBookEntry entry = entries[placeAbove]; decimal volume = entry.Volume - (entry.Price == myCurPrice ? myVolume : 0); if (volume > volumeAllowedAbove) { break; } placeAbove++; volumeAllowedAbove -= volume; } decimal price = entries[placeAbove].Price; if (kind == OrderKind.Buy) { price += 0.00001m; } else { price -= 0.00001m; } return(price, myVolume *allowAbove - volumeAllowedAbove); }
bool UpdateOrderBook(Ticker ticker, byte[] bytes) { if (bytes == null) { return(false); } int startIndex = 0; // skip { List <string[]> items = JSonHelper.Default.DeserializeArrayOfObjects(bytes, ref startIndex, OrderBookItems); List <OrderBookEntry> bids = ticker.OrderBook.Bids; List <OrderBookEntry> asks = ticker.OrderBook.Asks; List <OrderBookEntry> iasks = ticker.OrderBook.AsksInverted; foreach (string[] item in items) { OrderBookEntry entry = new OrderBookEntry(); entry.Id = FastValueConverter.ConvertPositiveLong(item[1]); entry.ValueString = item[4]; entry.AmountString = item[3]; if (item[2][0] == 'S') { iasks.Add(entry); asks.Insert(0, entry); } else { bids.Add(entry); } } ticker.OrderBook.UpdateEntries(); return(true); }
internal void OnUpdateOrderBook(Ticker ticker, byte[] bytes) { int startIndex = 0; string[] updateId = JSonHelper.Default.StartDeserializeObject(bytes, ref startIndex, OrderBookStartItems); if (ticker.CaptureData) { ticker.CaptureDataCore(CaptureStreamType.OrderBook, CaptureMessageType.Snapshot, System.Text.ASCIIEncoding.Default.GetString(bytes)); } const string bidString = "\"bids\":"; const string askString = "\"asks\":"; startIndex += bidString.Length + 1; List <string[]> jbids = JSonHelper.Default.DeserializeArrayOfArrays(bytes, ref startIndex, 2); startIndex += askString.Length + 1; List <string[]> jasks = JSonHelper.Default.DeserializeArrayOfArrays(bytes, ref startIndex, 2); ticker.OrderBook.BeginUpdate(); try { List <OrderBookEntry> bids = ticker.OrderBook.Bids; List <OrderBookEntry> asks = ticker.OrderBook.Asks; List <OrderBookEntry> iasks = ticker.OrderBook.AsksInverted; bids.Clear(); asks.Clear(); if (iasks != null) { iasks.Clear(); } if (jbids != null) { for (int i = 0; i < jbids.Count; i++) { string[] item = jbids[i]; bids.Add(new OrderBookEntry() { ValueString = item[0], AmountString = item[1] }); } } if (jasks != null) { for (int i = 0; i < jasks.Count; i++) { string[] item = jasks[i]; OrderBookEntry e = new OrderBookEntry() { ValueString = item[0], AmountString = item[1] }; asks.Add(e); if (iasks != null) { iasks.Insert(0, e); } } } ticker.OrderBook.Updates.Clear(FastValueConverter.ConvertPositiveLong(updateId[0]) + 1); } finally { ticker.OrderBook.IsDirty = false; ticker.OrderBook.EndUpdate(); } ticker.RaiseChanged(); }
public bool UpdateArbitrageOrderBook(ExmoTicker ticker, int depth) { string text = string.Empty; string address = string.Format("https://api.exmo.me/v1/order_book/?pair={0}", ticker.MarketName); try { text = GetDownloadString(address); if (text == null) { return(false); } } catch (Exception) { return(false); } Dictionary <string, object> res = null; lock (JsonParser) { res = (Dictionary <string, object>)JsonParser.Parse(text); } res = (Dictionary <string, object>)res[ticker.MarketName]; List <object> bids = (List <object>)res["bid"]; List <object> asks = (List <object>)res["ask"]; ticker.OrderBook.GetNewBidAsks(); int index = 0; OrderBookEntry[] list = ticker.OrderBook.Bids; foreach (List <object> item in bids) { OrderBookEntry entry = list[index]; entry.Value = (decimal)(double.Parse((string)item.First())); entry.Amount = (decimal)(double.Parse((string)item.Last())); index++; if (index >= list.Length) { break; } } index = 0; list = ticker.OrderBook.Asks; foreach (List <object> item in asks) { OrderBookEntry entry = list[index]; entry.Value = (decimal)(double.Parse((string)item.First())); entry.Amount = (decimal)(double.Parse((string)item.Last())); index++; if (index >= list.Length) { break; } } ticker.OrderBook.UpdateEntries(); ticker.OrderBook.RaiseOnChanged(new OrderBookUpdateInfo() { Action = OrderBookUpdateType.RefreshAll }); return(true); }
//重载OnRecvDataMsg方法,接收行情数据 // 请注意: // 1. 不要在这个函数里做耗时操作 // 2. 只在这个函数里做数据获取工作 -- 将数据复制到其它数据缓存区,由其它线程做业务逻辑处理 public override void OnRecvDataMsg(TDFMSG msg) { try { if (msg.MsgID == TDFMSGID.MSG_DATA_MARKET) { //行情消息 TDFMarketData[] marketDataArr = msg.Data as TDFMarketData[]; foreach (TDFMarketData data in marketDataArr) { //if (data.Code.Contains("10000015")) // continue; lock (this.dataDict) { if (dataDict.Keys.Contains(data.Code)) { SingleStockData sd = dataDict[data.Code]; //数据获取部分 if (data.Match != 0) { sd.LastPrice = (double)data.Match / 10000; //最新成交价 } sd.PrevClose = (double)data.PreClose / 10000; sd.AskPrices[0] = (double)data.AskPrice[0] / 10000; sd.BidPrices[0] = (double)data.BidPrice[0] / 10000; for (int i = 0; i < 10; i++) { sd.BidPrices[i] = (double)data.BidPrice[i] / 10000; sd.AskPrices[i] = (double)data.AskPrice[i] / 10000; sd.BidVol[i] = data.BidVol[i]; sd.AskVol[i] = data.AskVol[i]; } if ((sd.ShortPriceListed != sd.AskPrices[0]) && (sd.StatusTrending == StrategyStatus.ShortListedOnly)) //最新卖一已变动,需改价重挂 { sd.bAskPriceChanged = true; //测试,按卖五挂单 } # region Fishing Strategies //业务逻辑部分,只有对FishingStrategy这样时效要求极高的放在此处,其余均放入EngineClass if (sd.StatusCBFishing != StrategyStatus.None) //此ticker需要跑CBFishing Strategy { if (sd.StatusCBFishing == StrategyStatus.New) //首次挂买单,或上一轮结束后重新挂单 { //sd.LongPriceListed = sd.BidPrices[0] - sd.CBBuyPriceOffset; //挂在卖五,后续可以参数化 sd.LongPriceListed = sd.BidPrices[4]; //挂在卖五,后续可以参数化 sd.StatusCBFishing = StrategyStatus.LongListedOnly; //下一步考虑在EngineClass或TradeClass中生成Order,只需有strategy和ticker,即可在dataDict中取到生成order所需数据 FIXApi.OrderBookEntry entry = new OrderBookEntry(); entry.strategies = TradingStrategies.CBFishing; entry.action = OrderAction.Buy; entry.type = FIXApi.OrderType.CreditBuy; entry.ticker = data.Code; entry.quantityListed = sd.Quantity; entry.priceListed = sd.LongPriceListed; sd.StatusCBFishing = StrategyStatus.Pending; //获得成交回报后再改变状态,避免重复执行 Thread orderThread = new Thread(new ParameterizedThreadStart(tc.OrderSender_CBFishing)); orderThread.IsBackground = true; orderThread.Start(entry); } else if (sd.StatusCBFishing == StrategyStatus.LongListedOnly) //买单已挂,根据最新价格检查是否需要撤单重挂 { if ((sd.LongPriceListed >= sd.BidPrices[3]) || (sd.LongPriceListed <= sd.BidPrices[5])) //大于卖三或小于卖七时重挂 { sd.LongPriceListed = sd.BidPrices[0] - sd.CBBuyPriceOffset; FIXApi.OrderBookEntry entry = new OrderBookEntry(); entry.strategies = TradingStrategies.CBFishing; entry.action = OrderAction.CancelAndBuy; entry.type = FIXApi.OrderType.CreditBuy; entry.ticker = data.Code; entry.quantityListed = sd.Quantity; entry.priceListed = sd.LongPriceListed; sd.StatusCBFishing = StrategyStatus.Pending; //获得成交回报后再改变状态,避免重复执行 Thread orderThread = new Thread(new ParameterizedThreadStart(tc.OrderSender_CBFishing)); orderThread.IsBackground = true; orderThread.Start(entry); } //if ((sd.ShortPriceListed<data.AskPrice[4]) || (sd.ShortPriceListed>data.AskPrice[6]) ) //低于卖五或者高于卖七时撤单重挂,避免撤单过于频繁 // sd.ShortPriceListed = sd.AskPrices[4]; ////cancel and resend } else if (sd.StatusCBFishing == StrategyStatus.ShortListedOnly) //卖单已挂,根据最新价格检查是否需要撤单重挂 { if (sd.ShortPriceListed > sd.AskPrices[0]) { sd.ShortPriceListed = sd.AskPrices[0] - sd.CBSellPriceOffset; //一直挂在比卖一低0.01的位置 FIXApi.OrderBookEntry entry = new OrderBookEntry(); entry.strategies = TradingStrategies.CBFishing; entry.action = OrderAction.CancelAndSell_CF; entry.type = FIXApi.OrderType.CreditSell; entry.ticker = data.Code; entry.quantityListed = sd.Quantity; entry.priceListed = sd.ShortPriceListed; entry.strategies = TradingStrategies.CBFishing; sd.StatusCBFishing = StrategyStatus.Pending; //获得成交回报后再改变状态,避免重复执行 Thread orderThread = new Thread(new ParameterizedThreadStart(tc.OrderSender_CBFishing)); orderThread.IsBackground = true; orderThread.Start(entry); } //if ((sd.ShortPriceListed<data.AskPrice[4]) || (sd.ShortPriceListed>data.AskPrice[6]) ) //低于卖五或者高于卖七时撤单重挂,避免撤单过于频繁 // sd.ShortPriceListed = sd.AskPrices[4]; ////cancel and resend } else if (sd.StatusStockFishing != StrategyStatus.None) //此ticker需要跑StockFishing Strategy { } } # endregion } } } //极其耗时,轻易不要打开 //RecvDataReport(this, null); } else if (msg.MsgID == TDFMSGID.MSG_DATA_FUTURE) { //期货行情消息 TDFFutureData[] futureDataArr = msg.Data as TDFFutureData[]; foreach (TDFFutureData data in futureDataArr) { ; } return; } else if (msg.MsgID == TDFMSGID.MSG_DATA_INDEX) { //指数消息 TDFIndexData[] indexDataArr = msg.Data as TDFIndexData[]; foreach (TDFIndexData data in indexDataArr) { return; } } else if (msg.MsgID == TDFMSGID.MSG_DATA_TRANSACTION) { //逐笔成交 TDFTransaction[] transactionDataArr = msg.Data as TDFTransaction[]; foreach (TDFTransaction data in transactionDataArr) { //每一data变量包含最底层的一笔逐笔成交数据 lock (this.dataDict) { if (dataDict.Keys.Contains(data.Code)) { //数据获取部分 int timeStamp = Convert.ToInt32((double)data.Time / 1000 - 0.5); //去掉毫秒部分; if (timeStamp == 93524) { timeStamp = 93524; } int direction = 0; if (data.BSFlag == 66) { direction = 1; } else if (data.BSFlag == 83) { direction = -1; } int volume = data.Volume; double price = (double)data.Price / 10000; if (dataDict[data.Code].zbDataList.Count == 0) //第一次添加 { ZBTickData zbdata = new ZBTickData(); zbdata.timeStamp = timeStamp; if (direction == 1) { zbdata.volumeB = volume; zbdata.priceTotalB = price; zbdata.countB = 1; zbdata.priceB = zbdata.priceTotalB / (double)zbdata.countB;//计算该秒、买方向的平均价格 } else if (direction == -1) { zbdata.volumeS = volume; zbdata.priceTotalS = price; zbdata.countS = 1; zbdata.priceS = zbdata.priceTotalS / (double)zbdata.countS;//计算该秒、买方向的平均价格 } if ((zbdata.priceB > 0) && (zbdata.priceS > 0)) { zbdata.price = (zbdata.priceB + zbdata.priceS) / 2; } else { zbdata.price = (zbdata.priceB + zbdata.priceS); } zbdata.volume = zbdata.volumeB + zbdata.volumeS; if ((zbdata.volume == 0) || (zbdata.price == 0)) { continue; //空记录 } dataDict[data.Code].zbDataList.Add(zbdata); dataDict[data.Code].ZBFirstIndex = 0; dataDict[data.Code].ZBLastIndex = 0; } else { int currLastIndex = dataDict[data.Code].ZBLastIndex; if (dataDict[data.Code].zbDataList[currLastIndex].timeStamp == timeStamp) //同一时间戳存在,只需更新价格与成交量,不需插入新纪录 { ZBTickData zbdata = dataDict[data.Code].zbDataList[currLastIndex]; //取出字典中的元素并进行修改,由于是引用,对zbdata的修改会自动在字典中更新 if (direction == 1) { zbdata.priceTotalB = zbdata.priceTotalB + price; zbdata.countB = zbdata.countB + 1; zbdata.priceB = zbdata.priceTotalB / (double)zbdata.countB;//计算该秒、该方向的平均价格 zbdata.volumeB = zbdata.volumeB + volume; } else if (direction == -1) { zbdata.priceTotalS = zbdata.priceTotalS + price; zbdata.countS = zbdata.countS + 1; zbdata.priceS = zbdata.priceTotalS / (double)zbdata.countS;//计算该秒、该方向的平均价格 zbdata.volumeS = zbdata.volumeS + volume; } if ((zbdata.priceB > 0) && (zbdata.priceS > 0)) { zbdata.price = (zbdata.priceB + zbdata.priceS) / 2; } else { zbdata.price = (zbdata.priceB + zbdata.priceS); } zbdata.volume = zbdata.volumeB + zbdata.volumeS; dataDict[data.Code].zbDataList.RemoveAt(currLastIndex); dataDict[data.Code].zbDataList.Add(zbdata); } else //不存在此时间戳,需添加新纪录 { ZBTickData zbdata = new ZBTickData(); zbdata.timeStamp = timeStamp; if (direction == 1) { zbdata.volumeB = volume; zbdata.priceTotalB = price; zbdata.countB = 1; zbdata.priceB = zbdata.priceTotalB / (double)zbdata.countB;//计算该秒、买方向的平均价格 } else if (direction == -1) { zbdata.volumeS = volume; zbdata.priceTotalS = price; zbdata.countS = 1; zbdata.priceS = zbdata.priceTotalS / (double)zbdata.countS;//计算该秒、买方向的平均价格 } if ((zbdata.priceB > 0) && (zbdata.priceS > 0)) { zbdata.price = (zbdata.priceB + zbdata.priceS) / 2; } else { zbdata.price = (zbdata.priceB + zbdata.priceS); } zbdata.volume = zbdata.volumeB + zbdata.volumeS; //dataDict[data.Code].totalVolTillNow += zbdata.volume; if ((zbdata.volume == 0) || (zbdata.price == 0)) { continue; //空记录 } dataDict[data.Code].zbDataList.Add(zbdata); dataDict[data.Code].ZBLastIndex = dataDict[data.Code].ZBLastIndex + 1; } } /* * //数据获取部分 * ZBTickData zbdata = new ZBTickData(); * zbdata.timeStamp = Convert.ToInt32((double)data.Time / 1000); //去掉毫秒部分 * * //if (zbdata.timeStamp > 93850) { int i = 0; i++; } * * zbdata.price = (double)data.Price / 10000; * if (data.BSFlag == 66) * zbdata.direction = 1; * else if (data.BSFlag == 83) * zbdata.direction = -1; * else * zbdata.direction = 0; * zbdata.volume = data.Volume; * dataDict[data.Code].totalVolTillNow += zbdata.volume; * * dataDict[data.Code].zbDataList.Add(zbdata); * * if (dataDict[data.Code].zbDataList.Count == 1) //第一次添加 * { * dataDict[data.Code].ZBFirstIndex = 0; * dataDict[data.Code].ZBLastIndex = 0; * } * else * { * dataDict[data.Code].ZBLastIndex = dataDict[data.Code].ZBLastIndex + 1; * } */ } } //极其耗时,轻易不要打开 //RecvDataReport(this, null); } } else if (msg.MsgID == TDFMSGID.MSG_DATA_ORDER) { //逐笔委托 TDFOrder[] orderDataArr = msg.Data as TDFOrder[]; foreach (TDFOrder data in orderDataArr) { return; } } else if (msg.MsgID == TDFMSGID.MSG_DATA_ORDERQUEUE) { //委托队列 TDFOrderQueue[] orderQueueArr = msg.Data as TDFOrderQueue[]; foreach (TDFOrderQueue data in orderQueueArr) { return; } } }