Where to get realixed volumes on Bid x Ask ?
Where to get realixed volumes on Bid x Ask ?
15 Nov 2019, 15:52
Hi All,
im trying to implement a custom order flow indicator using the MarketDepth api. My assumption was following.
Store previous DoM state;
Compare current DoM with previous
- condition ( oldPrice < currentPrice)
- find the price gaps between new Bid price and Last Bid price
- add volumes on respective price levels into footprint
- condition ( oldPrice == currentPrice)
- add to footprint currentVolume - previousVolume
same logic for bid, ask
But of course the solution is completely wrong. So i would appreciate any thoughts about how to do it . Or maybe point me to some similar example.
Thanks a lot.
using System; using System.Collections.Generic; using System.Text; using cAlgo.API; using cAlgo.API.Collections; namespace cAlgo { [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AutoRescale = false, AccessRights = AccessRights.None)] public class OrderFlow : Indicator { private double high; private double low; private double lastPrice = 0; private bool isLong; private DOM lastDOM; private DOM currentDOM; private int lastBarIndex = 0; private MarketDepth marketDepth; private List<MarketDepthEntry> lastAsks; private List<MarketDepthEntry> lastBids; public override void Calculate(int index) { high = MarketSeries.High[index]; low = MarketSeries.Low[index]; isLong = lastPrice < MarketSeries.Close[index] ? true : false; lastPrice = MarketSeries.Close[index]; if (IsLastBar && index != lastBarIndex) { lastBarIndex = index; onNewBar(); } } private void onNewBar() { Print("New bar event"); lastDOM = currentDOM; currentDOM = new DOM(this); } protected override void Initialize() { currentDOM = new DOM(this); // Get Market Depth marketDepth = MarketData.GetMarketDepth(Symbol); // subscribe to event Updated marketDepth.Updated += MarketDepthUpdated; } void MarketDepthUpdated() { // Print("Last price " + last + " direction " + (isLong ? "Long" : "Short")); if(lastAsks != null && lastBids != null) { //Print("+++previous asks"); //printEntries(lastAsks); //Print("new asks"); //printEntries(marketDepth.AskEntries); int lastAskIdx = 0; double cumVolume = 0; while (lastAsks.Count > 0 && lastAskIdx < lastAsks.Count && marketDepth.AskEntries.Count > 0 && lastAsks[lastAskIdx].Price <= marketDepth.AskEntries[0].Price) { var ask = lastAsks[lastAskIdx]; double askVolume = Math.Round(ask.VolumeInUnits / 100000.0, 2); double currentAskVolume = Math.Round(marketDepth.AskEntries[0].VolumeInUnits / 100000.0, 2); double askPrice = Math.Round(ask.Price, 5); double askPriceCurrent = Math.Round(marketDepth.AskEntries[0].Price, 5); //Print("++diff price " + askPrice); if (lastAsks[lastAskIdx].Price == marketDepth.AskEntries[0].Price) { askVolume = Math.Abs(askVolume - currentAskVolume); } currentDOM.AddAsk(askPrice, askVolume); lastAskIdx++; } Print("---previous bids"); printEntries(lastAsks); Print("new bids"); printEntries(marketDepth.AskEntries); int lastBidIdx = 0; while (lastBids.Count > 0 && lastBidIdx < lastBids.Count && marketDepth.BidEntries.Count > 0 && lastBids[lastBidIdx].Price >= marketDepth.BidEntries[0].Price) { var bid = lastBids[lastBidIdx]; double bidVolume = Math.Round(bid.VolumeInUnits / 100000.0, 2); double currentBidVolume = Math.Round(marketDepth.BidEntries[0].VolumeInUnits / 100000.0, 2); double bidPrice = Math.Round(bid.Price, 5); double bidPriceCurrent = Math.Round(marketDepth.BidEntries[0].Price, 5); if (lastBids[lastBidIdx].Price == marketDepth.BidEntries[0].Price) { bidVolume = Math.Abs(bidVolume - currentBidVolume); } Print("----diff price " + bidPrice + " " + bidVolume); currentDOM.AddBid(bidPrice, bidVolume); lastBidIdx++; } } lastAsks = copyMarketDepthEntries(marketDepth.AskEntries); lastBids = copyMarketDepthEntries(marketDepth.BidEntries); ChartObjects.DrawText("FP", currentDOM.ToString(), StaticPosition.TopLeft, Colors.DarkBlue); Print(currentDOM.ToString()); Print("-----"); } private List<MarketDepthEntry> copyMarketDepthEntries(IReadonlyList<MarketDepthEntry> entries) { List<MarketDepthEntry> list = new List<MarketDepthEntry>(); foreach(var entry in entries) { list.Add(entry); } return list; } private void printEntries(List<MarketDepthEntry> list) { if (list == null) return; foreach(var entry in list) { Print(entry.Price + " -> " + Math.Round(entry.VolumeInUnits / 100000.0, 2)); } } private void printEntries(IReadonlyList<MarketDepthEntry> list) { if (list == null) return; foreach (var entry in list) { Print(entry.Price + " -> " + Math.Round(entry.VolumeInUnits / 100000.0, 2)); } } public void PrintToLog(string message) { Print(message); } } public class DOM { private OrderFlow _indicator { get; set; } private SortedDictionary<double, OFEntry> lastBidAsks = new SortedDictionary<double, OFEntry>(); private SortedDictionary<double, OFEntry> BidAsks = new SortedDictionary<double, OFEntry>(); public DOM(OrderFlow indicator) { _indicator = indicator; } public void AddBid(double price, double volume) { OFEntry ofEntry = getEntry(price); ofEntry.Bid += volume; } public void AddAsk(double price, double volume) { OFEntry ofEntry = getEntry(price); ofEntry.Ask += volume; } public OFEntry getEntry(double price) { if (BidAsks.ContainsKey(price)) { return BidAsks[price]; } else { OFEntry entry = new OFEntry { Ask = 0, Bid = 0 }; BidAsks.Add(price, entry); return entry; } } public override string ToString() { var sb = new StringBuilder(); foreach (KeyValuePair<double, OFEntry> entry in BidAsks) { sb.Insert(0, entry.Key + " " + entry.Value + ",\n "); } return sb.ToString(); } } public class OFEntry { public double Bid { get; set; } public double Ask { get; set; } public override string ToString() { return "[" + Ask + " x " + Bid + "]"; } } }