Writing Broker / Data Feed Plugins

Zorro supports most major brokers either with a direct connection, or by connecting through a broker-supported platform, for instance with the MT4/5 bridge or the Sierra bridge. A direct connection to a broker API, exchange, market data feed, or platform is established with a DLL in Zorro's Plugin folder. Zorro automatically scans that folder at startup, and lists all valid DLLs in the [Broker / Account] scrollbox. The DLL uses the broker's API for placing orders and getting market data. The interface is organized for keeping the DLL as simple as possible. Only a few functions are required for basic automated trading. Additional functionality, for instance to activate special order types or getting special data, can be implemented with an optional broker command. If you know programming and have access to the broker's API documentation, you can write a broker DLL in a few hours. For downloading historical data in CSV or JSON format from online data sources you'll need no DLL; a small script is sufficient (see assetHistory).

Writing a broker plugin

Plugins can be written in any language that supports DLLs, such as Java, Pascal, C#, or C++. Many plugins have been written by Zorro users, mostly in C++. We reward proper C++ written plugins with a free Zorro S subscription, license, or update extension. As a starting point you can use the plugin for a cryptocurrency REST API, which can be found in Zorro's Source folder. The source code of other plugins developed by Zorro users is available on the GitHub pages of their authors.

An article about writing a broker plugin can be found on Financial Hacker.

The source code of included broker plugins is available on request to experienced programmers who are developing a similar plugin for the community. Please contact us with a short description of your project and your prior C++ experience. You'll need to sign a non-disclosure agreement, and send us back the final plugin with source code for review. Technical support is free for developing broker plugins; you'll need no support ticket or Zorro S subscription.

You can also contact us for outsourcing a plugin development.

Setting up VC++

Creating a VC++ DLL project with access to all Zorro functions is described under VC++ project setup. Zorro functions, such as for HTTP requests or signatures, are often useful for the implementation. But if you want a plain DLL with no Zorro stuff, do not bind the ZorroDll.cpp source file, but use the dllmain.cpp file that's automatically created by VC++. Its DllMain function is the main entry point of the broker DLL, and you can leave that function unchanged. Broker functions require the DATE and T6 data types, thus you need to define DATE and include the trading.h header, like this:

typedef double DATE;
#include <trading.h>

If your broker DLL accesses Zorro-specific structs, set the struct alignment to 4 with a #pragma pack(4) statement before including trading.h. Otherwise structs have different sizes in Zorro and in your DLL.

For a DLL to appear in the scrollbox, it must be located in the Plugin folder. Zorro first checks at start if the DLL can be opened with LoadLibrary(). If so, it checks if there is a BrokerOpen function (see below) and if it returns a valid version number. If both conditions are fulfilled, the DLL is registered and appears in the scrollbox. LoadLibrary will fail when DllMain does not return properly. Most frequent reasons are not creating a plain Win32 DLL (f.i. a 64-bit or MFC DLL) or a missing module that the DLL requires. Thus, the more complex libraries you're using, the more likely is your DLL to fail, probably not on your, but on other people's PCs. For being on the safe side, include in the distribution all modules that your DLLs needs. If in doubt, check your DLL's dependencies with DependencyWalker. For debugging, place breakpoints in DllMain and BrokerOpen and check what's happening when Zorro starts.

On Financial Hacker you can find a step by step instruction for implementing a REST API DLL.

Development and test

The Source folder contains broker plugin examples in .zip archives:

You can find more Zorro broker plugins on Github. Use the best suited as a template for your own plugin. Implement the DLL functions (see below) in this order: BrokerOpen, BrokerLogin, BrokerAsset, BrokerBuy2. These 4 functions (described below) are the minimum required for trading with the broker. Optionally, implement BrokerAccount, BrokerHistory2, BrokerTime, BrokerTrade, BrokerSell2, BrokerStop if supported by the API. Test any function after implementation with the TradeTest script.

Some functions need not be fully implemented, or not at all. The minimum functions for TradeTest to run are BrokerOpen and BrokerLogin. If a function, f.i. BrokerAsset, is not yet available in the DLL, Zorro simulates it with default values. So you can implement and test the functions step by step.

As soon as the BrokerAsset function is correctly implemented, you should see the current price in the Server window. The TradeTest script opens a panel with the following buttons for testing various broker functions:

[Auto On/Off] - Toggle button for a simulated trade session that automatically opens or closes a trade every minute.

[NFA On/Off] - Toggle the NFA flag. Required for most US accounts; not to be set for most Forex/CFD accounts.

[Hedge] - Toggle between Hedge modes 0, 2, 4,and 5. Some brokers do not support full hedging (mode 2) or partial closing (mode 5).

[Order] - Toggle between limit (LMT), market orders (MKT), good-til-cancelled (GTC) and adaptive orders (Adaptive) when supported by the plugin.

[Asset] - Enter the asset symbol to trade (default: asset from the scroll box).

[Buy Long] - Open a long position with the Lots and Stop value set up with the sliders.

[Buy Short] - Open a short position. Dependent on Hedge, close any open position in opposite direction.

[Close Long] - Close the given number of lots from an open long position. Partial closing is not supported by some brokers.

[Close Long] - Close the given number of lots from an open short position.

[Update Stop] - Sets the Stop of all open positions to the value (in Pips) set up with the slider. Stop adjustment is not supported by some brokers. Due to StopFactor, the broker stop is more distant than the real stop.

LMT orders attempt to open the position at half spread, adaptive orders at zero spread. The broker must support real limit orders for this; MT4 "pending positions" are no limit orders and will not work for LMT or adaptive orders. Various trading modes, broker commands, asset lists etc. can be set up in #define statements at the begin of the TradeTest script.

Broker API functions

The broker DLL exports functions that are described in the following list. With VC++, exported DLL functions must be either declared with the extern "C" __declspec(dllexport) attribute, or listed in a .def file. The DLL functions use only a small subset of a usual broker API. In the following list, pointer arguments printed in italic can be NULL; if they are nonzero, the function must fill them with the required data. All data is mandatory if not mentioned otherwise.

BrokerOpen (char* Name, FARPROC fpMessage, FARPROC fpProgress) : int

Called at startup for all broker DLLs found in the Plugin folder. Retrieves the name of the broker, and sets up two callback functions. Should not allocate or load any resources, nor call any Zorro functions - all this can be done in the BrokerLogin function.

Parameters:

Name Output, char[32] array to be filled with the name of the broker, f.i. "FXCM". The name appears in the Account scrollbox adn is used for selecting the plugin.
fpMessage Input, pointer to a int BrokerMessage(const char* Message) function. The plugin can call BrokerMessage for printing messages - usually errors - in Zorro's message window. Using this function is not mandatory, but recommended. If the message string begins with an exclamation mark '!', Zorro opens an alert box for notifying the user that his attention might be required. If it begins with a hash '#', it is printed into the diagnostics file only.
fpProgress Input, pointer to a int BrokerProgress(intptr_t Progress) function. The plugin can call it repeatedly to keep Zorro responsive in long loops or when broker operations take longer than a second, like BrokerHistory2. When Progress is 0, the Zorro UI will only update its controls for preventing unresponsiveness. When it is 1, dots will be printed in the message window for indicating progress of a lengthy operation. When Progress is a pointer and a callback function exists in the script, it is called and the pointer is passed for triggering script functions from the broker API. When BrokerProgress returns 0, someone has hit Zorro's [Stop] button and the current broker operation must be aborted.

Returns:

Broker interface version number; currently 2.
  

BrokerLogin (char* User, char* Pwd, char* Type, char* Accounts): int

Login or logout to the broker's API server; called in [Trade] mode or for downloading historical price data. If the connection to the server was lost, f.i. due to to Internet problems or server weekend maintenance, Zorro calls this function repeatedly in regular intervals until it is logged in again. Make sure that the function internally detects the login state and returns safely when the user was still logged in.

Parameters:

User Input, User name for logging in, or NULL for logging out.
Pwd Input, Password for logging in.
Type Input, account type for logging in; either "Real" or "Demo".
Accounts Input / optional output, char[1024] array, intially filled with the account id from the account list. Can be filled with all user's account numbers as subsequent zero-terminated strings, ending with "" for the last string. When a list is returned, the first account number is used by Zorro for subsequent BrokerAccount calls.

Returns:

Login state: 1 when logged in, 0 otherwise.
 

BrokerTime (DATE *pTimeUTC): int

Optional function that sends a 'ping' to the server and returns connection status and server time. Repeatedly called in short intervals during the trading session. Can be used by the plugin for keeping the session open if required.

Parameters:

pTimeUTC Optional output, current server time in UTC / GMT+0 with no daylight saving. The DATE format (OLE date/time) is a double float value, counting days since midnight 30 December 1899, while hours, minutes, and seconds are represented as fractional days.

Returns:

0 when the connection to the server was lost (see remarks).
1 when the connection is ok, but the market is closed or trade orders are not accepted.
2 when the connection is ok and the market is open for trading at least one of the subscribed assets.

Remarks:

DATE convertTime(__time32_t t32)
{
  return (double)t32/(24.*60.*60.) + 25569.; // 25569. = DATE(1.1.1970 00:00)
} __time32_t convertTime(DATE date) { return (__time32_t)((date - 25569.)*24.*60.*60.);
}
 

BrokerRequest (string Path, string Method, string Data): string

Optional function for sending an arbitrary HTTP request to a REST API. Path is the relative URL including the query string, but without the endpoint root. If Method begins with '$', the request must be signed. If Method and Data are both 0, a GET request should be sent. The response is returned.
 

BrokerAsset (char* Asset, double *pPrice, double *pSpread, double *pVolume, double *pPip, double *pPipCost, double *pLotAmount, double *pMargin, double *pRollLong, double *pRollShort,double *pCommission): int

Subscribes an asset, and/or returns information about it. Zorro subscribes all used assets at the begin of the trading session. Price and spread for all assets are retrieved in TickTime intervals or when BrokerProgress was preciously called by the plugin. Other asset data is retrieved once per bar.

Parameters:

Asset Input, asset symbol for live prices (see Symbols).
pPrice Optional output, current ask price of the asset, or NULL for subscribing the asset. An asset must be subscribed before any information about it can be retrieved.
pSpread Optional output, the current difference of ask and bid price of the asset.
pVolume Optional output, a parameter reflecting the current supply and demand of the asset. Such as trade volume per minute, accumulated daily trade volume, open interest, ask/bid volume, or tick frequency. If a value is returned, it should be consistent with the fVol content of the T6 struct in BrokerHistory2 (see below)..
pPip Optional output, size of 1 PIP, f.i. 0.0001 for EUR/USD.
pPipCost Optional output, cost of 1 PIP profit or loss per lot, in units of the account currency. If not directly supported, calculate it as decribed under asset list.
pLotAmount Optional output, minimum order size, i.e. number of contracts for 1 lot of the asset. For currencies it's usually 10000 with mini lot accounts and 1000 with micro lot accounts. For CFDs it's usually 1, but can also be a fraction of a contract, like 0.1.
pMargin Optional output, either initial margin cost for buying 1 lot of the asset in units of the account currency. Or the leverage of the asset when negative (f.i. -50 for 50:1 leverage).
pRollLong Optional output, rollover fee for long trades, i.e. interest that is added to or subtracted from the account for holding positions overnight. The returned value is the daily fee per 10,000 contracts for currencies, and per contract for all other assets, in units of the account currency.
pRollShort Optional output, rollover fee for short trades.
pCommission Optional output, roundturn commission per 10,000 contracts for currencies, per contract for all other assets, in units of the account currency.

Returns:

1 when the asset is available and the returned data is valid, 0 otherwise. An asset that returns 0 after subscription will trigger Error 053, and its trading will be disabled.

Remarks:

double Price = MarketInfo(Asset,MODE_ASK);
double Spread = Price - MarketInfo(Asset,MODE_BID);
double Volume = 0;
double LotFactor = MarketInfo(Asset,MODE_MINLOT); // correction for different lot scale
double Pip = MarketInfo(Asset,MODE_POINT);
double PipCost = MarketInfo(Asset,MODE_TICKVALUE) * LotFactor;
int DigitSize = MarketInfo(Asset,MODE_DIGITS); // correction for brokers with 5 digits if(DigitSize == 3 || DigitSize == 5) { Pip *= 10.;
PipCost *= 10.; }
double MinAmount = MarketInfo(Asset,MODE_LOTSIZE) * LotFactor;
double Margin = MarketInfo(Asset,MODE_MARGINREQUIRED) * LotFactor; double RollLong = MarketInfo(Asset,MODE_SWAPLONG); double RollShort = MarketInfo(Asset,MODE_SWAPSHORT);
if(MarketInfo(Asset,MODE_SWAPTYPE) == 0.) { RollLong *= PipCost; RollShort *= PipCost; }

BrokerHistory2 (char* Asset, DATE tStart, DATE tEnd, int nTickMinutes, int nTicks, T6* ticks): int

Returns the price history of an asset. Called by Zorro's assetHistory function and at the begin of a trading session for filling the lookback period.

Parameters:

Asset Input, asset symbol for historical prices (see Symbols).
tStart Input, UTC start date/time of the price history (see BrokerTime about the DATE format). This has only the meaning of a seek-no-further date; the relevant date for the begin of the history is tEnd.
tEnd Input, UTC end date/time of the price history. If the price history is not available in UTC time, but in the brokers's local time, the plugin must convert it to UTC.
nTickMinutes Input, time period of a tick in minutes. Usual values are 0 for single price ticks (T1 data; optional), 1 for one-minute (M1) historical data, or a larger value for more quickly filling the LookBack period before starting a strategy.
nTicks Input, maximum number of ticks to be filled; must not exceed the number returned by brokerCommand(GET_MAXTICKS,0), or 300 otherwise.
ticks Output, array of T6 structs (defined in include\trading.h) to be filled with the ask prices, close time, and additional data if available, such as historical spread and volume. See history for details. The ticks array is filled in reverse order from tEnd on until either the tick time reaches tStart or the number of ticks reaches nTicks, whichever happens first. The most recent tick, closest to tEnd, is at the start of the array. In the case of T1 data, or when only a single price is available, all prices in a TICK struct can be set to the same value.

Returns:

Number of ticks returned, or 0 when no ticks could be returned, f.i. when the server was offline, the asset was not subscribed, or price history was not available for the given date/time.
 

BrokerAccount (char* Account, double *pBalance, double *pTradeVal, double *pMarginVal): int

Optional function. Is called by Zorro in regular intervals and returns the current account status. Is also used to change the account if multiple accounts are supported. If the BrokerAccount function is not provided, f.i. when using a FIX API, Zorro estimates balance, equity, and margin from initial values and trade results.

Parameters:

Account Input, new account name or number, or NULL for using the current account.
pBalance Optional output, current balance on the account.
pTradeVal Optional output, current value of all open trades; the difference between account equity and returned balance value. If not available, Zorro estimes the equity from balance and value of all open trades. If no balance was returned, the account equity can be returned in pTradeVal.
pMarginVal Optional output, current total margin bound by all open trades. If not

Returns:

1 when the account is available and the returned data is valid, 0 when a wrong account was given or the account was not found.
 

BrokerBuy2 (char* Asset, int Amount, double StopDist, double Limit, double *pPrice, int *pFill): int

Sends an order to open a long or short position, either at market, or at a price limit. Also used for NFA compliant accounts to close a position by opening a new position in the opposite direction. The order type (FOK, IOC, GTC) can be set with SET_ORDERTYPE before. Orders other than GTC are cancelled when they are not completely filled within the wait time (usually 30 seconds).

Parameters:

Asset Input, asset symbol for trading (see Symbols).
Amount Input, number of contracts, positive for a long trade and negative for a short trade. For currencies or CFDs, the number of contracts is the number of Lots multiplied with the LotAmount. If LotAmount is < 1 (f.i. for a CFD or a fractional share with 0.1 contracts lot size), the number of lots is given here instead of the number of contracts.
StopDist Optional input, 'safety net' stop loss distance to the opening price when StopFactor was set, or 0 for no stop, or -1 for indicating that this function was called for closing a position. This is not the real stop loss, which is handled by Zorro. Can be ignored if the API is NFA compliant and does not support a stop loss in a buy/sell order.
Limit Optional input, ask/bid entry price for limit orders, set up by OrderLimit, or 0 for market orders. Can be ignored if limit orders are not supported by the API. 
pPrice Optional output, the fill price if the position was partially or fully filled.
pFill Optional output, the fill amount.

Returns:

BrokerTrade (int nTradeID, double *pOpen, double *pClose, double *pCost, double *pProfit): int

Optional function that returns the order fill state (for brokers that support only orders and positions) or the trade state (for brokers that support individual trades). Called by Zorro for any unfilled order or open trade when the price moved by more than 1 pip, or when contractUpdate or contractPrice is called for an option or future trade.

Parameters:

nTradeID Input, order ID or trade ID as returned by BrokerBuy,  or -1 when the trade UUID was set before with a SET_UUID command.
pOpen Optional output, the average fill price if the trade was partially or fully filled. If not available by the API, Zorro will estimate the values based on last price and asset parameters.
pClose Optional output, current bid or ask close price of the trade.
pCost Optional output, total rollover fee (swap fee) of the trade so far.
pProfit Optional output, current profit or loss of the trade in account currency units, without rollover and commission.

Returns:

BrokerSell2 (int nTradeID, int nAmount, double Limit, double *pClose, double *pCost, double *pProfit, int *pFill): int

Optional function; closes a trade - completely or partially - at market or at a limit price. If partial closing is not supported, nAmount is ignored and the trade is completely closed. Only for not NFA compliant accounts that support individual closing of trades. If this function is not provided or if the NFA flag is set, Zorro closes the trade by calling BrokerBuy2 with the negative amount and with StopDist at -1.

Parameters:

nTradeID Input, trade ID as returned by BrokerBuy2, or -1 for a UUID to be set before with a SET_UUID command.
nAmount Input, number of contracts resp. lots to be closed, positive for a long trade and negative for a short trade (see BrokerBuy). If less than the original size of the trade, the trade is partially closed.
Limit Optional input, ask/bid price for a limit order, set up by OrderLimit, or 0 for closing at market. Can be ignored if limit orders are not supported by the API. 
pClose Optional output, close price of the trade.
pCost Optional output, total rollover fee (swap fee) of the trade.
pProfit Optional output, total profit or loss of the trade in account currency units.
pFill Optional output, the fill amount.
   

Returns:

BrokerCommand (int nCommand, DWORD dwParameter): var

Optional function. Sets various plugin parameters or returns asset specific extra data. This function is not mandatory, as it is not used by Zorro's trade engine; but it can be called in scripts through the brokerCommand function for special purposes.

Parameters:

nCommand Input, command from the brokerCommand list.
dwParameter Input, parameter or data to the command.

Returns:

0 when the command is not supported by this broker plugin, otherwise the data to be retrieved.

 

Remarks:

Example: see Source folder

See also:

Brokers, Symbols, brokerCommand, enter, order, DLL, IB, FXCM, Oanda, MT4

► latest version online