Oanda’s Order Book

This indicator uses the Oanda’s OrderBook API to draw a set of horizontal lines, each one representing the number of trapped open positions at a given price. More specifically, above the current price it shows the open buy orders and below the current price it shows the open sell orders.

Input Parameters

  • Height: indicates how many pips above and below the current price it should draw.
  • Width: represents the scale of the drawn lines.
  • Token: this is a token string required to use Oanda’s API. To get one, you must register for either a free demo or a live account. More info at https://developer.oanda.com/rest-live-v20/introduction/

Screenshots

orderbook

Code

using System;
using System.Net;
using cAlgo.API;
using cAlgo.API.Internals;
using cAlgo.API.Indicators;
using cAlgo.Indicators;
using Newtonsoft.Json.Linq;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Text;

namespace cAlgo
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.Internet)]
    public class OandaOrderBook : Indicator
    {
        [Parameter(DefaultValue = 200)]
        public int Height { get; set; }

        [Parameter(DefaultValue = 30)]
        public int Width { get; set; }
        
        [Parameter(DefaultValue = "")]
        public string Token { get; set; }

        private static string apiurl = "https://api-fxpractice.oanda.com/v3/instruments/";

        private int line_index = 0;
        //private DateTime orderbook_dt;

        protected override void Initialize()
        {
            LoadOrderBook();
        }

        private void LoadOrderBook()
        {
            using (WebClient webClient = new WebClient())
            {
                webClient.Headers.Add("Content-Type", "application/json");
                webClient.Headers.Add("Authorization", "Bearer " + Token);
                webClient.Headers.Add("Accept-Encoding", "gzip");

                byte[] data = webClient.DownloadData(apiurl + Symbol.Name.Insert(3, "_") + "/positionBook");

                using (var compressedStream = new MemoryStream(data))
                    using (var unzipStream = new GZipStream(compressedStream, CompressionMode.Decompress))
                        using (var resultStream = new MemoryStream())
                        {
                            unzipStream.CopyTo(resultStream);
                            var json = JObject.Parse(Encoding.ASCII.GetString(resultStream.ToArray()));

                            DrawOrderBook(json);
                        }
            }
        }

        private void DrawOrderBook(JObject json)
        {
            int index = Bars.OpenTimes.GetIndexByTime(Bars.OpenTimes.LastValue) + 20;
            double refprice = double.Parse(json["positionBook"]["price"].ToString().Replace(".", ","));
            var buckets = json["positionBook"]["buckets"];

            foreach (var bucket in buckets)
            {
                double price = double.Parse(bucket["price"].ToString().Replace(".", ","));
                double count = Width * double.Parse(bucket[price > refprice ? "longCountPercent" : "shortCountPercent"].ToString().Replace(".", ","));

                if (Math.Abs(price - refprice) / Symbol.PipSize < Height)
                {
                    int startindex = index - (int)Math.Floor(count);
                    Chart.DrawTrendLine("bucket" + line_index++, startindex, price, index, price, price > refprice ? Color.Blue : Color.Red, 1);
                }
            }
        }

        public override void Calculate(int index)
        {
        }
    }
}

You Might Also Like

Leave a Reply

Your email address will not be published. Required fields are marked *