The Blitz Trading System Help Guide is your reference to product features descriptions and detailed instructional content on their use. Instructional content is delivered via text, images and video where applicable. This Help Guide also serves as a reference to Blitz strategy development API used in the development of automated trading systems (strategies), exchange adapters and trading tools.
BlitzTrader is next generation; high performance fully automated trading system for rapid development, testing and deployment of simple to sophisticated trading strategies into constantly evolving financial marketplace. It is designed to increase trading efficiency and profitability by capturing alpha. All aspects of trading, such as obtaining market prices, analyzing price patterns, making trading decisions, placing orders, monitoring order executions, and controlling the risk are automated according to the user preferences. The central idea behind BlitzTrader is to completely remove the emotions from trading, so that the trading system can systematically and consistently follow a predefined set of trading and risk management rules.
The BlitzTrader API(Application Programming Interface) are C# libraries that can be integrated to any .NET based application and enables developer to create a server based algorithmic trading strategies, exchange/broker connectors and customize client side trading UI interface to seamlessly integrate with BlitzTrader platform and provides a real-time trading capabilities. The library makes it simple to integrate BlitzTrader service in your .NET project. Developers can leverage nearly any .NET language they prefer in building necessary exchange/broker integration connections and algorithmic trading strategies. API provides the ability for trading application development to extend the solutions capabilities. In addition BlitzTrader API provides rich set of methods that is useful for price analytics. For example: Technical analysis, Options pricing etc. The BlitzTrader environment available to the user can also be valuable asset in constructing custom financial tools like market data analysis tool, FIX connectivity adapter and FIX analysis tools etc. BlitzTrader API is built on top of Microsoft .NET platform, so strategies can be developed in any .NET supported language (C#, VB.NET, C++, J#...) and is fully integrated with Visual Studio platform through a set of ready-to-go templates. The trading API of BlitzTrader is used to develop automate trading strategies is driven by real-time events. Furthermore, this guide assumes some basic knowledge of the C# programming language.
The topic provides the high level overview of the basic BltzTrader API product architecture. The BlitzTrader platform relied on a modular software infrastructure, designed to enable flexible usage of BlitzTrader technologies and features. The following diagram illustrates the logical layout of different components of Blitz Trading System.
The Blitz Trading System Help Guide is your reference to product features descriptions and detailed instructional content on their use. Instructional content is delivered via text, images and video where applicable. This Help Guide also serves as a reference to Blitz strategy development API used in the development of automated trading systems (strategies), exchange adapters and trading tools.
BlitzTrader is next generation; high performance fully automated trading system for rapid development, testing and deployment of simple to sophisticated trading strategies into constantly evolving financial marketplace. It is designed to increase trading efficiency and profitability by capturing alpha. All aspects of trading, such as obtaining market prices, analyzing price patterns, making trading decisions, placing orders, monitoring order executions, and controlling the risk are automated according to the user preferences. The central idea behind BlitzTrader is to completely remove the emotions from trading, so that the trading system can systematically and consistently follow a predefined set of trading and risk management rules.
The BlitzTrader API(Application Programming Interface) are C# libraries that can be integrated to any .NET based application and enables developer to create a server based algorithmic trading strategies, exchange/broker connectors and customize client side trading UI interface to seamlessly integrate with BlitzTrader platform and provides a real-time trading capabilities. The library makes it simple to integrate BlitzTrader service in your .NET project. Developers can leverage nearly any .NET language they prefer in building necessary exchange/broker integration connections and algorithmic trading strategies. API provides the ability for trading application development to extend the solutions capabilities. In addition BlitzTrader API provides rich set of methods that is useful for price analytics. For example: Technical analysis, Options pricing etc. The BlitzTrader environment available to the user can also be valuable asset in constructing custom financial tools like market data analysis tool, FIX connectivity adapter and FIX analysis tools etc. BlitzTrader API is built on top of Microsoft .NET platform, so strategies can be developed in any .NET supported language (C#, VB.NET, C++, J#...) and is fully integrated with Visual Studio platform through a set of ready-to-go templates. The trading API of BlitzTrader is used to develop automate trading strategies is driven by real-time events. Furthermore, this guide assumes some basic knowledge of the C# programming language.
The topic provides the high level overview of the basic BltzTrader API product architecture. The BlitzTrader platform relied on a modular software infrastructure, designed to enable flexible usage of BlitzTrader technologies and features. The following diagram illustrates the logical layout of different components of Blitz Trading System.
This section covers the basic terminology and concepts required to understand how BlitzTrader works. Once you understand the core concept, it’s easy to use BlitzTrader API for the development of proprietary Strategies, Exchange adapters and trading tools within the eco-system.
Strategies are algorithmic trading programs defining set instruction or rules for entering and exiting trades seeking an alpha opportunity, manage market impact or optimize risk. The developer implements the entry/exit rules based on his/her own knowledge and hypothesis, and the strategy will automatically place the trades in real-time. The BlitzTrader Strategy development API provides environment to build rule based strategies to monitor real-time prices, submit, cancel or modify orders based on market data events, receive order and fill updates and have access of positions and real-time trade statistics. The Strategy development framework completely decoupled the core strategy business logic from complex underneath software managing straight through processing and provides cleaner separation for you to focus only on your core strength trading and research.
The quant developers leverage existing tools like Visual Studio.NET IDE and Mocrosft.NET programming language to develop strategies using BlitzTrader API. Visual Studio IDE provides comprehensive development environment for code intellisense and track down bugs using a full power of modern debugger while running Strategy under market simulation. Set breakpoints, step through strategy code and watch values change during execution.
Strategies is a programmable component that is plugged and configured within BlitzTrader platform. It is usable when system administrator assigns the permissions and roles of it to trading user. It is then trading user responsibility to create the usable portfolio of strategy by assigning a tradable instruments and state of the strategy parameter. The creation of portfolio and assigning a state is termed as Strategy Instance creation process. Strategy Instance is analogous to a object of a class created at run-time.
Administrator can create a trading user, assign strategies, exchange segment and define a risk constraint.
Trading user logged to a BlitzTrader trading dashboard to manage and control automated trading strategies. Every running strategies Instance is owned by some trading user.
BlitzTrader provides comprehensive Framework and Integration interface to develop your own connectivity adapter to use a particular exchange or broker system in process of achieving a Direct Market Access (DMA) and facilitates the connectivity to Exchanges, Broker, ECN, Banks etc. It enables trading firm to build out fully transparent cross-region trading infrastructure, so they can connect to any market around the globe. The adapter role is intermediary to establish a connection oriented session with exchange and translate Blitz OMS messages to counterpart system defined messages and vice-versa. The BlitzTrader API provides a well define interface of communication between BlitzTrader OMS and Exchange adapter component. In basic Exchange Adapter is the gateway to the liquidity provider for market data, order routing and execution. It can optionally also hold an implementation of a market data feeder. The BlitzTrader FIX component greatly simplifies the development of FIX based counterparty adapter plugin. FIX component offer comprehensive, high performance support for FIX standard and routing via FIX stream.
A liquidity venues in BlitzTrader is identified as an Exchange Segment. BlitzTrader supports connectivity to the multiple markets to use either as a source of market data information or for the order routing or both. Each connectivity to the Exchange/Broker gateway system is managed by a programmable component called Adapter. BlitzTrader provides a comprehensive API and framework to develop and integrate the exchange adapter as a plugin component. Each adapter is identified by unique name identifier called Exchange Segment. Every tradable instrument also linked to specific exchange segment which helps, BlitzTrader framework to easily identify the Adapters to route the order for an Instrument.
Instrument is basic component of any trading system and holds an information about tradable securities for a given exchange segment. It holds some financial value and can be of type Equities, Futures, Options, Currency, etc. BlitzTrader platform support multiple exchange connectivity and each connectivity is managed through an adapter component represented as an exchange segment.
Name | Security Type | Exchange Segment | TickSize | LotSize | Expiry | StrikePrice | OptionType |
---|---|---|---|---|---|---|---|
ESM15 | FUTURES | CME | 0.25 | 1 | June 2015 | - | - |
GOOG | EQUITY | NASDAQ | 0.01 | 1 | - | - | - |
NIFTY | FUTURES | NSEFO | 0.05 | 50 | 26Feb2015 | - | - |
SBIN | OPTIONS | NSEFO | 0.05 | 500 | 26Feb2015 | 295.00 | CE |
RELIANCE | EQUITY | NSECM | 0.05 | 300 | - | - | - |
USD/INR | FUTURES | NSECD | 0.0025 | 1000 | 26Feb2015 | - | - |
EUR/USD | FOREX | FXCM | 0.0001 | 1000 | - | - | - |
BlitzTrader API provides an abstract Instrument class that represents exchange traded contracts i.e. Equity, Futures, Options, Spread and Spot(Forex) The instrument class contains all the common properties that define the contract such as name, exchange id, exchange segment, tick size, lot size etc. The others properties of Instrument are more embedded into a concrete instrument type class, such as derivative contracts (Futures, Options) contain expiration date. Options contract contains strike price, options type (CE, PE, CA, PA) etc. Any custom properties of an Instrument can be added through an Extended Market Properties mechanism of inserting key-value pair. BlitzTrader Framework laid down a process to import tradable instrument definitions and persist it internally. BlitzTrader Adapter is a programmable component representing the exchange segment and provides the access of the market for both trading and market data interface. It is Adapter responsibility to provide the list of tradable Instrument to the BlitzTrader framework.
For more details, please refer to Adapter section on How to import the Instrument definition into BlitzTrader? BlitzTrader maintains the unique name of instrument per exchange segment based on following nomenclature.
Instrument Types | Symbology | Example |
---|---|---|
Equity | [Symbol Name] | GOOG |
Spot | [Symbol Name] | EUR/USD |
Futures | [Symbol Name] [Expiration Month] [Expiration Year] | NIFTY FEB 2015 |
Options | Symbol Name] [Expiration Month] [Expiration Year] [Option Type] [Strike Price] | NIFTY FEB 2015 CE 8800 |
To access the Market Data Container interface of an Instrument from your strategy other than your Instrument Variable can be done as:
IMarketDataContainerInfo marketDataContainerInfo = base.GetMarketDataContainer(ExchangeSegment.NSEFO, "NIFTY FEB 2015 CE 8800"); if (marketDataContainerInfo != null) { ITouchLineInfo touchlineInfo = marketDataContainerInfo.TouchLineInfo; double bestBidPrice = touchlineInfo.BestBidPrice; int bestBidSize = touchlineInfo.BestBidSize; double bestAskPrice = touchlineInfo.BestAskPrice; int bestAskSize = touchlineInfo.BestAskSize; double lastPrice = touchlineInfo.LastPrice; int lastSize = touchlineInfo.LastSize; long lastTradedTime = touchlineInfo.LastTradedTime; }
BlitzTrader provides a high level of abstraction of tradable instrument with a very powerful concept called Instrument variable (IV). Strategy developer needs to define a required number of instances of IV based on the strategy requirement. You can assume this is something you can buy or sell and have access of real-time price information. For example, a pair trading statistical arbitrage strategy works on two historically correlated instruments has to define two IVs say PairLeg1 and PairLeg2. When a well established price correlation between PairLeg1 and PairLeg2 broke down, i.e. stock PairLeg1 traded up while PairLeg2 traded down, they would sell PairLeg1 and buy PairLeg2, betting that the spread would eventually converge.
private IVObject _ivObjectPairLeg1 = new IVObject("PairLeg1", "Pair First Leg", true, InstrumentType.Equity | InstrumentType.Futures | InstrumentType.Options, MarketDataType.All, OrderEventType.All); private IVObject _ivObjectPairLeg2 = new IVObject("PairLeg2", "Pair Second Leg", true, InstrumentType.Equity | InstrumentType.Futures | InstrumentType.Options, MarketDataType.All, OrderEventType.All);
public IVObject(string name, string description, bool isTradable, InstrumentType instrumentType, MarketDataType requiredMarketDataType, OrderEventType requiredOrderEventType)
name: Name of the instrument variable. This should be unique name across different instrument variable within the same strategy implementation class.
description: The multiple words description about instrument variable
instrumentType: Represent asset class type of instrument variable.
Member name | Value | Description |
---|---|---|
Futures | 1 | Represent Futures contract |
Options | 2 | Represent Options contract |
Spread | 4 | Represent 2-Leg Spread contract |
Equity | 8 | Represent Equity contract |
Spot | 16 | Represent Spot contract (Forex) |
requiredMarketDataType: IV declare itself for the kind of market event it is interested to listen.
Touchline – Delivers the best price change event, including last traded price change.
MarketDepth – Deliver the 5 best buy and sell prices change event. The market data information is delivered to your strategy implementation class through an overridden callback method:
override void OnMarketDataEvent(StrategyMarketDataEventArgs strategyMarketDataEventArgs)
Member name | Value | Description |
---|---|---|
None | 1 | Represent no market data event delivered as a callback event |
Touchline | 2 | Represent level-I market data event delivered as a callback event |
MarketDepth | 4 | Represent level-II market data event delivered as a callback.event |
All | 8 | Represent all type of market data event delivered as a callback event |
requiredOrderEventType: This attribute is valid for a tradable IV and allow programmer to register for different order events that triggers during the order state changes during the order lifecycle. This allows programmers to receive the order events as a callback function for a respective order state change.
Member name | Value | Description |
---|---|---|
None | 1 | Represent no order event delivered as a callback |
OrderAccepted | 2 | Represent a order accepted event by exchange is delivered as a callback method: protected override void OnOrderAccepted(IVObject ivObject, OrderAcceptedEventArgs orderAcceptedEventArgs) |
OrderRejected | 4 | Represent a order rejected event by exchange is delivered as a callback method: protected override void OnOrderRejected(IVObject ivObject, OrderRejectedEventArgs orderRejectedEventArgs) |
OrderModificationAccepted | 8 | Represent a order modification request accepted by exchange is delivered as a callback method: protected override void OnOrderModified(IVObject ivObject, OrderModificationAcceptedEventArgs orderModificationAcceptedEventArgs) |
OrderModificationRejected | 16 | Represent a order modification request rejected event by exchange is delivered as a callback method: protected override void OnOrderModificationRejected(IVObject ivObject, OrderModificationRejectEventArgs orderModificationRejectEventArgs) |
OrderCancellationAccepted | 32 | Represent a order cancellation request accepted event by exchange is delivered as a callback method: protected override void OnOrderCancelled(IVObject ivObject, OrderCancellationAcceptedEventArgs orderCancellationAcceptedEventArgs) |
OrderCancellationRejected | 64 | Represent a order cancel request rejected event by exchange is delivered as a callback method: protected override void OnOrderCancellationRejected(IVObject ivObject, OrderCancellationRejectEventArgs orderCancellationRejectEventArgs) |
OrderTraded | 128 | Represent a order traded event by exchange is delivered as a callback method: protected override void OnTrade(IVObject ivObject, TradeDataEventArgs tradeDataEventArgs) |
OrderTriggered | 256 | Represent a stop order triggered event by exchange is delivered as a callback method: protected override void OnOrderTriggered(IVObject ivObject, OrderTriggeredEventArgs eventArgs) |
All | 510 | Represent all above event by exchange is delivered on their respective callback method |
The strategy implementation class must override following property to return to framework the list of Instrument Variables used in the Strategy.
public override IVObject[] IVObjects
The framework manages to assign a concrete Instrument based on Traders request for portfolio creation. The mapped Instrument to IV is subscribed for market and order events delivered through an event callback mechanism to the Strategy.
public override IVObject[] IVObjects { get { List _ivObjectArray = new List(); _ivObjectArray.Add(_ivOptionObject); _ivObjectArray.Add(_ivUnderlyingObject); return _ivObjectArray.ToArray(); } }
The trading order generated from strategy instance is uniquely assigned and identified by BlitzTrader as AppOrderID. This is internal ID assigned to the order and can also be referred as Client Order ID.
This section provides an overview of using BlitzTrader API to develop proprietary trading strategies and quant developers learn about on how plug-in architecture allows easy extensibility of system to develop and integrate powerful trading ideas into BlitzTrader system.
Before you start developing your custom proprietary trading strategy, you need following prerequisites: Latest BlitzTrader Framework components files (QX.Blitz.Core.dll, QX.Base.Common.dll, QX.Base.Core.dll, QX.Base.Data.dll, QX.Base.Financial.dll) A C# 4.0-5.0 development IDE (Microsoft Visual Studio, SharpDevelop or any other IDE).
using QX.Base.Common; using QX.Base.Core; using QX.Blitz.Core; using QX.Base.Common.Message; using QX.Base.Common.InstrumentInfo;
Then we rename the default Class1.cs to SpreadScalping.cs and implement your strategy according to following example code:
using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Runtime.CompilerServices; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Collections.Generic; using QX.Base.Common; using QX.Base.Common.InstrumentInfo; using QX.Base.Common.Message; using QX.Base.Core; using QX.Blitz.Core; using QX.Common.Lib; namespace QX.Blitz.Strategy.ATExecution { namespace QX.Blitz.Strategy.SpreadScalpingX2 { [StrategyAttribute("{7CA0AE08-3363-4BCF-92D2-0FE2A59A06A9}", "Spread-Scalping-X2", "Spread Scalping Strategy", "Quantum Hedge Fund")] class SpreadScalping : StrategyBase { [StrategyParameterAttribute("BenchMarkSpread", DefaultValue = 5, Description = "Benchmark Spread", CategoryName = "Standard", DisplayName = "Benchmark Spread")] private double BenchMarkSpread = 5; [StrategyParameterAttribute("OrderLotSize", DefaultValue = 1, Description = "Order Quantity", CategoryName = "Standard", DisplayName = "Order Size in Lots")] private int OrderQty = 5; [StrategyParameterAttribute("Rounds", DefaultValue = 1, Description = "Total number of Rounds to perform", CategoryName = "Standard", DisplayName = "Rounds")] private int Rounds = 5; [StrategyPublishParameter("CompletedRounds", DefaultValue = 0, Description = "Published By Server : Total Completed Rounds.")] private int CompletedRounds = 0; private IVObject _ivObject = new IVObject("IV", "Spread Scalping Instrument", true, InstrumentType.Equity | InstrumentType.Futures | InstrumentType.Options, MarketDataType.All, OrderEventType.All); private IVInfo _ivInfo = null; private IOrderCommand _entryOrderCommand = null; private IOrderCommand _exitOrderCommand = null; #region Override Methods protected override void OnInitialize() { _ivInfo = base.GetIVInfo(_ivObject); _entryOrderCommand = base.GetSmartOrderCommand("Entry", TimeInForce.GFD, _ivObject); _exitOrderCommand = base.GetSmartOrderCommand("Exit", TimeInForce.GFD, _ivObject); if (_entryOrderCommand == null || _exitOrderCommand == null) throw new Exception("Strategy Initialization Failed. Reason : Smart Order is not Initialized."); TraceLogInfo("Strategy Initialize Successfully"); } protected override bool OnStart(out string errorString) { errorString = string.Empty; return true; } protected override void OnStopping() { string errorString = string.Empty; if (!base.CancelAllOpenOrders(5, out errorString)) { TraceLogWarning("Order cancellation failed. Reason : " + errorString); } TraceLogInfo("Strategy Stopped."); } public override IVObject[] IVObjects { get { List _ivObjectArray = new List(); _ivObjectArray.Add(_ivObject); return _ivObjectArray.ToArray(); } } protected override int MarketDataDelayNotifyTimeInSeconds { get { return 10; } } protected override bool ValidateStrategyParameter(string parameterName, object paramterValue, out string errorString) { errorString = string.Empty; bool retValue = false; switch (parameterName) { case "BenchMarkSpread" : retValue = paramterValue is double; if (retValue == false) errorString = parameterName + " value is invalid"; break; case "OrderLotSize" : retValue = paramterValue is int; if (retValue == false) errorString = parameterName + " value is invalid"; break; case "Rounds" : retValue = paramterValue is int; if (retValue == false) errorString = parameterName + " value is invalid"; break; default: retValue = base.ValidateStrategyParameter(parameterName, paramterValue, out errorString); break; } return retValue; } protected override void OnMarketDataEvent(StrategyMarketDataEventArgs strategyMarketDataEventArgs) { try { if (StrategyRunningMode == StrategyMode.Stopped) return; if (!OrderRoutingEnabled) return; if (base.IsStrategyStopInitiated) return; if (CompletedRounds >= Rounds) return; if (_entryOrderCommand == null || _exitOrderCommand == null) return; if (strategyMarketDataEventArgs.MarketDataContainerInfo.TouchLineInfo.BestBidPrice <= 0 || strategyMarketDataEventArgs.MarketDataContainerInfo.TouchLineInfo.BestAskPrice <= 0) return; OrderSide entrySide = GetSpreadScalpingeEntrySide(strategyMarketDataEventArgs.MarketDataContainerInfo); double entryOrderPrice = 0; if (_entryOrderCommand.CurrentOrder == null) { // Current order null indicates that no open order is active // retrieve the best price in the entry side of the order book entryOrderPrice = base.GetBestPrice(_ivInfo.MarketDataContainer, entrySide); } else { // retrieve the best price in the entry side of the order book, keeping self order state entryOrderPrice = base.GetBestPrice(_ivInfo.MarketDataContainer, _entryOrderCommand.CurrentOrder); } // Set call will automatically send a new order or modify existing order with a new price. _entryOrderCommand.Set(true, entrySide, OrderType.Limit, OrderQty, entryOrderPrice, 0); if (_entryOrderCommand.TotalTradedQuantity > 0) { //Process Exit Logic OrderSide exitSide = OrderSide.None; if (_entryOrderCommand.CurrentOrder.OrderSide == OrderSide.Buy) exitSide = OrderSide.Sell; else exitSide = OrderSide.Buy; double exitOrderPrice = 0; if (_exitOrderCommand.CurrentOrder == null) exitOrderPrice = base.GetBestPrice(_ivInfo.MarketDataContainer, entrySide); else exitOrderPrice = base.GetBestPrice(_ivInfo.MarketDataContainer, _exitOrderCommand.CurrentOrder); _exitOrderCommand.Set(true, exitSide, OrderType.Limit, _entryOrderCommand.TotalTradedQuantity, exitOrderPrice, 0); } if (_entryOrderCommand.TotalTradedQuantity > 0 && _entryOrderCommand.TotalTradedQuantity == _exitOrderCommand.TotalTradedQuantity) { CompletedRounds++; base.TraceLogInfo("Transaction Completed."); string errorString = string.Empty; if (!_entryOrderCommand.Reset(out errorString)) base.TraceLogError("Smart Order Resetting Failed. Reason : " + errorString); if (!_exitOrderCommand.Reset(out errorString)) base.TraceLogError("Smart Order Resetting Failed. Reason : " + errorString); } } catch(Exception oEx) { base.TraceLogError("Error occured. Message : " + oEx.Message); } } #endregion #region Private Methods private OrderSide GetSpreadScalpingeEntrySide(IMarketDataContainerInfo marketDataContainerInfo) { // Alpha to detect a direction of trade entry OrderSide spreadScalpingeEntryDecesion = OrderSide.None; double marketSpreadValue = marketDataContainerInfo.TouchLineInfo.BestAskPrice -marketDataContainerInfo.TouchLineInfo.BestBidPrice; double buyerLTPGap = marketDataContainerInfo.TouchLineInfo.LastPrice - marketDataContainerInfo.TouchLineInfo.BestBidPrice; double sellerLTPGap = marketDataContainerInfo.TouchLineInfo.BestAskPrice - marketDataContainerInfo.TouchLineInfo.LastPrice; if (marketSpreadValue >= BenchMarkSpread) { if (buyerLTPGap > sellerLTPGap) spreadScalpingeEntryDecesion = OrderSide.Buy; else if (buyerLTPGap < sellerLTPGap) spreadScalpingeEntryDecesion = OrderSide.Sell; } return spreadScalpingeEntryDecesion; } protected override void OnDispose() { if (!IsInitialized) return; TraceLogInfo("Strategy Dispossing."); } } }
Change the output path property value in project setting to redirect the output to {BlitzTraderInstallation Folder}/Strategies folder. Now all we need to do is build the project. You can also manually copy the required custom strategy DLL file and any of its dependedable DLL to {BlitzTraderInstallation Folder}/Strategies folder. The user defined Strategy implementation class must derive from QX.Blitz.Core.StrategyBase base class provided by the framework. By overriding methods of this StrategyBase class provided by the framework, you can customize the behaviour of your strategy. StrategyBase class provides a way to establish a bridge between your code and the native platform.
BlitzTrader trading system development API (BTS API) exposes following event-driven methods that your strategy implementation class must implement. Event notification condition describes the circumstances under which each of the following event call-backs are invoked.
Callback | Conditions |
---|---|
OnInitialize | Invoked when strategy instance is loaded. Once your code is initialized the requested data is pushed into your strategy through events. The event triggered depends on the data you request or subscribed. |
OnStart | Invoked in response of user started the strategy. Here one would normally reset the variables and does other strategy setup operations. |
OnMarketDataEvent | OnMarketDataEvent is called on every change in market data of subscribed instruments from strategy. The method receives a StrategyMarketDataEventArgs of a particular instrument and can be used to retrieve latest market prices like Bid, Ask, LTP. Here one would implement strategy logic which is related to price change. |
OnStopping | OnStopping is called before a strategy is stopped. Here, depending on strategy logic, one would consider closing all active orders, disposing any custom objects, etc. |
ValidateStrategyParameter | This function is called when user set to create the strategy instance by assigning a actual instrument to Instrument Variable (IV) or change of the input parameter value during the strategy control from trader console window. Based on strategy requirements, here developers can write a code to validate the parameter value before applying it to the internal variables. In case of validation failed. Developer can return a valid reason of failure. |
Strategy implementation class need to expose user input variables which is necessary to control the behaviour of running strategy from BlitzTrader terminal. StrategyParameter attribute is applied over any strategy variable definition to mark that variable is of type input parameter. StrategyParameter attribute allow to specify characteristic such as: Name of the variable: Unique name identifier of variable Default value: Default value set during the initialization Description: Detail description of the variable CategoryName: User defined category name DisplayName: Diaplay name of the variable
[StrategyParameter("MaxBuyPositionInLots", DefaultValue = 0, Description = "Maximum Buy Position.", CategoryName = "Buy IV", DisplayName = "Max Position (Lots)")] private int MaxBuyPositionInLot = 0; [StrategyParameter("BuyBiddingAtTargetIV", DefaultValue = 0, Description = " Bidding on target IV instead on best bid(If available).", CategoryName = "Buy IV", DisplayName = " Bidding @ Target IV ")] bool BuyBiddingAtTargetIV = false;
Strategy sometimes needs to publish some important indicator value to the trader for information purpose. The server hosted strategy can define some variables marked with StrategyPublishParameter attribute. The runtime value of these marked variables is published to the BlitzTrader terminal in their respective strategy instance view as a snapshot. We sometime also can refer Strategy publish Parameter as Output variable.
[StrategyPublishParameter("UnHedgedBuyOptionQuantity", DefaultValue = 0, Description = "UnHedged Buy Option Quantity.")] private double UnhedgedOptionBuyQuantity = 0; [StrategyPublishParameter("UnHedgedSellOptionQuantity", DefaultValue = 0, Description = "UnHedged Sell Option Quantity.")] private double UnhedgedOptionSellQuantity = 0;
All strategy must define at least one Instrument Variable for trading transaction. The strategy can define any number of Instrument Variable based on its requirement. For example an options strategy for buying and selling a straddle or strangle needs at least two options contracts. The Strategy must define two Instrument Variables and during the stragy instace creation process, trader can assign a real tradable contract to IV. The server can implement ValidateInstrumentAssignment function to validate if user has correctly mapped the options contract based on strategy requirement. The function ValidateInstrumentAssignment is called multiple time for each Instrument Variable define in your strategy.
private IVObject _ivObjectOptionFirstLeg = new IVObject(("OptionsFirstLeg", "Option First Leg", true, InstrumentType.Options, MarketDataType.All, OrderEventType.All); private IVObject _ivObjectOptionSecondLeg = new IVObject(("OptionsSecondLeg", "Option Second Leg", true, InstrumentType.Options, MarketDataType.All, OrderEventType.All); public override bool ValidateInstrumentAssignment(IVObject ivObject, Instrument instrument, out string errorString) { if (_ivObjectOptionFirstLeg.Name == ivObject.Name) { if (instrument.InstrumentType != InstrumentType.Options) { errorString = "Instrument assignment not a valid for Option contract. It must be Option Contract."; return false; } } else if (_ivObjectOptionFirstLeg.Name == ivObject.Name) { if (instrument.InstrumentType != InstrumentType.Options) { errorString = "Instrument assignment not a valid for Option contract. It must be Option Contract."; return false; } } errorString = string.Empty; return true; }
There is one more function supported for Instrument Variable validation. It is called once and share a list of mapped Instrument to its corresponding IVs defined in a strategy. It is useful to compare some properties of both mapped instruments.
public override bool ValidateInstrumentAssignments(KeyValuePair[] ivObjetToInstrumentMap, out string errorString) { Options optionFirstLegInstrument = null; Options optionSecondLegInstrument = null; foreach (KeyValuePair iterator in ivObjetToInstrumentMap) { if (iterator.Key == _ivObjectOptionFirstLeg) optionFirstLegInstrument = (Options)iterator.Value; else if (iterator.Key == _ivObjectOptionSecondLeg) optionSecondLegInstrument = (Options)iterator.Value; } if (optionFirstLegInstrument.StrikePrice > optionSecondLegInstrument.StrikePrice) { errorString = "Instrument assignment is incorrect. First leg strike price must be less than second leg strike Price."; return false; } ........... ........... errorString = string.Empty; return true; }
This is important to validate all the inputs parameter against the constraint that is defined for the variables in the given strategy. For example a user defined parameter named UserBenchmark must have a positive value.
[StrategyParameter("UserBenchmark", "0.0", "Target Spread")] private double UserBenchmark = 0; [StrategyParameterAttribute(("VWAPPriceTillDepth", "4", "VWAP Till Depth")] private int VWAPTillDepth = 0; ........... ........... protected override bool ValidateStrategyParameter(string parameterName, object paramterValue, out string errorString) { errorString = string.Empty; bool retValue = false; switch (parameterName) { case "UserBenchmark" : retValue = paramterValue is double; if (retValue == false || retValue < 0) errorString = parameterName + " value is invalid."; break; case "VWAPTillDepth" : retValue = paramterValue is int; if (retValue == false || retValue < 0) errorString = parameterName + " value is invalid."; break; default: retValue = base.ValidateStrategyParameter(parameterName, paramterValue, out errorString); break; case StrategyInputParameter.BuyJumpPrice: } }
Strategy sometimes needs to publish some custom commands to be reflected to the trading terminal for general control of strategy based on its operational requirement. The framework provides a method to publish all available command and optional parameter list for given command. The command is identified by a unique GUID identifier, the display name and optional input variable definitions. All these command is visible as a context menu on a strategy instance row of a trading terminal. The strategy implementation class must implement following method and return the list of supported command. This command is visible to the trading terminal and triggered based on user action or automated call from custom user interface strategy plug-in.
protected override ActionCommandInfo[] GetActionCommands() { List actionCommandList = new List(); actionCommandList.Add(GetSendModifyOrderActionCommand ()); return actionCommandList; } ....... ....... // Generate a new GUID to be used for a every custom command private static Guid ModifyCommandStaticID = new Guid("{9A1B9203-F8A1-4CCD-B84F-10731D877AB7}"); private ActionCommandInfo GetSendModifyOrderActionCommand() { List actionCommandParameterInfoList = new List(); actionCommandParameterInfoList.Add(new ActionCommandFieldInfo("OrderSide",, FieldDataType.Int, (int)OrderSide.None)); actionCommandParameterInfoList.Add(new ActionCommandFieldInfo("OldPrice",, FieldDataType.Double, 0)); actionCommandParameterInfoList.Add(new ActionCommandFieldInfo("NewPrice", FieldDataType.Double, 0)); return CreateActionCommand(ModifyCommandStaticID, "Modify Order Price", true, actionCommandParameterInfoList.ToArray()); } //When user trigger the command from trading terminal, the control immediately pass to following //strategy implementation class method protected override void ExecuteActionCommand(Guid commandStaticID, ActionCommandFieldInfo[] inputFields) { ActionCommandFieldInfo newOrderSideCommand = null; ActionCommandFieldInfo newOrderOldPriceCommand = null; ActionCommandFieldInfo newOrderNewPriceCommand = null; // Retrieve new parameter foreach (ActionCommandFieldInfo actionCommandFieldInfo in inputFields) { if (actionCommandFieldInfo.Name.Equals("OrderSide", StringComparison.InvariantCultureIgnoreCase)) { newOrderSideCommand = actionCommandFieldInfo; } else if (actionCommandFieldInfo.Name.Equals("OldPrice", StringComparison.InvariantCultureIgnoreCase)) { newOrderOldPriceCommand = actionCommandFieldInfo; } else if (actionCommandFieldInfo.Name.Equals("NewPrice", StringComparison.InvariantCultureIgnoreCase)) { newOrderNewPriceCommand = actionCommandFieldInfo; } } if (newOrderSideCommand == null || newOrderOldPriceCommand == null || newOrderNewPriceCommand == null) { // Parameter validation failed return; } OrderSide orderSide = (OrderSide)(int)newOrderSideCommand.Value; double orderOldPrice = (double)newOrderOldPriceCommand.Value; double orderNewPrice = (double)newOrderNewPriceCommand.Value; // Do some custom processing in strategy implementation class // based on new parameters ........ ........ } }
It is evident that most of the strategy order initiating decision is triggered from the market data event. Sometime it is required that strategy need to receive the real-time market data even if it is in stopped mode. This may be to cache and calculate some technical indicator value. In order to receive the market data event during the strategy stop mode, override a method RequiredToSendMarketDataInStrategyStopMode and return true.
public virtual bool RequiredToSendMarketDataInStrategyStopMode { get { return true; } }In order to publish output parameter during the strategy stop mode, override a method RequiredToSendMarketDataInStrategyStopMode and return true.
public virtual bool RequiredToPublishParameterInStrategyStopMode { get { return true; } }The trading terminal has a default access of server based command called Refresh. Here the strategy has an opportunity to send some important state message to trading terminal based on user expliciut refresh command invocation. Strategy will receive following callback method
protected override void OnStrategyRefresh() { string infoText = GetStrategyCurrentStateText(); TraceLogInfo(infoText); }
The Blitz strategy framework provides the order state change event through a callback event mechanism. The BlitzTrader OMS raised these callback event based on order state change and strategy implementation class override them to have a proper control of the order flow and position management. Following is the event handler that are called during the order state change event:
OnOrderAccepted: Called when order is accepted by exchange. This event provides information on the exchange order ID.
protected override void OnOrderAccepted(IVObject ivObject, OrderAcceptedEventArgs orderAcceptedEventArgs) { string exchangeOrderID = orderAcceptedEventArgs.ExchangeOrderID; }OnOrderModified: Called when active order modification request is accepted by exchange
protected override void OnOrderModified(IVObject ivObject, OrderModificationAcceptedEventArgs orderModificationAcceptedEventArgs) { }OnOrderModificationRejected: Called when order modification request is rejected by exchange. This event provides the information on the rejection reason.
protected override void OnOrderModificationRejected(IVObject ivObject, OrderModificationRejectEventArgs orderModificationRejectEventArgs) { }OnOrderTrade: Called when order is traded with complete of partial fill. This event provides the information on the filled price and quantity of a trade.
protected override void OnTrade(IVObject ivObject, TradeDataEventArgs tradeDataEventArgs) { double lastTradedPrice = tradeDataEventArgs.LastTradedPrice; int lastTradedQty = tradeDataEventArgs.LastTradedQuantity; int leavesQty = tradeDataEventArgs.LeavesQuantity; }OnOrderRejected: Called when order request is rejected by exchange. This event provides the information on the rejection reason.
protected override void OnOrderRejected(IVObject ivObject, OrderRejectedEventArgs orderRejectedEventArgs) { string rejectionReason = orderRejectedEventArgs.RejectReason; }OnOrderCancelled: Called when active order cancel request is confirmed as cancelled by exchange. This event makes order in terminal state.
protected override void OnOrderCancelled(IVObject ivObject, OrderCancellationAcceptedEventArgs orderCancellationAcceptedEventArgs) { }OnOrderTriggered: Called when active stop order price is triggered by exchange. This indicates that exchange has converted stop order to market order.
protected virtual void OnOrderTriggered(IVObject ivObject, OrderTriggeredEventArgs eventArgs) { }
During the development phase, it is common practice to insert logging statement within the strategy code to produce informative logs at runtime, whether for troubleshooting or for analysis purposes. There are four category of output you can generate from your strategy implementation class. The output generated is shown in the strategy instance log window of the trading terminal. TraceLogError is used to writes the error log to the trading terminal TraceLogWarning is used to writes the warning log to the trading terminal TraceLogInfo is used to writes the error log to the trading terminal TraceStrategyExecutionMessage is special log used by strategy to notify some important event of the strategy. This information publishes in a specific log window where traders can monitor the important state of the strategy. Most of the time here one can publish the Profit/Loss information after the completion of strategy logical cycle.
protected override void OnStopping() { string errorString = string.Empty; if (!base.CancelAllOpenOrders(30, out errorString)) TraceLogInfo("Cancel all open order operation failed. Reason : " + errorString); TraceLogInfo("Strategy Instance [" + base.GetStrategyInstanceInfo().InstanceName + "] Stopped."); } ................... ................... base.TraceStrategyExecutionMessage(string.Format("SELL-IV-Difference:{0}, Target-IV-Difference:{1}, FirstLegExecutedIV:{2}, SecondLegExecutedIV:{3}, Un-HedgedQuantity:{4}", Math.Round(executedIVDiff * 100, 2), InputTargetSellIVBenchmark * 100, Math.Round(firstLegExecutedIV * 100), Math.Round(secondLegExecutedIV * 100), Output_UnHedgedDeltaQuantity));
NewSingleOrderRequestMessage class provides different static methods to create an order command to submit to a exchange gateway.
Market Order
private IVObject _iv = new IVObject("Instrument", "Tradable Instrument", true, InstrumentType.Futures | InstrumentType.Options, MarketDataType.All, OrderEventType.All); .................. int orderQty = 10; NewSingleOrderRequestMessage newSingleOrderRequest = NewSingleOrderRequestMessage.CreateMarketOrder(-iv, OrderSide.Sell, TimeInForce.GFD, orderQty);
double limitPrice = 125.35; NewSingleOrderRequestMessage newSingleOrderRequest = NewSingleOrderRequestMessage.CreateLimitOrder(_iv, OrderSide.Buy, TimeInForce.GFD, orderQty, limitPrice);
double stopPrice = 125.35; NewSingleOrderRequestMessage newSingleOrderRequest = NewSingleOrderRequestMessage.CreateStopOrder(_iv, OrderSide.Buy, TimeInForce.GFD, orderQty, stopPrice);
double limitPrice = 125.30; double stopPrice = 125.35; NewSingleOrderRequestMessage newSingleOrderRequest = NewSingleOrderRequestMessage.CreateStopLimitOrder(_iv, OrderSide.Buy, TimeInForce.GFD, orderQty, limitPrice, stopPrice);
Call SendNewOrder method passing your order command to place an order in a market. There is important property AppOrderID of class NewSingleOrderRequestMessage to retrieve a reference client order id which is used to refer to cancel or modify the order.
uint appOrderID = newSingleOrderRequest.AppOrderID; string errorString = string.Empty; if (!base.SendNewOrder(newSingleOrderRequest, out errorString)) { base.TraceLogInfo("SendOrder failed." + " Reason : " + errorString); } else { base.TraceLogInfo ("SendOrder succeeded."); }
Most exchanges support native multi-leg order that allow trader to buy and sell number of different instrument with same underline simultaneously without placing a separate orders. Multi-legged orders is used in variety of trading strategies such as straddle trading, strangle trading, ratio spread and butterfly spread etc.
NewMultiLegOrderRequestMessage multilegRequest = new NewMultiLegOrderRequestMessage(); multilegRequest.AddLeg(NewSingleOrderRequestMessage.CreateLimitOrder( _ivObjectOptionOTMLeg, OrderSide.Buy, TimeInForce.IOC, 1, otmOrderLimitPrice)); multilegRequest.AddLeg(NewSingleOrderRequestMessage.CreateLimitOrder( _ivObjectOptionATMLeg, OrderSide.Sell, TimeInForce.IOC, 2, atmOrderLimitPrice)); multilegRequest.AddLeg(NewSingleOrderRequestMessage.CreateLimitOrder( _ivObjectOptionITMLeg, OrderSide.Buy, TimeInForce.IOC, 1, itmOrderLimitPrice)); string errorString = string.Empty; uint currentMultilegAppOrderID = multilegRequest.AppOrderID; if (!base.SendNewOrder(multilegRequest, out errorString)) { currentMultilegAppOrderID = 0; base.TraceLogWarning("Multileg Order Request Failed. Reason:" + errorString); }
A spread is defined as the sale of one or more futures contracts and the purchase of one or more offsetting futures contracts. A spread tracks the difference between the price of whatever it is you are long and whatever it is you are short. Therefore the risk changes from that of price fluctuation to that of the difference between the two sides of the spread. Most exchanges support native spread contract that allow trader to buy and sell two contracts at differene of their price simultaneously without placing a separate orders
if (_ivInstrument.Instrument.InstrumentType == InstrumentType.Spread) { NewSpreadOrderRequestMessage newSpreadOrderRequestMessage = null; switch (orderType) { case OrderType.Market: newSpreadOrderRequestMessage = NewSpreadOrderRequestMessage.CreateMarketOrder(_ivObject, orderSide, orderQty); break; case OrderType.Limit: newSpreadOrderRequestMessage = NewSpreadOrderRequestMessage.CreateLimitOrder(_ivObject, orderSide, orderQty, orderPrice); break; case OrderType.Stop: case OrderType.StopLimit: TraceLogError("OrderType is not spported for Spread Order."); break; } if (newSpreadOrderRequestMessage != null) { string errorString = string.Empty; if (!SendNewOrder(newSpreadOrderRequestMessage, out errorString)) { TraceLogWarning("Order Sending Failed. Reason : " + errorString); } else { TraceLogInfo("Order Send. AppOrderID : " + newSpreadOrderRequestMessage.AppOrderID); } } }
Create a CancelOrderRequestMessage command which takes client order id and exchange order id. Exchange order ID is identifier assigned by exchange on the acceptance of the order. Cancel can only be applied to accepted order. Call SendOrderCancellation method passing your cancel order command to cancel pending order from a market.
uint appOrderID = GetAppOrderID(); string exchangeOrderID = GetExchangeOrderID(); CancelOrderRequestMessage cancelRequest = CancelOrderRequestMessage.Create(_iv, appOrderID, exchangeOrderID); string errorString = string.Empty; if (!SendOrderCancellation(cancelRequest, out errorString)) { base.TraceLogInfo("Cancel order failed." + " Reason : " + errorString); } else { base.TraceLogInfo ("Cancel order command routed."); }
To modify the attributes of pending order like target price, quantity or order type you need to create OrderModificationRequestMessage object and call a proper method on it to set the modifiable attributes.
uint appOrderID = GetAppOrderID(); string exchangeOrderID = GetExchangeOrderID(); OrderModificationRequestMessage modifyOrder = OrderModificationRequestMessage.Create(iv, appOrderID, exchangeOrderID); // Modify limit order price modifyOrder.SetPrice(limitOrderPrice); string errorString = string.Empty; if (!SendOrderModification(modifyOrder, out errorString)) { base.TraceLogInfo("Order modification failed." + " Reason : " + errorString); } else { base.TraceLogInfo ("Order modification command routed."); } //Following is available method to change the specific attribute of the order: public void SetOrderType(OrderType orderType) public void SetQuantity(uint quantity) public void SetDisclosedQuantity(uint quantity) public void SetMinimumQuantity(uint quantity) public void SetPrice(double limitPrice) public void SetStopPrice(double stopPrice) public void SetOrderValidity(TimeInForce timeInForce) public void SetOrderValidity(DateTime orderExpiryDate)
Smart Order Command is one of the powerful features of the BlitzTrader API to enable quant developer with a standardized mechanism of managing the order state of an instrument with ease. Earlier we encounter with individual orders APIs to manage sending new order, modifying and cancelling it based on strategy logic. We need to understand some limitation with earlier approach to manage the order of an instrument. Order modification and cancellation request need exchange order ID which can only be accessible once order is accepted by the exchange. For the same reason developers need to handle order accepted event and cache various state of the order across the different orders event of the strategy. Smart Order Command is intelligent way to manage instrument order state from single unified command. It intelligently decides the intention when to fire a fresh new order, modifying exiting order state or cancelling it. It also prevents and provides a secure way of avoiding some mistakes of generating new orders in loop conditions. Smart Order Command is represented by interface IOrderCommand and framework can provide template object by requesting with a function call GetSmartOrderCommand. GetSmartOrderCommand takes unique name identifier, order TimeInForce attribute and reference to your Instrument Variable to return the Smart Order Command. Following is important functions used to control the order routing behaviour:
void Set(bool condition, OrderSide side, OrderType orderType, int orderQuantiy, double orderPrice, double orderStopPrice);
condition : Indicating a condition by strategy to route the order or not. If condition is false, the existing order is cancelled. If condition is true, based in order state, it either send a fresh new order or modify the existing open order with a new order attributes. side : Side of the order (Buy or Sell) orderType : Type of the order(Market, Limit, Stop) orderQuantity : order quantity of a new order state orderPrice : limit order price of a new order state. This is valid for ordertype Limit. orderStopPrice : stop order price of a new order state. This is valid for ordertype Stop. If condition is false, all other attributes does not hold any significance and smart order command initiate a cancel order request.
bool Reset(out string errorString);Reset is called to clean the smart order command state and is done before a fresh logic start or the end of logical iteration. Following code snippet demonstrate how to use Smart Order Command
private IVObject _ivObject = new IVObject("Instrument", "Tradable Instrument", true, InstrumentType.Equity | InstrumentType.Futures | InstrumentType.Options, MarketDataType.All, OrderEventType.All); private IOrderCommand _entryOrderCommand = null; private IOrderCommand _exitOrderCommand = null; private IVInfo _ivInfo = null; .......................................... ......................................... protected override void OnInitialize() { _ivInfo = base.GetIVInfo(_ivObject); _entryOrderCommand = base.GetSmartOrderCommand("Entry", TimeInForce.GFD, _ivObject); _exitOrderCommand = base.GetSmartOrderCommand("Exit", TimeInForce.GFD, _ivObject); if (_entryOrderCommand == null || _exitOrderCommand == null) throw new Exception("Strategy Initialization Failed. Reason : Smart Order is not Initialized."); TraceLogInfo("Strategy Initialize Successfully"); } ............................................ ............................................ ............................................ OrderSide entrySide = GetEntryOrderSide(); if(_opportunitHit) _entryOrderCommand.Set(true, entrySide, OrderType.Limit, OrderQty, entryOrderPrice, 0); if(_entryOrderCommand.TotalTradedQuantity > 0) { .......................... .......................... OrderSide exitSide = GetExitOrderSide(); _exitOrderCommand.Set(true, exitSide, OrderType.Limit, _entryOrderCommand.TotalTradedQuantity, exitOrderPrice, 0); } .......................... .......................... if (_entryOrderCommand.TotalTradedQuantity > 0 && _entryOrderCommand.TotalTradedQuantity == _exitOrderCommand.TotalTradedQuantity) { CompletedRounds++; base.TraceLogInfo("Transaction Completed."); string errorString = string.Empty; if (!_entryOrderCommand.Reset(out errorString)) base.TraceLogError("Smart Order Resetting Failed. Reason : " + errorString); if (!_exitOrderCommand.Reset(out errorString)) base.TraceLogError("Smart Order Resetting Failed. Reason : " + errorString); } //Register a callback function on smart order command event _ entryOrderCommand.OnOrderRejected += OnSmartOrderRejected; _ entryOrderCommand.OnOrderSendingFailed += OnSmartOrderSendingFailed _ entryOrderCommand.OnOrderTraded += OnSmartOrderTraded; .......................... .......................... private void OnSmartOrderRejected(IOrderCommand orderCommand, string reason) { this.Stop("Smart order[" + orderCommand.SmartOrderID + "] Rejected. Rejection Reason : " + reason); } private void OnSmartOrderSendingFailed(IOrderCommand orderCommand, string reason) { this.Stop("Smart order[" + orderCommand.SmartOrderID + "] sending failed. Reason : " + reason); } private void OnSmartOrderTraded(IOrderCommand orderCommand) { if (orderCommand.SmartOrderID == _ entryOrderCommand.SmartOrderID) { } }
BlitzTrader API enabled your strategy to stream real-time market data information for Level-I and Level-II data. Level-I information consists of only the real-time bid/offer quotes for tradable securities. The Level II data displays the highest bid prices and lowest ask prices along with their size for each Market participant for a given security. Level II Data is of interest to traders because it indicates the buying and selling pressure behind individual securities.
Market depth is Level-II information data and shows the supply and demand for stock at various prices and can be a key indicator of market sentiment. Following is the snapshot of ANZ Securities up to 5 level depths. In market depth information, you can see a summary of all orders that are currently in the market. The information is continuously updated as new orders arrive and existing orders are filled or being pulled from the market.
BID |
ASK |
||||
---|---|---|---|---|---|
Quantity | No. | Price | Price | No. | Quantity |
29536 | 31 | 243 | 243.50 | 1 | 16086 |
50000 | 1 | 242.50 | 244 | 3 | 45647 |
154800 | 2 | 242 | 245 | 4 | 92959 |
4000 | 1 | 240 | 245 | 1 | 31500 |
57018 | 2 | 239 | 246.50 | 1 | 10000 |
The bid is the price that someone is willing to pay for a security at a specific point in time, whereas the ask is the price at which someone is willing to sell. "Bids" refers to the quantity of shares wanted to be purchased for a maximum price. The Bid price is also referred to as the "Buy" price. "Asks" refers to the quantity of shares available to be sold at a minimum price. The Ask price is also referred to as the "Sell" or "Offer" price. A trade occurs when the Bid price is raised to meet the Ask price or, alternatively, when the Ask price is lowered to meet the Bid price. During market trading hours, Bid prices are lower than Ask prices - thus creating a "price spread"
The difference between the highest Bid price and the lowest Ask prices. If you're trading highly liquid securities, the bid-ask spread will tend to be small, meaning that buyers and sellers generally agree about what the right price for a security should be. A large spread will exist when a market is not being actively traded.
BID |
ASK |
||||
---|---|---|---|---|---|
Quantity | No. | Price | Price | No. | Quantity |
29536 | 31 | 243 | 243.50 | 1 | 16086 |
A tick size is the smallest increment in price that equity, future, or other exchange-traded instrument is permitted to move. In a financial market, the tick size is the minimum allowable price variation that an equity, future, or other exchange-traded instrument is permitted to move. Futures markets often have specific tick sizes, but stock markets have a tick size of 0.01, which is the equivalent of $0.01 for US stock markets. Tick sizes and tick values are part of the contract specifications for all financial markets. For example, the EUR futures market has a tick size of 0.0001, which means that the smallest increment that the price can move from 1.2902, would be up to 1.2903, or down to 1.2901. The tick size is also known as the minimum price change.
A market's tick value is the cash value of one tick (one minimum price movement). For example, the EMinini S&P 500 futures market has a tick size 0.25 and tick value of $12.50, which means that for every 0.25 moves up or down, the profit or loss of a trade would increase or decrease by $12.50. The tick value is also known as the minimum price value.
It usually represents the highest bid and lowest offer and also known as best bid and offer.
BID |
ASK |
||||
---|---|---|---|---|---|
Quantity | No. | Price | Price | No. | Quantity |
29536 | 31 | 243 | 243.50 | 1 | 16086 |
BlitzTrader API provides Event callback OnMarketDataEvent method in your strategy that developers need to override to get notification of change in market data information for subscribed instrument variable.
private IVObject _iv = new IVObject("Instrument", "Tradable Instrument", true, InstrumentType.Futures | InstrumentType.Options, MarketDataType.All, OrderEventType.All); .................... .................... protected override void OnMarketDataEvent(StrategyMarketDataEventArgs strategyMarketDataEventArgs) { if (strategyMarketDataEventArgs.IVObject == _iv) { ITouchLineInfo touchLineInfo = strategyMarketDataEventArgs.MarketDataContainerInfo.TouchLineInfo; double bestBidPrice = touchLineInfo.BestBidPrice; int bestBidSize = touchLineInfo.BestBidSize; double bestAskPrice = touchLineInfo.BestAskPrice; int bestAskSize = touchLineInfo.BestAskSize; double lastPrice = touchLineInfo.LastPrice; int lastSize = touchLineInfo.LastSize; long lastTradedTime = touchLineInfo.LastTradedTime; } }LastTradedTime is represented in number format and its value is depend upon exchange segment of the instrument for which market data event notification is raised. For example in most exchange segment it is represented as numbers of seconds elapsed since epoch. To get a actual DateTime object call a following utility method
DateTime lastTradedUTCDT = ExchangeCommon.GetDateTimeFromBaseDateElapsedSeconds( touchLineInfo.Instrument.ExchangeSegment, touchLineInfo.LastTradedTime); DateTime lastTradedLocalDT = lastTradedUTCDT.ToLocalTime(); //To know if touchline represent a change in any attribute of Last trade bool isLastPriceChange = touchLineInfo.IsLastPriceChange; //To access a previous last price. double lastPrice = touchLineInfo.PreviousLastPrice;Getting MarketDepth information
IMarketDepthInfo marketDepthInfo = strategyMarketDataEventArgs.MarketDataContainerInfo.MarketDepthInfo; double totalSumBidPrice = 0; int totalBidSize = 0; // Calculating BuySide VWAP price till depth level 5; for(int i=0; i< marketDepthInfo.MarketDepthLevel; i++) { totalSumBidPrice += marketDepthInfo.GetBidPriceAt(i); totalBidSize += marketDepthInfo.GetBidSizeAt(i); if (i >= 5 || marketDepthInfo.GetBidSizeAt(i) == 0 || marketDepthInfo.GetBidPriceAt(i) <= 0) break; } double vwapBidPriceTill5Level = totalSumBidPrice / totalSize;IMarketDepthInfo interface provides depth level price and size information. To access the price and size at any depth level use a method:
int GetBidSizeAt(int depthIndex); double GetBidPriceAt(int depthIndex); int GetAskSizeAt(int depthIndex); double GetAskPriceAt(int depthIndex);Note: The depthIndex = 0 indicate the first level depth IMarketDepthInfo interface also give access to indicator functions to return some calculated value related to market depth i.e
int GetTotalDepthQuantity(OrderSide side); int GetTotalQuantityTillDepth(OrderSide side, int depthLevel); int GetDepthIndexForAvailableQuantity(OrderSide side, int quantityToCheck); double GetVWAP(OrderSide side); double GetVWAPTillDepth(OrderSide side, int depthLevel);
To convert any fractional value to a nereast price compatible with instrument tick size use a function RoundOffPriceToWholeTicks
double RoundOffPriceToWholeTicks(double orderPrice, OrderSide orderSide, IVObject ivObject) double priceToReturn = bestBidPrice(1-percentBenchmark*0.01); double priceToReturn = base.RoundOffPriceToWholeTicks(priceToReturn, optionOrderSide, _ivObject);The best price on its order side can be evaluated based on order book state and your exiting order in the book. Here it is necessary that you should not become best of your own order. BlitzTrader provides easy to use API to evaluate the best bidding price using GetBestPrice method. If order is new and you have no open order state, then use following method to evaluate best bidding price.
double GetBestPrice(IMarketDataContainerInfo marketDataContainer, OrderSide targetOrderSide)If order is already in the bood and you need to evaluate best price based on changed market condition, use following method.
double GetBestPrice(IMarketDataContainerInfo marketDataContainer, IOrderExecutionReportData currentOrder)
private IOrderCommand _entryOrderCommand = null; .............................. .............................. if (_entryOrderCommand.CurrentOrder == null) entryOrderPrice = base.GetBestPrice(_ivInfo.MarketDataContainer, entrySide); else if (entrySide == OrderSide.Sell) entryOrderPrice = base.GetBestPrice(_ivInfo.MarketDataContainer, _entryOrderCommand.CurrentOrder); Access of Instrument information IMarketDepthInfo marketDepthInfo = strategyMarketDataEventArgs.MarketDataContainerInfo.MarketDepthInfo; QX.Base.Common.InstrumentInfo.Instrument instrument = strategyMarketDataEventArgs.IVInstrument.Instrument; if(instrument.InstrumentType == InstrumentType.Options) { Options optionInstrument = (Options)instrument; double strikePrice = optionInstrument.StrikePrice; DateTime contractExpiration = optionInstrument.ContractExpiration; }
IMarketDepthInfo marketDepthInfo = strategyMarketDataEventArgs.MarketDataContainerInfo.MarketDepthInfo; QX.Base.Common.InstrumentInfo.Instrument instrument = strategyMarketDataEventArgs.IVInstrument.Instrument; if(instrument.InstrumentType == InstrumentType.Options) { Options optionInstrument = (Options)instrument; double strikePrice = optionInstrument.StrikePrice; DateTime contractExpiration = optionInstrument.ContractExpiration; }
When we talk about stock market we generally refers to Index such as Dow Jones Industrial Average (DJIA), S&P500, NASDAQ, CNX NIFFTY etc. The Index is a statistical measure of the changes in a portfolio of stocks representing the portion of market. The Index information is disseminated by exchange on a regular interval and represents the economic indicator value of the underlying portfolio. The Derivative contract of Index is tradable but here we are referring to a non-tradable Index information. The Index Data information can be provided to The BlitzTrader and is easily accessible through API model from your strategy code. The Index information is retrieved by its a name which should be unique per exchange segment.
IndexData indexData = GetIndexData(ExchangeSegment.NSECM, "CNX NIFTY"); if (indexData != null) { double indexValue = indexData.IndexValue; double lowIndexValue = indexData.LowIndexValue; ......... ......... } Receive a real-time Index Data event as a callback of subscribed index name string errorString = string.Empty; if (SubscribeIndexDataUpdate(ExchangeSegment.NSEFO, "CNX NIFTY", out errorString)) { // Index CNX NIFTY is subscribed successfully } .......... .......... protected override void OnIndexDataEvent(IndexUpdateEventArgs eventArgs) { TraceLogInfo("Index Name: " + eventArgs.IndexName + ", Index Value: " + eventArgs.IndexValue.ToString()); }The framework for IndexData provides open opportunity to disseminate any kind of information from outside application to your strategy.
News is information, often from outside the actual markets, providing background and insight into individual securities and the broader economy. News information is either presented in text, elementized or machine readable form or offered by news provider like Dow Jones, Thomson Reuters etc. BlitzTrader provides a framework to parse, normalize and disseminate the news information to your strategy. Receive a real-time News Data event as a callback of subscribed news provider name
string errorString = string.Empty; if (SubscribeNewsDataUpdate ("DOWJONES", out errorString)) { // DowJones news provider subscription is successful } .......... .......... string errorString = string.Empty; protected override void OnNewsDataEvent(NewsDataEventArgs eventArgs) { if (eventArgs.IsMachineReadableNews) { string newsID = eventArgs.ID; double actualValue = eventArgs.ActualValue; double forecastValueValue = eventArgs.ForecastValue; } }
BlitzTrader API provides implementation of the classic Black-Scholes option model for pricing Calls or Put. It also computes IV and Greeks: delta, gamma, theta, vega and rho The Library is used in our standard strategy of IV Scalping to compute delta position used to hedge the open position in options by buying/selling an underline contract. BlackSholes and OptionsGreek class provides API method to evaluate options pricing and Greeks
using namespace QX.Base.Financial ......... private IVObject _ivOptionObject = new IVObject("OptionInstrument", "Option Instrument", true, InstrumentType.Options, MarketDataType.All, OrderEventType.All); private IVObject _ivUnderlyingObject = new IVObject("UnderlyingInstrument", "Underlying Instrument", true, InstrumentType.Equity | InstrumentType.Futures, MarketDataType.All, OrderEventType.All); ............................. ............................. IVInfo _ivInfoOption = base.GetIVInfo(_ivOptionObject); Options _optionInstrument = ((Options)_ivInfoOption.IVInstrument.Instrument); IVInfo _ivInfoUnderlying = base.GetIVInfo(_ivUnderlyingObject); int _optionMaturityDays = _optionInstrument.RemainingExpiryDays; double _timeToMaturityInYearsInABS = (double)_optionMaturityDays / 365; // 10% risk free Interest rate double _riskFreeInterestRateInABS = .01; double _dividendYieldInABS = 0; private double GetCallOptionsImpliedVolatility(double optionPrice, double underlyingPrice) { double marketVolatility = 0; marketVolatility = BlackScholes.GetCallInitialImpliedVolatility(underlyingPrice, _optionInstrument.StrikePrice, _timeToMaturityInYearsInABS, _riskFreeInterestRateInABS, optionPrice, _dividendYieldInABS) / 100; return marketVolatility; } private double GetPutOptionsImpliedVolatility(double optionPrice, double underlyingPrice) { double marketVolatility = 0; marketVolatility = BlackScholes. GetPutInitialImpliedVolatility (underlyingPrice, _optionInstrument.StrikePrice, _timeToMaturityInYearsInABS, _riskFreeInterestRateInABS, optionPrice, _dividendYieldInABS) / 100; return marketVolatility; } private double GetUnderlyingDelta(OrderSide underlyingOrderSide, double ivValue) { double underlyingPrice = 0; if (underlyingOrderSide == OrderSide.Buy) underlyingPrice = _ivInfoUnderlying.MarketDataContainer.TouchLineInfo.BestAskPrice; else if (underlyingOrderSide == OrderSide.Sell) underlyingPrice = _ivInfoUnderlying.MarketDataContainer.TouchLineInfo.BestBidPrice; if (underlyingPrice <= 0) return 0; double delta = 0; if (_optionInstrument.OptionType == OptionType.CA || _optionInstrument.OptionType == OptionType.CE) { delta = OptionsGreeks.GetCallOptionDelta( underlyingPrice, _optionInstrument.StrikePrice, _riskFreeInterestRateInABS, ivValue, _timeToMaturityInYearsInABS, _dividendYieldInABS); } else if (_optionInstrument.OptionType == OptionType.PA || _optionInstrument.OptionType == OptionType.PE) { delta = OptionsGreeks.GetPutOptionDelta( underlyingPrice, _optionInstrument.StrikePrice, _riskFreeInterestRateInABS, ivValue, _timeToMaturityInYearsInABS, _dividendYieldInABS); } return delta; }
Some time it is required to synchronize some important moving state data information (DataSeries) of server to client for visual display. That gives more inutive UI interface to monitor the strategy at run-time. For instance, server hosted strategy is maintaing a runtime state of technical indicator and its trading signal decision on every bar close event. The trader needs to visualize the live state of indicator and signal in some graphical presentation. The BlitzTrader framework provides mechanism that strategy can define a dataseries that can hold information of type: integer, long, double or BarData(OHLC). This series is updated at server end and automatically synchronize at the client end. The strategy client plugin have access of these data series and can use and present the information as it required. The framework provides following type of dataseries. BlitzDoubleDataSeries: Holds a data of type Double BlitzIntDataSeries: Holds a data of type Integer BlitzLongDataSeries: Holds a data of type Long BlitzBarDataSeries: Holds a data of type BarData (OHLC) The seroes is registerd to framework by call of a API function RegisterDoubleBlitzDataSeries providing a unique name identifier. The framework creates a image of the series at the client end and any change in data is also reflected at client end.
private BlitzDoubleDataSeries _mtmDataSeries = null; protected override void OnInitialize() { ....................................... ....................................... string errorString = string.Empty; if (!base.RegisterDoubleBlitzDataSeries("MTMSeries", out _mtmDataSeries, out errorString)) { TraceLogWarning("BlitzDataSeries [MTMSeries] registration failed. : Reason" + errorString); } } .................... .................... double currentMTM = GetCurrentTransactionMTM(); _mtmDataSeries.Add(currentMTM);
One of the basic tools of the analysis is Bar Chart and study of a chart pattern in technical analysis of stocks. BlitzTrader API provides all flexibility to harness the technical analysis based trading model with best execution controlled to manage your risk and reward with every event of the market. GetMinuteBarDataSeries API retrieve the MinuteBar time series data of any minute compression. The historical data is maintained in Blitz Market Data Server (MDS). The IVMinuteBarDataSeries is linked to real-time market data event and Bar completion event is notified to registered callback method.
string errorString = string.Empty; int BarSize = 1; // Gets 1 minute bar data from historical Bid time series of last 25 days // in sync with realtime data IVMinuteBarDataSeries _ivMinuteBarSeries = GetMinuteBarDataSeries(_iv, PriceType.Bid, BarSize, DateTime.Today.AddDays(-25), out errorString); MinuteBarDataSeries minuteBarDataSeries = _ivMinuteBarSeries.BarDataSeries; // Gets the latest bar data IBarData barData = minuteBarDataSeries[minuteBarDataSeries.Count - 1]; // Bind to a callback method to receive a notification on every bar completion. _ivMinuteBarSeries.OnBarCompleted += OnBarCompleted; ....................... ....................... ....................... private void OnBarCompleted(string seriesID, IBarData barData) { } Definition of IBarData interface public interface IBarData { long DateTime { get; } DateTime DateTimeDT { get; } double Open { get; } double High { get; } double Low { get; } double Close { get; } long Volume { get; } long OpenInterest { get; } bool IsCompleted { get; } double BarHLAverage { get; } }
In finance, technical analysis is a security analysis discipline for forecasting the direction of prices through the study of past market data, primarily price and volume. Technical analysts believe that prices trend directionally, i.e., up, down, or sideways (flat) or some combination. Many non-arbitrage algorithmic trading systems rely on the idea of trend-following, as do many hedge funds. Technical analysis focuses on prices Most mechanical trading system employs technical analysis based indicators to model a robust system with some consistent return following a proper risk and money management rules
The BlitzTrader API provides more than 30 important standard technical indicator components that can be directly used within your strategy creation process. The standard technical Indicator list will keep growing based on common requirements of most of quants. You may decide to write your own custom Indicator to be reused in your various strategies. Following is standard template in C# for any custom Indicator under development and then we discussed in more details below on the implementation.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace QX.Base.Data.Indicators { public class MyIndicatorX1 : IndicatorBase { private int _lengthPeriod; public MyIndicatorX1(BarDataSeries dataSeries, int lengthPeriod) : base(dataSeries) { if (lengthPeriod <= 0) { throw new ArgumentException("Invalid length parameter"); } _lengthPeriod = lengthPeriod; } protected override void Initialize() { } /// /// Calculates the Indicator Function value at the index. /// /// The index at which Indicator Function value need to be calculated. /// /// The calculated Indicator function value at the index. /// protected override double Calculate(int index) { if (index < _lengthPeriod) { return double.NaN; } else { double return 1; } } } }
Your Indicator class MyIndicatorX1 must derive from IndicatorBase class provided by BlitzTrader API. You need to provide a constructor that generally takes your BarDataSeries and any parameters used to evaluate your indicator value. For example we will be demonstrating an implementation of BollingerBand implementation that takes length and standardDeviation as input values to evaluate the Indicator values for upper, middle and lower band. Usually most indicator like SimpleMovingAverage evaluates a single value called a Main value which is initialized in the IndicatorBase class from a value returned from a Calculate method. Methods provided to be overridden in your implementation class.
Initialize() The Initialize method is optional and called once at the beginning of your Indicator evaluation process. This method is used to initialize any other embedded indicator.
Calculate The Calculate method is mandatory to be overridden by Indicator implementation class. The logic of Indicator value calculation is described in Calculate method. This method is called sequentially for every bar completion and takes the current index of bar at which the indicator value has to evaluated.
BollingerBand Indicator contains three Indicator series, a simple moving average, upper and lower bands representing K times standard deviation away from moving average.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace QX.Base.Data.Indicators { public class BollingerBand : IndicatorBase { private int _lengthPeriod; private double _standardDeviation; private DoubleSeries _doubleSeriesUpper = null; private DoubleSeries _doubleSeriesLower = null; /// /// Initializes a new instance of the class. /// /// The DataSeries. /// The length period. /// The standard deviation. public BollingerBand(BarDataSeries dataSeries, int lengthPeriod, double standardDeviation): base(dataSeries) { if (lengthPeriod <= 0) { throw new ArgumentException("Invalid Bollinger band length"); } _lengthPeriod = lengthPeriod; _standardDeviation = Math.Abs(standardDeviation); _doubleSeriesUpper = new DoubleSeries(); _doubleSeriesLower = new DoubleSeries(); } public IDoubleSeries Upper { get { return _doubleSeriesUpper; } } public IDoubleSeries Lower { get { return _doubleSeriesLower; } } /// /// Calculates the Indicator Function value at the index. /// /// The index at which Indicator Function value need to be calculated. /// /// The calculated Indicator function value at the index. /// protected override double Calculate(int index) { if (index < _lengthPeriod) { _doubleSeriesUpper[index] = double.NaN; _doubleSeriesLower[index] = double.NaN; return double.NaN; } else { double avg = BarDataSeries.GetAverage(BarPriceType.Close, _lengthPeriod, index); double std = BarDataSeries.GetStandardDeviation(BarPriceType.Close, _lengthPeriod, index); _doubleSeriesUpper[index] = avg + (_standardDeviation * std); _doubleSeriesLower[index] = avg - (_standardDeviation * std); return avg; } } } }
string errorString = string.Empty; int BarSize = 1; // Gets 1 minute bar data from historical Bid time series of last 25 days // in sync with real-time data IVMinuteBarDataSeries _ivMinuteBarSeries = GetMinuteBarDataSeries(_iv, PriceType.Bid, BarSize, DateTime.Today.AddDays(-25), out errorString); MinuteBarDataSeries minuteBarDataSeries = _ivMinuteBarSeries.BarDataSeries; int lengthPeriod = 12; double standardDeviation = 2; QX.Base.Data.Indicators.BollingerBand _bollingerBand = new QX.Base.Data.Indicators.BollingerBand(minuteBarDataSeries, lengthPeriod, standardDeviation); // Gets the latest bar data IBarData barData = minuteBarDataSeries[minuteBarDataSeries.Count - 1]; // Bind to a callback method to receive a notification on every bar completion. _ivMinuteBarSeries.OnBarCompleted += OnBarCompleted; ....................... ....................... ....................... private void OnBarCompleted(string seriesID, IBarData barData) { double bbValue = _bollingerBand[minuteBarDataSeries.Count - 1]; }
BlitzTrader provides comprehensive framework to enable the quick development and integration to use a particular liquidity source such as exchanges, ECN and broker systems in addition to a broad set of a pre-built connectivity adapter for a direct use. The adapter framework is used to connect Blitz Trading System with external liquidity provider and responsible for the communication between Blitz Trading System and Exchange Adapter. The framework provides following features -FIX components library to develop connectivity adapters using the industry standard Financial Information eXchange (FIX) messaging protocol. -Define a mechanism to import Instrument class of any asset type -Provides interface, APIs for Order and Execution messaging -Manages the session state event of adapter
This section defines the details of how to create an exchange connectivity adapter plugin. Your main adapter implementation class must derived from core base class .AdapterBase (QX.Base.Core.Adapter namespace) provided by the framework. By implementing override methods of base class, you can bridge the communication mechanism between BlitzTrader OMS and native implementation of your adapter class. Adapter implementation class decorated by attribute AdapterBaseAttribute defining the unique identifier represented by Guid, Name, the adapter type (Trading or Market Data), the Exchange Segment enum and the description. Here is explanation of some important override function provided for your adapter implementation class
Initialize This function is notified only once during the lifetime of the adapter instance before a start of the adapter. This is a place where you can initialize your adapter level variables. During initialize state the adapter state is Disconnected (with counterparty)
Start This function is notified by framework to start the adapter. This is a place where a adapter implementation class establish a connection and create a valid session with counterparty system to transact trading business messages. The valid adapter state after start process is successful is Logged.
Stop This function is notified by framework to stop the adapter. Adapter implementation class terminate the counterparty session here and notify to framework on session disconnected state.
ProcessAdapterOutboundMessage This function is notified to get an event of order related request message such as new order, modification and cancellation request. This information is converted into counterparty messaging format and transact with them on a establish session.
GetReadyToTradeState This function is notified by framework immediately after the successful Logged state triggered by Start. Here framework needs to ask adapter implementation class to confirm on ReadyToTrade State. ReadyToTrade state is final good state of adapter to routes and transact trade related message with counterparty system. Implement your adapter implementation according to following example:
[AdapterBaseAttribute("{D56EB250-021A-4898-BE68-268802FC2296}", "IB", AdapterType.Trading, ExchangeSegment.IB, "The adapter provides the Interactive and MarketData connectivity towards IB TWS")] public class IBMarketDataNativeAdapter : AdapterBase { private NSEInitDefaults _initDefaults = null; ............................ ............................ protected override void Initialize() { ............................................ ............................................. _initDefaults = new NSEInitDefaults(base.AdapterBaseInterface.ConfigurationFile.FullName, 0); } public override void Start() { ........................................................... base.SetAdapterState(SessionState.LoggedIn); } public override void Stop() { } public override void DisposeAdapter() { } public override void ProcessAdapterOutboundMessage(BlitzMessage outboundMessage) { switch (outboundMessage.MessageCode) { case BlitzMessageCode.NewOrder: ProcessNewOrderMessage(outboundMessage as NewSingleOrderRequestMessage); break; case BlitzMessageCode.OrderModification: ProcessOrderModificationMessage(outboundMessage as OrderModificationRequestMessage); break; case BlitzMessageCode.OrderCancellation: ProcessOrderCancellationMessage(outboundMessage as OrderCancelRequestMessage); break; case BlitzMessageCode.NewMultiLeg: ProcessMultilegOrderMessage(outboundMessage as NewMultiLegOrderRequestMessage); break; case BlitzMessageCode.NewSpreadOrder: ProcessSpreadOrderMessage(outboundMessage as NewSpreadOrderRequestMessage); break; default: FileLogger.WriteLine("Outbound message not supported by Adapter."); break; } } protected override string GetSessionIdentifer() { //Your custom session identifer return "IB->" + AdapterConfig.Instance.ClientID; } protected override void GetReayToTradeState() { base.SetAdapterState(SessionState.ReadyToTrade); } }After compiling your implementation of .NET adapter, place output assembly to application Adapter directory.
Exchange sends real-time trade information notification called as Execution Report for orders sent to them. The following message types are covered by adapter API Execution Reports: -Confirm the receipt of an order. -Confirm changes to an existing order (i.e. accept, cancel requests and cancel replace requests). -Update order status changes. -Update trade information of working orders (Filled/Partially Filled). -Update Rejection of orders. Exchange relayed native order execution report needs to be translated and communicated to Blitz OMS.
ExecutionReportMessage executionReport = ExecutionReportMessage.CreateOrderAcceptedMessage(long exchangeInstrumentID, uint clientOrderID, string exchangeOrderID, string exchangeExecutionID, long transactTime, long transactTimeUTC, long orderAcceptedTransactTime);
ExecutionReportMessage executionReport = ExecutionReportMessage.CreateOrderRejectedMessage (long exchangeInstrumentID, uint clientOrderID, string exchangeOrderID, string exchangeExecutionID, long transactTime, long transactTimeUTC, string rejectReason);
ExecutionReportMessage executionReport = ExecutionReportMessage.CreateOrderCancelRejectMessage(long exchangeInstrumentID, uint clientOrderID, string exchangeOrderID, string exchangeExecutionID, long transactTime, long transactTimeUTC, OrderCancelOrReplaceRejectType replaceRejectType, string rejectReason);
ExecutionReportMessage executionReport = ExecutionReportMessage.CreateOrderReplaceRejectMessage( long exchangeInstrumentID, uint clientOrderID, string exchangeOrderID, string exchangeExecutionID, long transactTime, long transactTimeUTC, OrderCancelOrReplaceRejectType replaceRejectType, string rejectReason);
ExecutionReportMessage executionReport = ExecutionReportMessage.CreatePartialFillReportMessage( long exchangeInstrumentID, uint clientOrderID, string exchangeOrderID, string exchangeExecutionID, long transactTime, long transactTimeUTC, uint tradedQuantity, double tradedPrice);
ExecutionReportMessage executionReport = ExecutionReportMessage.CreatePartialFillReportMessage( long exchangeInstrumentID, uint clientOrderID, string exchangeOrderID, string exchangeExecutionID, long transactTime, long transactTimeUTC);
ExecutionReportMessage executionReport = ExecutionReportMessage.CreateFilledReportMessage( long exchangeInstrumentID, uint clientOrderID, string exchangeOrderID, string exchangeExecutionID, long transactTime, long transactTimeUTC, uint tradedQuantity, double tradedPrice);
ExecutionReportMessage executionReport = ExecutionReportMessage.CreateOrderCanceledMessage( long exchangeInstrumentID, uint clientOrderID, string exchangeOrderID, string exchangeExecutionID, long transactTime, long transactTimeUTC);Execution report message communicated to BlitzOMS with following API
base.ProcessAdapterInboundMessage(executionReport);
FileLogger.WriteLine(LogType.Error, base.AdapterExchangeSegment + " Adapter is not initialized .");
base.CreateActionCommand(new Guid("AEEA965A-DCDE-4387-B071-88B2AFCB8345"), "Upload Instruments", new ActionCommandFieldInfo[] { }, ExecuteActionCommandUploadInstrument); base.CreateActionCommand(new Guid("A199361D-1B6C-4C80-BFEE-231395353D68"), "Display Adapter Health", new ActionCommandFieldInfo[] { }, DisplayAdapterHealthStatus); ................................... ................................... private void ExecuteActionCommandUploadInstrument(ActionCommandFieldInfo[] inputFields) { } private void DisplayAdapterHealthStatus(ActionCommandFieldInfo[] inputFields) { string adapterHealthStatus = string.Format("AdapterState: {0}, InvitationCount: {1}, TotalInvitationCount:{2}, TotalAckCount: {3}.", AdapterBaseInterface.SessionState, _interactiveSession.GetInvitationCount(), _interactiveSession.GetTotalInvitationCount(), _interactiveSession.GetTotalAcknowledgePacketCount()); RaiseAlert(AlertType.Info, adapterHealthStatus); }
Importing a Instrument is a efficient way to add Instruments of specific type in the BlitzTrader system. Exchange Adapter base class provides a handle to Blitz Instrument Persistence that can be used in your implementation class to persist all instrument supported by the adapter. The Instrument list can be obtained through your internal function which understands the proprietary mechanism of the exchange to get an Instrument List. Most exchange provides a ASCII file with the details of tradable instrument in their proprietary format. In this case, your code must parse the file to retrieve relevant information to create a Instrument object of specific type BlitzTrader import mechanism consolidates and persist the entire instrument list from all configured adapters and allow system to have an access of Instruments.
Instrument[] availableInstruments = GetNSEFOInstrumentList(); ..... ..... // Persisting the Instrument List in BlitzTrader. It overrides the existing entry InstrumentPersistence.AddInstruments(ExchangeSegment.NSEFO, availableInstruments); Pseudo code snippet of GetNSEFOInstrumentList() function Instrument[] GetNSEFOInstrumentList() { ConcurrentBag instrumentList = new ConcurrentBag(); ....... ....... Instrument instrument = new Futures(........); instrumentList.Add(instrument); ....... instrument = new Options(........); instrumentList.Add(instrument); ....... instrument = new Equity(........); instrumentList.Add(instrument); ....... return instrumentList.ToArray(); }The Instrument import process can triggered using an custom command supported by Adapter. BlitzTrader administrator can use the command to manually execute the command to refresh the latest Instrument into the system.
Automated trading solutions are widely used by investors, banks, funds, and other stock market players and are based on complex mathematical algorithms to evaluate the right time for placing buy/sell orders or can even make a deal without any human involvement.
BlitzTrader platform enables quant developer to set their propritary trading strategies of High or mid frequency, arbitrage, scalping or quantitiative types across single or multiple markets. This section provides several trading strategies case-studies to illustrade how to use BlitzTrader API.