Skip to content

Instantly share code, notes, and snippets.

@cameronfletcher
Last active April 29, 2020 08:41
Show Gist options
  • Save cameronfletcher/2180ddc4a484143c1601ae33f7a4a4ce to your computer and use it in GitHub Desktop.
Save cameronfletcher/2180ddc4a484143c1601ae33f7a4a4ce to your computer and use it in GitHub Desktop.
Alexandria Product Universe
namespace Alexandria
{
using System;
using System.Collections.Generic;
public sealed class InstrumentService
{
public static class Venues
{
public const string Unspecified = "__unspecified";
public const string B2C2 = "b2c2";
public const string Binance = "binance";
public const string Bitfinex = "bitfinex";
public const string Bitmart = "bitmart";
public const string Bitmex = "bitmex";
public const string Bitstamp = "bitstamp";
public const string Bittrex = "bittrex";
public const string Blackcube = "blackcube";
public const string CEXIO = "cex.io";
public const string Cryptofacilities = "cryptofacilities";
public const string GBX = "gbx";
public const string Kraken = "kraken";
public const string KrakenFutures = "krakenfutures";
public const string Kucoin = "kucoin";
public const string LykkeInvest = "lykke.invest";
public const string LykkePocket = "lykke.pocket";
public const string LykkeTokens = "lykke.tokens";
public const string LykkeX = "lykke";
public const string InteractiveBrokers = "interactivebrokers";
}
private static readonly Dictionary<string, Dictionary<string, string>> Lookup = new Dictionary<string, Dictionary<string, string>>
{
{
Venues.Unspecified,
new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
{ "ADA", "currency.crypto.ADA" },
{ "ATOM", "currency.crypto.ATOM" },
{ "AUD", "currency.fiat.AUD" },
{ "BAT", "currency.crypto.BAT" },
{ "BCD", "currency.crypto.BCD" },
{ "BCH", "currency.crypto.BCH" },
{ "BCN", "currency.crypto.BCN" },
{ "BEAR", "token.lykke.BEAR" },
{ "BMX", "currency.crypto.BMX" },
{ "BNB", "currency.crypto.BNB" },
{ "BTC", "currency.crypto.BTC" },
{ "BTG", "currency.crypto.BTG" },
{ "BTT", "currency.crypto.BTT" },
{ "CAD", "currency.fiat.CAD" },
{ "CHF", "currency.fiat.CHF" },
{ "CZK", "currency.fiat.CZK" },
{ "DASH", "currency.crypto.DASH" },
{ "DCR", "currency.crypto.DCR" },
{ "DENT", "token.crypto.DENT" },
{ "DKK", "currency.fiat.DKK" },
{ "DOGE", "currency.crypto.DOGE" },
{ "EOS", "currency.crypto.EOS" },
{ "ETC", "currency.crypto.ETC" },
{ "ETH", "currency.crypto.ETH" },
{ "EUR", "currency.fiat.EUR" },
{ "GAS", "currency.crypto.GAS" },
{ "GBP", "currency.fiat.GBP" },
{ "Germany30", "token.crypto.Germany30" },
{ "HKD", "currency.fiat.HKD" },
{ "HMC", "token.crypto.HMC" },
{ "HT", "currency.crypto.HT" },
{ "HUF", "currency.fiat.HUF" },
{ "ICX", "currency.crypto.ICX" },
{ "ILS", "currency.fiat.ILS" },
{ "IOTA", "currency.crypto.IOTA" },
{ "JPY", "currency.fiat.JPY" },
{ "KIN", "currency.crypto.KIN" },
{ "LINK", "currency.crypto.LINK" },
{ "LKK", "token.lykke.LKK" },
{ "LKK1Y", "token.lykke.LKK1Y" },
{ "LKK2Y", "token.lykke.LKK2Y" },
{ "LSK", "currency.crypto.LSK" },
{ "LTC", "currency.crypto.LTC" },
{ "LYCI", "token.lykke.LYCI" },
{ "MIOTA", "currency.crypto.MIOTA" },
{ "MKR", "currency.crypto.MKR" },
{ "MXN", "currency.fiat.MXN" },
{ "NANO", "currency.crypto.NANO" },
{ "NEO", "currency.crypto.NEO" },
{ "NOK", "currency.fiat.NOK" },
{ "NOVN", "stock.fiat.NOVN" },
{ "NZD", "currency.fiat.NZD" },
{ "OMG", "currency.crypto.OMG" },
{ "ONG", "currency.crypto.ONG" },
{ "ONT", "currency.crypto.ONT" },
{ "PLN", "currency.fiat.PLN" },
{ "PLYCI", "token.lykke.PLYCI" },
{ "QTUM", "currency.crypto.QTUM" },
{ "REP", "currency.crypto.REP" },
{ "RRB", "token.crypto.RRB" },
{ "RUB", "currency.fiat.RUB" },
{ "SEK", "currency.fiat.SEK" },
{ "SGD", "currency.fiat.SGD" },
{ "SHEELA", "token.crypto.SHEELA" },
{ "SHORTLYCItest", "token.lykke.SHORTLYCItest" },
{ "SLR", "currency.crypto.SLR" },
{ "SLYCI", "token.lykke.SLYCI" },
{ "TRX", "currency.crypto.TRX" },
{ "TRY", "currency.fiat.TRY" },
{ "UBSG", "stock.fiat.UBSG" },
{ "USD", "currency.fiat.USD" },
{ "USDT", "currency.crypto.USDT" },
{ "VET", "currency.crypto.VET" },
{ "VTHO", "currency.crypto.VTHO" },
{ "WAVES", "currency.crypto.WAVES" },
{ "WIN", "currency.crypto.WIN" },
{ "XAG", "token.commodity.XAG" },
{ "XAU", "token.commodity.XAU" },
{ "XEM", "currency.crypto.XEM" },
{ "XLM", "currency.crypto.XLM" },
{ "XMR", "currency.crypto.XMR" },
{ "XPD", "token.commodity.XPD" },
{ "XPT", "token.commodity.XPT" },
{ "XRP", "currency.crypto.XRP" },
{ "XTZ", "currency.crypto.XTZ" },
{ "ZAR", "currency.fiat.ZAR" },
{ "ZEC", "currency.crypto.ZEC" },
{ "ZRX", "currency.crypto.ZRX" },
}
},
{
Venues.Bitmex,
new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
{ "ADAH20", "future.crypto.ADABTC_20200327" },
{ "XBTH20", "future.crypto.XBTUSD_20200327" },
}
},
{
Venues.Cryptofacilities,
new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
{ "FI_ETHUSD_200327", "future.crypto.ETHUSD_20200327" },
{ "FI_LTCUSD_200327", "future.crypto.LTCUSD_20200327" },
}
},
{
Venues.Kraken,
new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
{ "KFEE", "currency.crypto.FEE" },
{ "XETC", "currency.crypto.ETC" },
{ "XETH", "currency.crypto.ETH" },
{ "XLTC", "currency.crypto.LTC" },
{ "XXBT", "currency.crypto.BTC" },
{ "XXLM", "currency.crypto.XLM" },
{ "ZEUR", "currency.fiat.EUR" },
{ "ZUSD", "currency.fiat.USD" },
{ "XTZ.S", "currency.crypto.XTZ" },
{ "XXMR", "currency.crypto.XMR" },
{ "XXRP", "currency.crypto.XRP" },
}
},
{
Venues.KrakenFutures,
new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
{ "FI_BCHUSD_200327", "future.crypto.BCHUSD_20200327" },
{ "FI_ETHUSD_200327", "future.crypto.ETHUSD_20200327" },
{ "FI_LTCUSD_200327", "future.crypto.LTCUSD_20200327" },
{ "FI_XBTUSD_200327", "future.crypto.XBTUSD_20200327" },
{ "FI_XRPUSD_200327", "future.crypto.XRPUSD_20200327" },
}
},
{
Venues.LykkeX,
new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
{ "OTC BC", "token.crypto.OTCBC" },
}
},
};
public Instrument GetIntrument(string tenant, string symbol) => this.GetIntrument(tenant, symbol, Venues.Unspecified);
public Instrument GetIntrument(string tenant, string symbol, string venue)
{
// first try the custom venues
if (Lookup.TryGetValue(venue, out var map) && map.TryGetValue(symbol, out var instrument))
{
return instrument;
}
// default to unspecified
return venue == Venues.Unspecified ? null : this.GetIntrument(symbol, Venues.Unspecified);
}
public Instrument GetIntrumentById(string tenant, string instrumentId) => new Instrument(instrumentId);
public bool IsKnownInstrument(string tenant, string instrumentId)
{
try
{
return new Instrument(instrumentId).Name != "Unknown";
}
catch (ArgumentException)
{
return false;
}
}
public sealed class Instrument
{
private static readonly Dictionary<string, string> Names = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
{ "currency.crypto.ADA", "Cardano" },
{ "currency.crypto.ATOM", "Cosmos" },
{ "currency.crypto.BAT", "Basic Attention Token" },
{ "currency.crypto.BCD", "Bitcoin Diamond" },
{ "currency.crypto.BCH", "Bitcoin Cash" },
{ "currency.crypto.BCN", "Bytecoin" },
{ "currency.crypto.BMX", "BitMart Token" },
{ "currency.crypto.BNB", "Binance Coin" },
{ "currency.crypto.BTC", "Bitcoin" },
{ "currency.crypto.BTG", "Bitcoin Gold" },
{ "currency.crypto.BTT", "BitTorrent" },
{ "currency.crypto.DASH", "Dash" },
{ "currency.crypto.DCR", "Decred" },
{ "currency.crypto.DOGE", "Dogecoin" },
{ "currency.crypto.EOS", "Eos" },
{ "currency.crypto.ETC", "Ethereum Classic" },
{ "currency.crypto.ETH", "Ethereum" },
{ "currency.crypto.FEE", "Kranken Coin (Fee)" },
{ "currency.crypto.GAS", "Gas" },
{ "currency.crypto.HT", "Huobi Token" },
{ "currency.crypto.ICX", "Icon" },
{ "currency.crypto.IOTA", "Miota" },
{ "currency.crypto.KIN", "Kin" },
{ "currency.crypto.LINK", "Chainlink" },
{ "currency.crypto.LSK", "Lisk" },
{ "currency.crypto.LTC", "Litecoin" },
{ "currency.crypto.MIOTA", "IOTA" },
{ "currency.crypto.MKR", "Maker" },
{ "currency.crypto.NANO", "Nano" },
{ "currency.crypto.NEO", "NEO" },
{ "currency.crypto.OMG", "OmiseGO" },
{ "currency.crypto.ONG", "Ong (fuel)" },
{ "currency.crypto.ONT", "Ontology" },
{ "currency.crypto.QTUM", "Qtum" },
{ "currency.crypto.REP", "Augur" },
{ "currency.crypto.SLR", "SLR" },
{ "currency.crypto.TRX", "Tron" },
{ "currency.crypto.USDT", "Tether" },
{ "currency.crypto.VET", "VeChain" },
{ "currency.crypto.VTHO", "Vethor Token" },
{ "currency.crypto.WAVES", "Waves" },
{ "currency.crypto.WIN", "Wink" },
{ "currency.crypto.XEM", "NEM" },
{ "currency.crypto.XLM", "Stellar" },
{ "currency.crypto.XMR", "Monero" },
{ "currency.crypto.XRP", "Ripple" },
{ "currency.crypto.XTZ", "Tezos" },
{ "currency.crypto.ZEC", "Zcash" },
{ "currency.crypto.ZRX", "0x" },
{ "currency.fiat.AUD", "Australian Dollar" },
{ "currency.fiat.CAD", "Canadian Dollar" },
{ "currency.fiat.CHF", "Swiss Franc" },
{ "currency.fiat.CZK", "Czech Koruna" },
{ "currency.fiat.DKK", "Danish Krone" },
{ "currency.fiat.EUR", "Euro" },
{ "currency.fiat.GBP", "Pound Sterling" },
{ "currency.fiat.HKD", "Hong Kong Dollar" },
{ "currency.fiat.HUF", "Hungarian Forint" },
{ "currency.fiat.ILS", "Israeli New Shekel" },
{ "currency.fiat.JPY", "Japanese Yen" },
{ "currency.fiat.MXN", "Mexican Peso" },
{ "currency.fiat.NOK", "Norwegian Krone" },
{ "currency.fiat.NZD", "New Zealand Dollar" },
{ "currency.fiat.PLN", "Poland Zloty" },
{ "currency.fiat.RUB", "Russian Ruble" },
{ "currency.fiat.SEK", "Swedish Krona" },
{ "currency.fiat.SGD", "Singapore Dollar" },
{ "currency.fiat.TRY", "Turkish Lira" },
{ "currency.fiat.USD", "United States Dollar" },
{ "currency.fiat.ZAR", "South African Rand" },
{ "currency.smart.CHF", "Swiss Franc" },
{ "currency.smart.EUR", "Euro" },
{ "currency.smart.GBP", "Pound Sterling" },
{ "currency.smart.USD", "United States Dollar" },
{ "currency.simple.CHF", "Swiss Franc" },
{ "currency.simple.EUR", "Euro" },
{ "currency.simple.GBP", "Pound Sterling" },
{ "currency.simple.USD", "United States Dollar" },
{ "future.crypto.ADABTC_20200327", "ADA Future" },
{ "future.crypto.BCHUSD_20200327", "BCH Future" },
{ "future.crypto.ETHUSD_20200327", "ETH Future" },
{ "future.crypto.LTCUSD_20200327", "LTC Future" },
{ "future.crypto.XBTUSD_20200327", "BTC Future" },
{ "future.crypto.XRPUSD_20200327", "XRP Future" },
{ "index.crypto.BEAR", "BEAR" },
{ "index.crypto.LYCI", "LyCI" },
{ "index.crypto.PLYCI", "PayLyCI" },
{ "index.crypto.SHORTLYCItest", "SHORTLYCItest" },
{ "index.crypto.SLYCI", "SmartLyCI" },
{ "option.crypto.BTCUSD_CALL_7000_20200327", "BTC Option" },
{ "security.tokenized.LYNOVA", "Novartis Share" },
{ "stock.fiat.NOVN", "Novartis Share" },
{ "stock.fiat.UBSG", "UBS Share" },
{ "token.commodity.XAG", "Silver" },
{ "token.commodity.XAU", "Gold" },
{ "token.commodity.XPD", "PetroDollar" },
{ "token.commodity.XPT", "Platinum" },
{ "token.crypto.DENT", "Dent" },
{ "token.crypto.Germany30", "Germany30" },
{ "token.crypto.HMC", "HarmonyCoin" },
{ "token.crypto.OTCBC", "OTC BC" },
{ "token.crypto.RRB", "RRB" },
{ "token.crypto.SHEELA", "SHEELA" },
{ "token.lykke.BEAR", "BEAR" },
{ "token.lykke.LKK", "LKK" },
{ "token.lykke.LKK1Y", "LKK1Y" },
{ "token.lykke.LKK2Y", "LKK2Y" },
{ "token.lykke.LYCI", "LyCI" },
{ "token.lykke.PLYCI", "PayLyCI" },
{ "token.lykke.SHORTLYCItest", "SHORTLYCItest" },
{ "token.lykke.SLYCI", "SmartLyCI" },
};
public Instrument(string id)
{
_ = id ?? throw new ArgumentNullException(nameof(id));
if (string.IsNullOrWhiteSpace(id))
{
throw new ArgumentException($"Invalid instrument ID: '{id}'.", nameof(id));
}
var components = id.Split('.');
if (components.Length < 2 || components.Length > 3)
{
throw new ArgumentException($"Invalid instrument ID: '{id}'.", nameof(id));
}
this.Type = components[0].ToLowerInvariant();
if (string.IsNullOrWhiteSpace(this.Type))
{
throw new ArgumentException($"Invalid instrument ID: '{id}'.", nameof(id));
}
var next = components[1];
if (string.IsNullOrWhiteSpace(next))
{
throw new ArgumentException($"Invalid instrument ID: '{id}'.", nameof(id));
}
if (components.Length == 2)
{
this.Symbol = next.ToUpperInvariant();
}
else
{
this.SubType = next.ToLowerInvariant();
this.Symbol = components[2].ToUpperInvariant();
if (string.IsNullOrWhiteSpace(this.Symbol))
{
throw new ArgumentException($"Invalid instrument ID: '{id}'.", nameof(id));
}
}
this.Id = string.IsNullOrEmpty(this.SubType) ? string.Join('.', this.Type, this.Symbol) : string.Join('.', this.Type, this.SubType, this.Symbol);
this.Name = Names.TryGetValue(id, out var name) ? name : "Unknown";
}
public string Id { get; }
public string Name { get; }
public string Type { get; }
public string SubType { get; }
public string Symbol { get; }
public bool Equals(Instrument other) => this.Id == other?.Id;
public override bool Equals(object obj) => obj is Instrument instrument && this.Equals(instrument);
public override int GetHashCode() => this.Id.GetHashCode();
public static bool operator ==(Instrument x, Instrument y) => x is object && x.Equals(y) || x is null && y is null;
public static bool operator !=(Instrument x, Instrument y) => !(x == y);
public override string ToString() => this.Id;
public static implicit operator string(Instrument instrument) => instrument?.ToString();
public static implicit operator Instrument(string value)
{
try
{
return new Instrument(value);
}
catch (ArgumentException ex)
{
throw new InvalidCastException($"Cannot implicitly convert '{value}' to '{nameof(Instrument)}'.\r\n{ex.Message}", ex);
}
}
}
}
}
@cameronfletcher
Copy link
Author

cameronfletcher commented Apr 7, 2020

Usage:

var instrumentService = new Alexandria.InstrumentService();
var instrument = instrumentService.GetIntrument("tenant", "KFEE", InstrumentUniverse.Venue.Kraken);

Should give you something like this:

Also, if you want to get data from currency.crypto.FEE, then you can get an instrument in this manner:

var instrument = new InstrumentService.Instrument("currency.crypto.FEE");

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment