Takion API and Developer Documentation
Takion API and Developer Documentation
Documentation
Current Version: 1.1.138
Scope
The scope of this document is to provide developers for the Takion API an overview
and some modest level of detail in order to write fully functional Takion extensions.
We will discuss the details of placing orders and receiving order notifications,
subscribing to stocks and receiving data from those stocks, as well as buying power,
risk constraints, and other account-based API capabilities.
Lastly we will discuss the Takion GUI and show a demonstration of several popular
GUI features.
Introduction
The Takion API is entirely based on the Observer pattern. A full treatment of the
Observer pattern can be found on the following pages:
http://en.wikipedia.org/wiki/Observer_pattern
http://www.oodesign.com/observer-pattern.html
You will be working extensively with this design pattern, and should understand the
details of it before proceeding. This document assumes a good knowledge of C++
and the Observer design pattern.
An example is a useful learning experience. Let’s say we want to monitor all NYSE
symbols and be notified when any trade events occur for any of those stocks.
Further, if any trade event occurs where the total order size is greater than 10,000
shares, we would like to place an order. For the purposes of our initial example use
case, we will create this functionality for a single symbol, and later in the
documentation we will discuss how to subscribe our single observer to all NYSE
symbols.
The following diagram depicts the software components that are used in this
example.
Observer
Observable
observes
MyNyseObserver Security (“XOM”)
Message
Fig 1. In the above diagram, objects in Blue are part of the Takion API, while objects in Red are
components that we will write. The Observer (MyNyseObserver) tells the Observable
(Security) that it wants to be notified of any messages that it sends. Subsequently, the Security
will invoke the Notify method on the Observer for every message that is generated.
The components that we will write to solve this example problem are quite simple.
First, we will create a observer, which will be notified when any message is
generated by Takion (in our case, the Trade messages). Second, we will subscribe
this Observer to the Observable (the Security object that represents the “XOM”
symbol, which is provided by Takion). And lastly, we will process some messages
that we receive from this Security.
MyNyseObserver.h
#include “ObserverApi.h”
#include “TakionDataApi.h”
public:
MyNyseObserver(const std::string& symbol);
virtual ~MyNyseObserver();
private:
Security* takSecurity;
};
Later, we will add the necessary methods to process a Trade message and respond
by placing an order.
Next, we will create the MyNyseObserver cpp file.
MyNyseObserver.cpp
#include “TakionLogApi.h”
#include “TakionUtilsApi.h”
#include “MyNyseObserver.h”
MyNyseObserver::~MyNyseObserver()
{
if (takSecurity != NULL)
{
takSecurity->RemoveInThreadObserver(this);
TD_ReleaseStock(takSecurity);
}
}
We will add the following code to our MyNyseObserver header file. We begin by
adding a new method to the MyNyseObserver class. This method is also called
Notify, but its parameter list accepts a message of a more specific type :
TMsgTrade.
private:
// we re-direct the above Notify to this
// method when we receive a message of this type
void Notify(const TMsgTrade* msg,
const Observable* from,
const Message* info);
};
Next, we will add the following implementation code to our MyNyseObserver cpp
file.
First, we will provide a detailed implementation inside of our Notify method. This
implementation will perform a switch-case operation on the Message::m_type
property to determine the message type. If the message is of a type that is relevant
to our feature set, we will process this message by dispatching it to a method to
handle that specific message type.
In our case, we are concerned with the M_TRADE_REPORT message enumerated
type, which corresponds to the TMsgTrade Message subclass type. A list of the most
commonly used enumerated types and corresponding subclassed Message types can
be found later in the documentation.
Secondly, we will add some implementation to our specialized Notify method to log
a friendly message if the trade execution was within our parameters.
In the previous step, we simply logged a friendly message when a trade met our
criteria. In this step, we place an order when we receive a trade that meets our
criteria.
private:
Account* currentAccount;
};
Note that it is likely that you will send a wide variety of orders and order types.
However, the majority of these will have almost identical method parameters with
slight variations. We recommend creating a few wrapper methods, for example, one
could write the following methods that take only the parameters that differ from the
defaults:
1. SendArcaLimit
2. SendNsdqLimit
3. SendNyseMarketOpen
4. SendNyseMarketClose
5. SendArcaStop
6. SendNsdqStop
int reservedQty = 0;
int routingId = RI_PROACTIVE;
int routeSubType = 0;
int routeName = 0;
if (routeStrategy != NULL)
{
routeName = routeStrategy->GetNumericName();
}
currentAcct->SendOrder(&orderClientId,
nullOrder,
replaceSizeOffset,
takSecurity,
theDestination,
orderSide,
orderType,
clientOrderType,
clientOrderData,
orderPrice,
discretionaryPrice,
stopPrice,
stopOrderType,
stopOrderBase,
level1Bid,
level1Ask,
displayQty,
reserveQty,
routingId, routeSubType, routingName,
mnemonic, iso, pegType, pegOffset,
orderTif, orderTifMillis,
cancelWashOrders,
orderResizePolicy,
resizeShortBorrow,
preBorrowShares,
preBorrowPrice,
orderNoRedirect,
closeOnly,
resizeToClose,
proAts,
blockAggressive,
roundLotPolicy);
if (orderClientId != 0)
{
// order was successfully placed
}
else
{
// order was not successfully placed
}
}
For the sake of simplicity in our Hello World extension, we will observe the
Account. For a more detailed description of observing order messages from the
other objects, see the Accounts and Positions section below.
MyNyseObserver::~MyNyseObserver()
{
if (takSecurity != NULL)
{
takSecurity->RemoveInThreadObserver(this);
TD_ReleaseStock(takSecurity);
}
if (currentAcct != NULL)
{
currentAcct->RemoveInThreadObserver(this);
}
}
We now must modify our Notify method to acknowledge Order events. Note
that I have excluded the previous cases here for the sake of brevity.
In order to cancel all open orders, we will obtain an OrderMap from the Position,
through which we can iterate and issue cancels.
And we will add the following method definition to our MyNyseObserver source
file. Note that the Notify method is the same one that we have previously added,
and we are inserting the method invocation for Canceling all orders and Placing the
new order.
if (position != NULL)
{
const OrderMap& allOrders = pos->GetAllOrders();
theOrder->Cancel();
}
}
}
Position* position =
currentAcct->FindPosition(takSecurity);
if (position != NULL)
{
position->LockInquiryWait();
CancelAllOrders(position);
position->Unlock();
}
PlaceSomeOrder(msg);
}
The following components are required by the Takion DLL system in order to
function properly:
TakionMain
The TakionMain source and header files are the primary entry points from the
Takion application into the Takion extension DLL.
The following table lists the required DLL entry point methods and a description for
each. A sample of them can be found below.
A sample of the above TakionMain methods is listed below. They are exceedingly
simple in that we simply redirect them to the TakionApp to perform any necessary
work.
TakionApp
Note that for our purposes, we recommend redirecting the TakionMain entry
methods (described below) to the TakionApp object. As such, these methods and
their accompanying parameters must be added to the TakionApp. While this seems
like a bit of a complication at first, it pays dividends in the future.
protected:
DECLARE_MESSAGE_MAP()
std::string m_filePathAndName;
std::string m_fileDescription;
std::string m_platform;
std::string m_versionStr;
unsigned __int64 m_versionNum;
};
The source file is quite simple as well. Note, the user’s own objects should be owned
by TakionApp. This provides a singular spot where all resources are created and
destroyed and owned. However, one must avoid the temptation to place the
initialization code in the TakionApp::InitInstance method. This method is
provided for compatibility with MFC only.
TakionApp theApp;
BEGIN_MESSAGE_MAP(TakionApp, CWinApp)
END_MESSAGE_MAP()
TakionApp::TakionApp() {
BOOL TakionApp::InitInstance() {
CWinApp::InitInstance();
U_InitializeInstanceInfo(m_hInstance,
m_filePathAndName, m_fileDescription,
m_platform, m_versionNum, m_versionStr);
return TRUE;
}
int TakionApp::ExitInstance() {
return CWinApp::ExitInstance();
}
GUI Concerns