Where to get realixed volumes on Bid x Ask ?

Created at 15 Nov 2019, 15:52
How’s your experience with the cTrader Platform?
Your feedback is crucial to cTrader's development. Please take a few seconds to share your opinion and help us improve your trading experience. Thanks!
MA

marek.balla

Joined 13.11.2019

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 + "]";
        }
    }
}

 


@marek.balla