Instrument
Instrument object represent a tradable contract such as Equity, Futures, Options. In any trading framework, Instrument class is key to represent the important properties such as InstrumentID, Exchange InstrumentID, Exchange Segment, Symbol name, Lot Size, Minimum tick Size, Contract multiplier etc. Every exchange or broker provides these details in structured file format or through an API called contract specifications or contract master. QXFinLib defines these Instrument class structure to represent your contracts in object form to be used in trading models. The technical analysis functionality uses Instrument class to derive various statistics based on TickSize, multiplier and other properties of Instrument class.
namespace QX.FinLib.Instrument
InstrumentBase is a base class of all instrument types and is abstract class.

User can create specific Instrument type object depending on needs and register it with InstrumentManager singleton object.
These instrument types holds some additional properties relevant to them i.e OptionsInstrument has addition properties like StrikePrice, OptionsType(CE, PE, CA, PA)
Following are some important instrument properties and must be assigned while define Instrument object:
| Properties | Data Type | Descriptions |
|---|---|---|
| InstrumentID | ulong | It is unique identifier across all instrument in system and it is automatically assigned based on two subkeys ExchangeSegment and Exchange InstrumentID i.e ExchangeSegment is NSECM(1) and exchange token id is 17903. The system assign InstrumentID a value 100000017903. |
| ExchangeSegment | Enumerated value | NSECM = 1 NSEFO = 2 NSECD = 3 etc |
| ExchangeInstrumentID | uint | The unique identifier provided by exchange for instrument |
| InstrumentType | Enumerated value | Futures =1 Options = 2 Spread = 4 Equity = 8 etc |
| Symbol | string | Example: Reliance, SBIN, ACC, APPL, EUR/USD |
| InstrumentName | string | For Equity segment it is usually same as Symbol name and for FO segment the name is in format BANKBARODA 25MAR21 FUT BANKNIFTY 18FEB21 PE 27700 |
| InstrumentDescription | string | User can provide any descriptive name i.e. BANKBARODA21MARFUT IGL21FEB760PE RELIANCE INDUSTRIES LTD |
| LowLimit | double | In some cases, exchanges provides a Low limit price below which order cannot be submitted. |
| HighLimit | double | In some cases, exchanges provides a High limit price above which order cannot be submitted. |
| QtyMultiplier | int | The quantity multiplier is used to get a traded value. In most cases it is 1 but some contracts are quoted at low denomination but traded value is higher, i.e MCX gold quoted price is 10 gram but traded unit is 1 kg. In this case the multiplier is 100. |
| LotSize | This is minimum shares or contract buy in one transaction. i.e. Nifty has lot size of 75. You can buy or sell in multiple of 75 |
|
| MinTickSize | Every exchange defines a minimum price movement of a tradable contract. In case of NSECM and NSEFO all major contracts have a minimum price movement also called tick size value as 0.05. For emini S&P 500 the tick size is 0.25 |
|
| BigPointValue | In some case quotes value is different than monetary value of a contract. In most cases the BPP is 1. For For emini S&P 500 the BPP is $12.50 per tick movement. This value is used to derive a contract value in monetary terms. | |
| PriceFormat | Enumerated value | How price can be formatted and represented. Default value is DECIMAL .i.e. DECIMAL THIRTYSECONDS HALFTHIRTYSECONDS QUARTERTHIRTYSECONDS etc. US treasury bond and futures are not traded in decimal price format but in fractional of par value |
| ISIN (EquityInstrument) | string | ISIN (International Securities Identification Number) is a unique identification number for a security across universe i.e. for RELIANCE the ISIN is INE002A01018 |
| ContractExpiration (FuturesInstrument, OptionsInstrument) | Datetime | The date on which contract expire. It is mainly a derivative property. |
| UnderlyingType (FuturesInstrument, OptionsInstrument) | Enumerated Value | Assign a underline type. Default is General General = 0 Commodity = 1 Currency = 2 Equity = 3 Index = 4 |
| OptionType (OptionsInstrument) | Enumerated Value | Valid for options contract CA = 1 (Call American) PA = 2 (Put American) CE = 1 (Call European) PE = 1 (Put European) |
| Strike Price (OptionsInstrument) | double | Valid for options contract A strike price is the set price at which a derivative contract can be bought or sold when it is exercised. |
Instrument Manager
This is singleton class and every instrument instance must be subscribe with Instrument manager. It is a container class for all subscribed instruments and provides access and filter criteria to identify individual or set of instruments meeting specific group creteria.
Every instrument instance must subscribe to InstrumrntManager as follows:
InstrumentManager.Instance.SubscribeInstrument(equityInstrument);
How to create instrument class and subscribe it with instrument manager?
Here we are taking an example of NSE exchange which provides to brokers an instrument definition files for each segments. Following is example to decode relevant information from exchange provided contract master files and create a Instrument class and register it with InstrumentManager.
For equity segment NSE provides security.txt file holding contract master definition and following is code snippet on how to parse the file and identify important attributes to create EquityInstrument object instances and subscribe it with Instrument Manager.
InstrumentManager.Instance.SubscribeInstrument(equityInstrument);
string securityFileName = "security.txt";
if (!File.Exists(securityFileName))
throw new Exception(securityFileName + " file does not exists.");
List<string> fileLines = new List<string>(File.ReadAllLines(securityFileName));
if (fileLines.Count <= 1)
throw new Exception(securityFileName + " file has no record.");
fileLines.RemoveAt(0);
foreach (string fileLine in fileLines)
{
string[] splittedString = fileLine.Split(Constant.PIPESEPERATOR);
if (splittedString.Count() < 54)
continue;
uint exchangeInstrumentID = Convert.ToUInt32(splittedString[0]);
char deleteFlag = Convert.ToChar(splittedString[51]);
if (deleteFlag == 'Y')
{
continue;
}
string symbol = splittedString[1];
string series = splittedString[2];
// EQ
if (series != "EQ")
continue;
ulong instrumentID = ExchangeCommon.GenerateUniqueTokenID(ExchangeSegment.NSECM, exchangeInstrumentID);
string highLowRange = splittedString[6];
string[] highLowPriceTokens = highLowRange.Split(new char[] { '-' });
int lowerPriceLimit = (int)(Convert.ToDouble(highLowPriceTokens[0]) * 100);
int higherPriceLimit = (int)(Convert.ToDouble(highLowPriceTokens[1]) * 100);
// The BoardLot qty is 1 for NSECM instruments
int boardLotQty = Convert.ToInt32(splittedString[19]);
// The TickSize is read as 5(Paisa) and interpreted as .05(INR)
int tickSize = Convert.ToInt32(splittedString[20]);
// The Tick Per point is evaluated as 20 if tickSize is .05
int tpp = (int)(1.0 / tickSize);
string instrumenDescription = splittedString[21];
string isin = splittedString[53];
EquityInstrument equityInstrument = new EquityInstrument(ExchangeSegment.NSECM, exchangeInstrumentID, symbol, symbol, instrumenDescription, boardLotQty, tpp);
equityInstrument.ISIN = isin;
equityInstrument.LowLimit = lowerPriceLimit * .01;
equityInstrument.HighLimit = higherPriceLimit * .01;
InstrumentManager.Instance.SubscribeInstrument(equityInstrument);
}
For Futures and Options segment NSE provides contract.txt file holding contract master definition and following is code snippet on how to parse the file and identify important attributes to create FuturesInstrument and optionsInstrument object instances and subscribe it with Instrument Manager.
string contractFileName = "contract.txt";
if (!File.Exists(contractFileName))
throw new Exception(contractFileName + " file does not exists.");
List<string> fileLines = new List<string>(File.ReadAllLines(contractFileName));
if(fileLines.Count <= 1)
throw new Exception(contractFileName + " file has no record.");
fileLines.RemoveAt(0);
foreach (string fileLine in fileLines)
{
string[] splittedString = fileLine.Split(Constant.PIPESEPERATOR);
if (splittedString.Count() < COLUMNCOUNT)
continue;
uint exchangeInstrumentID = Convert.ToUInt32(splittedString[TOKEN_INDEX]);
uint assetToken = Convert.ToUInt32(splittedString[ASSETTOKEN_INDEX]);
string instrumenType = splittedString[INSTRUMENTTYPE_INDEX]; // OPTIDX, FUTIDX, FUTSTK
string symbol = splittedString[SYMBOL_INDEX]; // BANKNIFTY
string series = splittedString[SERIES_INDEX]; // XX
string optionType = splittedString[OPTIONTYPE_INDEX];
DateTime contractExpiration = ExchangeCommon.GetDateTimeFromBaseDateElapsedSeconds( ExchangeSegment.NSEFO, (long)Convert.ToInt32(splittedString[EXPIRYDATE_INDEX]));
double strikePrice = Convert.ToInt32(splittedString[STRIKEPRICE_INDEX]) / ExchangeCommon.GetPriceDivisor(ExchangeSegment.NSEFO);
bool isFutures = true;
if (optionType == "XX" && strikePrice > 0)
continue;
if (instrumenType.StartsWith("OPT") && strikePrice <= 0)
continue;
OptionType optionTypeEnum = OptionType.NONE;
if (optionType == "CE")
{
optionTypeEnum = OptionType.CE;
isFutures = false;
}
else if (optionType == "PE")
{
optionTypeEnum = OptionType.PE;
isFutures = false;
}
else if (optionType == "XX")
isFutures = true;
else
continue;
string category = splittedString[CATEGORY_INDEX];
short caLevel = Convert.ToInt16(splittedString[CALEVEL_INDEX]);
ulong instrumentID = ExchangeCommon.GenerateUniqueTokenID(ExchangeSegment.NSEFO, exchangeInstrumentID);
short permittedToTrade = Convert.ToInt16(splittedString[PERMITTEDTOTRADE_INDEX]);
short issueRate = Convert.ToInt16(splittedString[ISSUERATE_INDEX]);
int minimumLotQuantity = Convert.ToInt32(splittedString[MINIMUMLOTQUANTITY_INDEX]);
int boardLotQty = Convert.ToInt32(splittedString[BOARDLOTQUANTITY_INDEX]);
double tickSize = (double)Convert.ToInt32(splittedString[TICKSIZE_INDEX]) / ExchangeCommon.GetPriceDivisor(ExchangeSegment.NSEFO);
if (tickSize <= 0)
{
continue;
}
// The Tick Per point is evaluated as 20 if tickSize is .05
int tpp = (int)(1.0/tickSize);
int lowPriceRange = Convert.ToInt32(splittedString[LOWPRICERANGE_INDEX]);
int highPriceRange = Convert.ToInt32(splittedString[HIGHPRICERANGE_INDEX]);
string instrumentDisplayName = splittedString[NAME_INDEX];
if (isFutures)
{
string instrumentName = InstrumentBase.GetInstrumnetName(symbol, contractExpiration);
FuturesInstrument futuresInstrument = new FuturesInstrument(ExchangeSegment.NSEFO,
exchangeInstrumentID,
symbol,
instrumentName,
instrumentDisplayName,
contractExpiration,
boardLotQty,
tpp);
futuresInstrument.LowLimit = lowPriceRange * .01;
futuresInstrument.HighLimit = highPriceRange * .01;
instrumentDict[instrumentID] = futuresInstrument;
InstrumentBase underlineInstrument = InstrumentManager.Instance.GetInstrument(ExchangeSegment.NSECM, assetToken);
if (underlineInstrument != null)
futuresInstrument.UnderlyingInstrument = underlineInstrument;
futuresInstrument.ExtendedPropertyList["UnderlyingExchangeInstrumentID"] = assetToken.ToString(); InstrumentManager.Instance.SubscribeInstrument(futuresInstrument);
}
else
{
string instrumentName = InstrumentBase.GetInstrumnetName(symbol, contractExpiration, optionTypeEnum, strikePrice);
OptionsInstrument optionInstrument = new OptionsInstrument(ExchangeSegment.NSEFO,
exchangeInstrumentID,
symbol,
instrumentName,
instrumentDisplayName,
contractExpiration,
optionTypeEnum,
strikePrice,
boardLotQty,
tpp);
optionInstrument.LowLimit = lowPriceRange * .01;
optionInstrument.HighLimit = highPriceRange * .01;
instrumentDict[instrumentID] = optionInstrument;
InstrumentBase underlineInstrument = InstrumentManager.Instance.GetInstrument(ExchangeSegment.NSECM, assetToken);
if (underlineInstrument != null)
optionInstrument.UnderlyingInstrument = underlineInstrument;
optionInstrument.ExtendedPropertyList["UnderlyingExchangeInstrumentID"] = assetToken.ToString();
InstrumentManager.Instance.SubscribeInstrument(futuresInstrument);
}
}
How to add custom properties in instrument object?
Instrument object provides an extended property container to add your custom properties that can be retrieved as when needed
FuturesInstrument futuresInstrument = InstrumentManager.Instance.Getinstrument(Exchangesegment.NSECM, 10222);
futuresInstrument.ExtendedPropertyList["UnderlyingExchangeInstrumentID"] = "23332";
futuresInstrument.ExtendedPropertyList["AssetClass"] = "Comodities";
string assetClass = futuresInstrument.ExtendedPropertyList["AssetClass"]
Accessing Instrument or set of Instruments from Instrument Manager
InstrumentManager is singleton container of all subscribed instruments and allow a single point access of Instrument instance
// Accessing instrument using Exchange Segment and Exchange Instrument ID
FuturesInstrument futuresinstrument1 = (FuturesInstrument)InstrumentManager.Instance.GetInstrument(ExchangeSegment.NSEFO, 48548);
// Accessing instrument using Exchange Segment and Instrument Name
FuturesInstrument futuresinstrument2 = (FuturesInstrument)InstrumentManager.Instance.GetInstrument(ExchangeSegment.NSEFO, "BANKNIFTY 25MAR21 FUT");
// Accessing instrument using InstrumentID
FuturesInstrument futuresinstrument3 = (FuturesInstrument)InstrumentManager.Instance.GetInstrument(200000048548);
// Accessing all call and put options list of BankNifty with specific expiry month
string symbolName = "BANKNIFTY";
DateTime contractExpiry = new DateTime(2021, 03, 25);
List<OptionsInstrument> callOptionsList = InstrumentManager.Instance.GetAllCallOptionsInstrumentForSymbolAndExpiry(symbolName, contractExpiry);
List<OptionsInstrument> putOptionsList = InstrumentManager.Instance.GetAllPutOptionsInstrumentForSymbolAndExpiry(symbolName, contractExpiry);
// Accessing all call and put options list of BankNifty
List<OptionsInstrument> bankNiftyOptionsList = InstrumentManager.Instance.GetAllOptionsInstrumenttForSymbol(symbolName);
// Apply linq query to filter call options with given expiry month
List<OptionsInstrument> callOptionsListX = bankNiftyOptionsList.Where(iterator => iterator.Symbol.ToUpper() == symbolName.ToUpper() &&
(iterator.OptionType == OptionType.CE || iterator.OptionType == OptionType.CA) &&
iterator.StrikePrice > 0 &&
iterator.ContractExpiration.Date == contractExpiry.Date). OrderBy(iterator => iterator.ContractExpiration).ThenBy(iterator => iterator.StrikePrice).ToList();
Instrument object is serializable and deserializable using a Protobuf?
All instrument types object are seriazable to byte array and subsequently deserialize byte array to object using a protobuf serialization deserialization mechanism. This is helpful in case you want to preserve the state of Instrument in some binary file or database.
Using ProtoBuf;
using Newtonsoft.Json;
using QX.FinLib.Common;
using QX.FinLib.Instrument;
FuturesInstrument futuresinstrument = (FuturesInstrument)InstrumentManager.Instance.GetInstrument(ExchangeSegment.NSEFO, 48548);
// Serialize to byte stream
byte[] bData = ProtoSerialize<FuturesInstrument>(futuresinstrument);
// Deserialzie from byte stream to object
FuturesInstrument futuresinstrumentX = ProtoDeserialize<FuturesInstrument>(bData);
public byte[] ProtoSerialize<T>(T record) where T : class
{
if (null == record) return null;
try
{
using (var stream = new MemoryStream())
{
Serializer.Serialize(stream, record);
return stream.ToArray();
}
}
catch (Exception exp)
{
// Log error
throw exp;
}
}
public T ProtoDeserialize<T>(byte[] data) where T : class
{
if (null == data) return null;
try
{
using (var stream = new MemoryStream(data))
{
return Serializer.Deserialize<T>(stream);
}
}
catch (Exception exp)
{
// Log error
throw exp;
}
}