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