Original (English)

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 Zorro S users 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; for this 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:

  • Simulation is a simple 'broker simulation' plugin that generates random prices and allows to open a trade with an arbitrary asset. Use it in NFA mode.
  • Bittrex is a REST API plugin for the Bittrex crypto exchange.
  • AllyInvest is a Github snaphot of a real broker plugin.

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 Short] - 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:

  • If the UTC server time is not available in the broker API, *pTimeUTC can be left unchanged. If the market state is not available, let the function just return 2 or 0 dependent on whether the connection is established or not.
  • If the server time is returned, but does not change for several minutes, Zorro assumes that the broker server is offline. It then displays "Offline" in the server window, and suspends trading and requesting price quotes.
  • If the broker API uses a different time format, here's a C++ code example for converting DATE to/from the Linux time format, which is the number of seconds since January 1st 1970 midnight:
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.

Remarks:

  • If parameters are not supplied by the broker API, they can be left unchanged. Zorro will then use default values from the asset list. Only price and spread must always be returned when the pPrice and pSpread parameters are nonzero.
  • For receiving streaming price data, get the Zorro window handle from the SET_HWND command for sending messages to a Zorro window. The message WM_APP+1 triggers a price quote request.
  • Dependent on the broker API, some asset parameters might require unit conversions because lots and pips can have special meanings. In most APIs, such as the FXCM API, the parameters are directly available. A more complicated example is the MT4™ API where the parameters must be corrected by the different scales of "Lot" and "Point" (MQ4 example):
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;
}
    
  • Asset parameters can be different dependent on when they are requested. For instance, some brokers charge a three times higher rollover fee on Wednesday for compensating the weekend. Spreads are usually higher when the market is closed or illiquid.
  • If the broker API can not subscribe an asset, it must be manually subscribed in the broker platform or website.

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 ticks (for T1 or T2 data; all prices of a T6 struct get the tick price), 1 for one-minute (M1) historical candles, or a larger value for low-resolution data.
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 or T2 data, or when only a single price is available, all prices in a T6 struct must 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.

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 units, positive for a long trade and negative for a short trade. For currencies or CFDs, the number of units is the number of Lots multiplied with the LotAmount. If LotAmount is < 1 (f.i. for a CFD, or for a fractional share with 0.1 contracts lot size), the number of lots is given here instead of the number of units.
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, fill 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 average fill price if the position was partially or fully filled. If no price was set, Zorro assumes the current price.
pFill Optional output, the fill amount (positive), or 0 for an unfilled order. If no amount was set, Zorro assumes a complete fill.

Returns:

  • 0 or 1 when the order was rejected or when a FOK or IOC order was unfilled within the wait time (adjustable with the SET_WAIT command). An unfilled FOK or IOC order must be cancelled by the plugin.
  • Unique trade or order ID number when the order was successfully placed. If the broker API does not provide trade or order IDs, the plugin should generate a unique 6-digit number, f.i. from a counter, and return it as a trade ID.
  • -1 when the trade or order identifier is a UUID that is then retrieved with the GET_UUID command.
  • -2 when the broker API did not respond within the wait time, so the order state is unknown. The plugin must then cancel the order. Zorro will display a "possible orphan" warning.
  • -3 when the order was accepted, but got no ID yet. The ID is then taken from the next subsequent BrokerBuy call that returned a valid ID. This is used for combo positions that require several orders.

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 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/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. If not available, Zorro will estimale the value based on current ask price and ask-bid spread.
pCost Optional output, total rollover fee (swap fee) of the trade so far. If not available, Zorro will estimate the swap from the asset parameters.
pProfit Optional output, current profit or loss of the trade in account currency units, without rollover and commission. If not available, Zorro will estimate the profit from the difference of current price and fill price.

Returns:

  • Current fill amount in units or lots as in BrokerBuy2.
  • -1 when the trade was completely closed.
  • NAY (defined in trading.h) when the order or trade state was unavailable. Zorro will then assume that the order was completely filled, and keep the trade open.
  • NAY-1 when the order was cancelled or removed by the broker. Zorro will then cancel the trade and book the profit or loss based on the current price and the last fill amount.

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 used 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/order 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, fill 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 amount that was closed from the position, always positive.

Returns:

  • New trade ID when the trade was partially closed and the broker assigned a different ID to the remaining position.
  • nTradeID when the ID did not change or the trade was fully closed.
  • 0 when the trade was not found or could not be closed.
     

BrokerCommand (int Command, ...): var

Optional function, directly called by the brokerCommand function for setting special modes or retrievong special information from the broker API.

 

Remarks:

  • A broker DLL must contain at least the BrokerOpen function for being recognized by Zorro and appearing in the scrollbox.
  • Functions ending with '2' replace older functions that are however still supported. For instance, BrokerHistory2 replaced BrokerHistory, but old plugins with BrokerHistory will still work.
  • The broker plugin has full access to all HTTP and other Zorro functions with the SET_FUNCTIONS command. The old BrokerHTTP function is no longer needed, but still supported.
  • Date/Time parameters and historical time stamps should be UTC. If GET_BROKERZONE is supported and returns a different time zone, they should be in that time zone.
  • If the connection breaks down, BrokerTime will be called in TickTime intervals for determining if it is still broken. If interrupted for a longer time, Zorro will attempt to re-login in increasing intervals from minutes to hours until the connection is established again.
  • If optional functions are not implemented or optional parameters not returned, Zorro replaces them with educated guesses and assumptions. For instance, if BrokerSell2 is not implemented, Zorro will assume that trades are closed by buying in opposite direction. If BrokerTrade is not implemented and thus the fill amount and fill price of GTC orders cannot be traced, Zorro will treat the order as if it were completely filled at the entry price, and will estimate the value of the position from the current price and entry price.
  • If BrokerTrade is implemented, it is automatically called in regular intervals for updating the fill amounts and values of all open positions, except for contracts. For contracts it is only called by contractUpdate or contractPrice, and is preceded by a SET_SYMBOL command with the current contract symbol.
  • For a script with low-level broker access, you can call the above functions of a broker plugin directly from your script. For this, open the plugin DLL with LoadLibrary or DefineApi as described under DLL / API implementation. The broker DLL may also contain other broker-specific functions that are not directly used by Zorro, but can be called this way from strategy scripts.
  • For passing struct pointers via BrokerProgress from the API to the Zorro script, make sure that struct member alignment is set to 4 bytes or less. Lite-C does not align or pad struct members.
  • For asynchronously triggering a price quote request, send a WM_APP+1 message to the window handle received by the SET_HWND command. For triggering the callback function, send a WM_APP+2 message. This can be used for prices streamed by another thread. An example for sending messages can be found under HWnd.
  • Some crypto exchanges require HMAC authentication signatures for transmitting orders. There is public C++ code for that in many code libraries on Github (search for f.i. sha512.cpp).
  • Since Zorro broker plugins are standard 32-bit DLLs, they can also be used by third party software. For instance, the above functions can be called from Python using the ctypes library.

Example: see Source folder

See also:

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

► latest version online

Übersetzung (Deutsch)

Entwicklung von Broker- / Data-Feed-Plugins

Zorro unterstützt die meisten großen brokers entweder über eine direkte Verbindung oder über eine vom Broker unterstützte Plattform, zum Beispiel über die MT4/5 bridge oder die Sierra bridge. Eine direkte Verbindung zu einer Broker-API, einer Börse, einem Market Data Feed oder einer Plattform wird über eine DLL im Plugin-Ordner von Zorro hergestellt. Zorro durchsucht diesen Ordner beim Start automatisch und listet alle gültigen DLLs in der [Broker / Account]-Auswahl auf. Die DLL nutzt die API des Brokers, um Orders auszuführen und Marktdaten abzurufen. Das Interface ist so organisiert, dass die DLL so einfach wie möglich bleibt.
  Für automatisiertes Trading sind nur wenige Funktionen notwendig. Zusätzliche Funktionalität, zum Beispiel spezielle Order-Typen oder besondere Daten, kann über einen optionalen broker command hinzugefügt werden. Wer programmieren kann und Zugang zur Broker-API-Dokumentation hat, kann eine Broker-DLL in wenigen Stunden schreiben. Um historische Daten im CSV- oder JSON-Format von online data sources herunterzuladen, braucht man keine DLL; ein kleines Script genügt (siehe assetHistory).

Broker-Plugin schreiben

Plugins können in jeder Sprache geschrieben werden, die DLLs unterstützt, etwa Java, Pascal, C# oder C++. Viele Plugins wurden von Zorro-Anwendern verfasst, meist in C++. Wir belohnen sauber in C++ geschriebene Plugins mit einer kostenlosen Zorro S-Subscription, Lizenz oder Verlängerung. Als Ausgangspunkt kann man das Plugin für eine Kryptowährungs-REST-API verwenden, das im Source-Ordner von Zorro zu finden ist. Der Quellcode anderer von Zorro-Anwendern entwickelter Plugins ist auf den entsprechenden GitHub-Seiten der Autoren verfügbar.

Einen Artikel über das Schreiben eines Broker-Plugins findet man auf Financial Hacker.

Der Quellcode zu enthaltenen Broker-Plugins kann auf Anfrage von Zorro-S-Nutzern, die ein ähnliches Plugin für die Community entwickeln, angefordert werden. Bitte kontaktieren Sie uns mit einer kurzen Beschreibung Ihres Projekts und Ihrer bisherigen C++-Erfahrung. Ein Non-Disclosure-Agreement muss unterzeichnet werden, und der fertige Plugin-Code wird zur Prüfung an uns zurückgeschickt. Technischer Support ist kostenlos für die Entwicklung von Broker-Plugins; hierfür sind kein Support-Ticket oder eine Zorro-S-Subscription nötig.

Man kann uns auch bezüglich Outsourcing einer Plugin-Entwicklung kontaktieren.

Einrichtung von VC++

Wie man ein VC++-DLL-Projekt mit Zugriff auf alle Zorro-Funktionen erstellt, ist unter VC++ project setup beschrieben. Zorro-Funktionen wie zum Beispiel HTTP-Anfragen oder Signaturen sind oft nützlich für die Implementierung. Wer jedoch eine reine DLL ohne Zorro-Funktionen möchte, bindet nicht die Datei ZorroDll.cpp, sondern die automatisch von VC++ erstellte Datei dllmain.cpp ein. Deren DllMain-Funktion ist der Haupteinstiegspunkt für die Broker-DLL und kann unverändert bleiben. Broker-Funktionen benötigen die Datentypen DATE und T6, daher müssen DATE definiert und trading.h eingebunden werden, zum Beispiel so:

typedef double DATE;
#include <trading.h>
    

Wenn Ihre Broker-DLL Zorro-spezifische Structs verwendet, setzen Sie vor dem Einbinden von trading.h das Struct-Alignment mit #pragma pack(4) auf 4. Andernfalls haben Structs in Zorro und in Ihrer DLL unterschiedliche Größen.

Damit eine DLL im Auswahlmenü erscheint, muss sie sich im Ordner Plugin befinden. Zorro prüft beim Start zuerst, ob sich die DLL mit LoadLibrary() laden lässt. Falls ja, wird geprüft, ob eine Funktion BrokerOpen (siehe unten) existiert und ob diese eine gültige Versionsnummer zurückgibt. Sind beide Bedingungen erfüllt, wird die DLL registriert und im Auswahlmenü aufgeführt. LoadLibrary schlägt fehl, wenn DllMain nicht ordnungsgemäß zurückkehrt. Häufige Ursachen sind die Erstellung einer falschen DLL (z.B. 64-bit oder MFC) oder fehlende Abhängigkeiten. Je komplexer die verwendeten Bibliotheken sind, desto eher besteht die Gefahr, dass die DLL auf anderen Rechnern nicht funktioniert. Um auf Nummer sicher zu gehen, sollten alle benötigten Module in der Distribution enthalten sein. Im Zweifelsfall kann man die Abhängigkeiten der DLL mit DependencyWalker überprüfen. Zum Debuggen setzt man Breakpoints in DllMain und BrokerOpen und überprüft, was passiert, wenn Zorro startet.

Auf Financial Hacker gibt es eine Schritt-für-Schritt-Anleitung zur Implementierung einer REST-API-DLL.

Entwicklung und Test

Im Ordner Source befinden sich Beispiele für Broker-Plugins in .zip-Archiven:

  • Simulation ist ein einfaches "broker simulation"-Plugin, das Zufallspreise erzeugt und das Öffnen eines Trades mit einem beliebigen Asset ermöglicht. Verwenden Sie es im NFA-Modus.
  • Bittrex ist ein REST-API-Plugin für die Bittrex-Krypto-Börse.
  • AllyInvest ist ein GitHub-Snapshot eines echten Broker-Plugins.

Weitere Zorro-Broker-Plugins findet man auf GitHub. Verwenden Sie das am besten geeignete als Vorlage für Ihr eigenes Plugin. Implementieren Sie die DLL-Funktionen (siehe unten) in folgender Reihenfolge: BrokerOpen, BrokerLogin, BrokerAsset, BrokerBuy2. Diese 4 Funktionen (unten beschrieben) sind das Minimum, um mit dem Broker zu traden. Optional können folgende Funktionen implementiert werden, wenn sie von der API unterstützt werden: BrokerAccount, BrokerHistory2, BrokerTime, BrokerTrade, BrokerSell2, BrokerStop. Jede fertig implementierte Funktion sollte man mit dem TradeTest-Script testen.

Einige Funktionen müssen nicht vollständig implementiert werden, oder gar nicht. Für das TradeTest-Script genügen BrokerOpen und BrokerLogin. Wenn z.B. BrokerAsset noch fehlt, simuliert Zorro dieses mit Standardwerten. So kann man Schritt für Schritt die Funktionen hinzufügen und jeweils testen.

Sobald BrokerAsset korrekt implementiert ist, sollte im Server-Fenster der aktuelle Preis erscheinen. Das TradeTest-Script öffnet ein Panel mit folgenden Buttons zum Test verschiedener Broker-Funktionen:

[Auto On/Off] - Umschalten für eine simulierte Trading-Session, die automatisch jede Minute einen Trade eröffnet oder schließt.

[NFA On/Off] - Umschalten des NFA-Flags. In den meisten US-Konten notwendig; für die meisten Forex/CFD-Konten nicht aktivieren.

[Hedge] - Umschalten verschiedener Hedge-Modi (0, 2, 4 und 5). Manche Broker unterstützen kein echtes Hedging (Modus 2) oder kein Teil-Schließen (Modus 5).

[Order] - Umschalten zwischen Limit (LMT), Market Orders (MKT), Good-til-cancelled (GTC) und Adaptive Orders (Adaptive), falls vom Plugin unterstützt.

[Asset] - Eingabe des zu handelnden Asset-Symbols (Vorgabe: Asset aus der Auswahlliste).

[Buy Long] - Eröffnung einer Long-Position mit der in den Slidern eingestellten Lots- und Stop-Größe.

[Buy Short] - Eröffnung einer Short-Position. Abhängig von Hedge wird eine offene Position in entgegengesetzter Richtung geschlossen.

[Close Long] - Schließt die angegebene Lots-Anzahl einer offenen Long-Position. Teilweises Schließen wird von einigen Brokern nicht unterstützt.

[Close Short] - Schließt die angegebene Lots-Anzahl einer offenen Short-Position.

[Update Stop] - Setzt den Stop aller offenen Positionen auf den per Slider angegebenen Wert (in Pips). Nicht alle Broker unterstützen eine nachträgliche Stop-Anpassung. Durch StopFactor liegt der Broker-Stop meist weiter entfernt als der eigentliche Stop.

Mit LMT-Orders wird versucht, die Position zum halben Spread zu eröffnen, Adaptive Orders versuchen es zum Spread = 0. Dafür muss der Broker echte Limit-Orders unterstützen; MT4-"Pending Orders" sind keine echten Limit Orders und funktionieren nicht für LMT oder Adaptive. Verschiedene Trading-Modi, Broker Commands, Asset-Listen usw. können in #define-Anweisungen am Anfang des TradeTest-Scripts eingestellt werden.

Broker-API-Funktionen

Die Broker-DLL exportiert Funktionen, die in der folgenden Liste beschrieben sind. Unter VC++ müssen exportierte DLL-Funktionen entweder mit extern "C" __declspec(dllexport) deklariert oder in einer .def-Datei aufgeführt werden. Die DLL-Funktionen nutzen nur einen kleinen Teil einer üblichen Broker-API. In der folgenden Liste können Pointer-Argumente, die kursiv geschrieben sind, NULL sein; falls sie ungleich 0 sind, muss die Funktion die entsprechenden Daten eintragen. Alle Daten sind obligatorisch, sofern nicht anders vermerkt.

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

Wird beim Start für alle im Ordner Plugin gefundenen Broker-DLLs aufgerufen. Ruft den Namen des Brokers ab und setzt zwei Callback-Funktionen. Sollte keine Ressourcen laden oder allozieren und keine Zorro-Funktionen aufrufen; all das kann in BrokerLogin geschehen.

Parameter:

Name Ausgabe, char[32]-Array, das mit dem Namen des Brokers gefüllt werden soll, z.B. "FXCM". Dieser Name wird im Account-Menü angezeigt und dient der Auswahl des Plugins.
fpMessage Eingabe, Zeiger auf die Funktion int BrokerMessage(const char* Message). Das Plugin kann BrokerMessage aufrufen, um Nachrichten - üblicherweise Fehler - in Zorros Nachrichtenfenster auszugeben. Der Gebrauch dieser Funktion ist nicht zwingend, aber empfehlenswert. Beginnt der String mit einem Ausrufezeichen '!', öffnet Zorro ein Alert-Fenster. Beginnt er mit einem Hash '#', wird er nur in die Diagnosedatei geschrieben.
fpProgress Eingabe, Zeiger auf die Funktion int BrokerProgress(intptr_t Progress). Diese kann vom Plugin regelmäßig aufgerufen werden, um Zorro während längerer Vorgänge (z.B. BrokerHistory2) reaktionsfähig zu halten. Ist Progress = 0, aktualisiert die Zorro-Oberfläche nur ihre Steuerelemente. Ist Progress = 1, werden im Nachrichtenfenster Punkte gedruckt, um den Fortschritt eines zeitintensiven Ablaufs anzuzeigen. Handelt es sich bei Progress um einen Pointer und existiert im Skript eine callback-Funktion, wird diese Funktion aufgerufen und der Pointer übergeben, um Skriptfunktionen aus der Broker-API heraus auszulösen. Liefert BrokerProgress = 0 zurück, hat der Nutzer den [Stop]-Knopf gedrückt, sodass der aktuelle Broker-Vorgang abgebrochen werden muss.

Rückgabewert:

Die Version der Broker-Schnittstelle; momentan 2.
  

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

Login oder Logout beim Broker-API-Server; wird im [Trade]-Modus oder zum Herunterladen historischer Preisdaten aufgerufen. Falls die Verbindung zum Server abgebrochen ist (z.B. durch Internetprobleme oder Wartungsarbeiten am Wochenende), ruft Zorro diese Funktion in regelmäßigen Abständen auf, bis eine erneute Anmeldung erfolgreich ist. Die Funktion sollte intern den Login-Status erkennen und eine sichere Rückgabe liefern, falls der Anwender noch eingeloggt ist.

Parameter:

User Eingabe, Benutzername zur Anmeldung oder NULL zum Logout.
Pwd Eingabe, Passwort zur Anmeldung.
Type Eingabe, Kontotyp; entweder "Real" oder "Demo".
Accounts Eingabe / optional Ausgabe, char[1024]-Array, initial gefüllt mit der Kontonummer aus der account list. Das Plugin kann dieses Array mit allen Kontonummern füllen, jeweils per Null-Terminierung getrennt, und am Ende mit "" abschließen. Wenn mehrere Konten zurückgegeben werden, wählt Zorro das erste Konto für alle BrokerAccount-Aufrufe.

Rückgabewert:

1 bei erfolgreichem Login, sonst 0.
 

BrokerTime (DATE *pTimeUTC): int

Optionale Funktion, die einen "Ping" an den Server sendet und den Verbindungsstatus sowie die Serverzeit abfragt. Wird in kurzen Abständen während der Trading-Session aufgerufen. Kann vom Plugin genutzt werden, um die Session offen zu halten, falls nötig.

Parameter:

pTimeUTC Optionale Ausgabe, aktuelle Serverzeit in UTC / GMT+0 ohne Sommerzeit. Das Format DATE (OLE date/time) ist ein double-Wert, der die Tage seit Mitternacht am 30. Dezember 1899 zählt; Stunden, Minuten und Sekunden sind dabei als Teil dieses Tageswerts abgebildet.

Rückgabewert:

0, wenn die Verbindung zum Server verloren wurde (siehe Anmerkungen).
1, wenn die Verbindung steht, der Markt aber geschlossen ist oder keine Orders angenommen werden.
2, wenn die Verbindung steht und der Markt für Trading bei mindestens einem der abonnierten Assets geöffnet ist.

Anmerkungen:

  • Falls die UTC-Serverzeit nicht von der Broker-API geliefert wird, kann *pTimeUTC unverändert bleiben. Wenn der Marktstatus unbekannt ist, genügt es, 2 oder 0 je nach bestehender oder fehlender Verbindung zurückzugeben.
  • Wenn die Serverzeit mehrere Minuten lang konstant bleibt, nimmt Zorro an, dass der Server offline ist. Dann zeigt Zorro "Offline" im Server-Fenster an und pausiert Trading und Kursabfragen.
  • Wenn das Broker-API ein anderes Zeitformat nutzt, hier ein C++-Beispiel zum Konvertieren von DATE in das Linux-Zeitformat (Sekunden seit 1.1.1970 Mitternacht) und umgekehrt:
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

Optionale Funktion für das Senden einer beliebigen HTTP-Anfrage an eine REST-API. Path ist die relative URL inklusive Query-String, aber ohne den Endpunkt ("Root"). Wenn Method mit "$" beginnt, muss die Anfrage signiert werden. Wenn Method und Data beide 0 sind, sollte eine GET-Anfrage gesendet werden. Die Antwort wird zurückgegeben.
 

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

Abonniert ein Asset und/oder gibt Informationen darüber zurück. Zorro abonniert alle verwendeten Assets zu Beginn einer Trading-Session. Preis und Spread für alle Assets werden in TickTime-Abständen oder dann abgerufen, wenn vom Plugin zuvor BrokerProgress aufgerufen wurde. Andere Asset-Daten werden einmal pro Bar abgefragt.

Parameter:

Asset Eingabe, Asset-Symbol für Live-Preise (siehe Symbols).
pPrice Optionale Ausgabe, aktueller Ask-Preis des Assets oder NULL zum reinen Abonnieren des Assets. Ein Asset muss abonniert sein, bevor es Infos dazu geben kann.
pSpread Optionale Ausgabe, die aktuelle Differenz zwischen Ask- und Bid-Preis des Assets.
pVolume Optionale Ausgabe, ein Parameter, der das aktuelle Angebot und die Nachfrage des Assets widerspiegelt (z.B. Handelsvolumen pro Minute, akkumuliertes Tagesvolumen, Open Interest, Ask/Bid-Volumen, Tick-Frequenz). Falls ein Wert zurückgegeben wird, sollte dieser konsistent zum Wert fVol in den T6-Strukturen von BrokerHistory2 sein (siehe unten).
pPip Optionale Ausgabe, die Größe eines PIPs, z.B. 0.0001 bei EUR/USD.
pPipCost Optionale Ausgabe, Gewinn/Verlust-Kosten pro 1 PIP und Lot in Einheiten der Kontowährung. Wenn nicht direkt verfügbar, nach asset list-Methode berechnen.
pLotAmount Optionale Ausgabe, Mindesthandelsgröße, d.h. Anzahl Kontrakte für 1 Lot des Assets. Bei Währungspaaren sind das meist 10.000 in Mini-Lot-Konten und 1.000 in Micro-Lot-Konten. Bei CFDs ist es oft 1, manchmal aber auch nur 0.1 Kontrakte.
pMargin Optionale Ausgabe, entweder die Initial Margin für den Kauf von 1 Lot in Einheiten der Kontowährung oder bei negativem Wert den Hebel (z.B. -50 für 50:1 Leverage).
pRollLong Optionale Ausgabe, Rollover-Gebühr für Long-Trades (Zinsen, die pro Nacht auf dem Konto gutgeschrieben oder belastet werden). Der Wert ist die tägliche Gebühr pro 10.000 Kontrakte bei Währungspaaren bzw. pro Kontrakt bei allen anderen Assets, gemessen in Einheiten der Kontowährung.
pRollShort Optionale Ausgabe, Rollover-Gebühr für Short-Trades.
pCommission Optionale Ausgabe, Roundturn-Kommission pro 10.000 Kontrakte bei Währungspaaren bzw. pro Kontrakt bei allen anderen Assets, in Einheiten der Kontowährung.

Rückgabewert:

1, wenn das Asset verfügbar ist und gültige Daten liefert, 0 sonst.

Anmerkungen:

  • Wenn die Parameter nicht von der Broker-API bereitgestellt werden, können sie unverändert bleiben. Zorro nutzt dann die Standardwerte aus der asset list. Nur Preis und Spread müssen immer zurückgegeben werden, wenn pPrice und pSpread ungleich NULL sind.
  • Um streaming price data zu empfangen, kann über den SET_HWND-Befehl das Handle zum Zorro-Fenster abgefragt werden. Eine Nachricht vom Typ WM_APP+1 an dieses Fenster triggert dann das Abfragen neuer Kurse.
  • Abhängig vom Broker-API können einige Asset-Parameter Konvertierungen erfordern, da Lots und Pips unterschiedlich definiert sein können. In vielen APIs (z.B. FXCM) sind sie direkt verfügbar. Ein komplizierteres Beispiel ist die MT4™-API, bei der die Werte aufgrund unterschiedlicher Skalen für "Lot" und "Point" korrigiert werden müssen (MQ4-Beispiel):
double Price = MarketInfo(Asset,MODE_ASK);
double Spread = Price - MarketInfo(Asset,MODE_BID);
double Volume = 0;
double LotFactor = MarketInfo(Asset,MODE_MINLOT); // Korrektur für unterschiedliche Lot-Skalen
double Pip = MarketInfo(Asset,MODE_POINT);
double PipCost = MarketInfo(Asset,MODE_TICKVALUE) * LotFactor;
int DigitSize = MarketInfo(Asset,MODE_DIGITS); // Korrektur bei 5-stelligen Kursen
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;
}
    
  • Asset-Parameter können je nach Zeitpunkt unterschiedlich sein. Zum Beispiel berechnen manche Broker mittwochs dreifache Rollover-Gebühren, um das Wochenende abzudecken. Spreads sind bei geschlossenen oder illiquiden Märkten in der Regel höher.
  • Wenn das Broker-API kein Asset-Abonnement unterstützt, muss man das Asset eventuell manuell in der Broker-Plattform oder auf der Website abonnieren.

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

Liefert die Preishistorie eines Assets. Aufgerufen durch assetHistory und zu Beginn einer Trading-Session, um den lookback-Zeitraum zu füllen.

Parameter:

Asset Eingabe, Asset-Symbol für historische Preise (siehe Symbols).
tStart Eingabe, UTC-Startdatum/-zeitpunkt der Preishistorie (siehe BrokerTime zum DATE-Format). Dieser Wert ist nur ein "nicht weiter zurück"-Zeitpunkt; das wesentliche Startdatum ist tEnd.
tEnd Eingabe, UTC-Enddatum/-zeitpunkt der Preishistorie. Wenn die Preishistorie nicht in UTC, sondern in lokaler Brokerzeit vorliegt, muss das Plugin die Zeit selbst nach UTC umrechnen.
nTickMinutes Eingabe, Zeitspanne eines Ticks in Minuten. Übliche Werte sind 0 für Einzelticks (T1- oder T2-Daten, wobei alle Preise in einem T6 gleich gesetzt werden), 1 für 1-Minuten-Kerzen (M1) oder ein größerer Wert für geringere Auflösung.
nTicks Eingabe, maximale Anzahl an Ticks, die gefüllt werden sollen; darf den Wert von brokerCommand(GET_MAXTICKS,0) nicht überschreiten oder sonst 300.
ticks Ausgabe, Array von T6-Strukturen (definiert in include\trading.h), das mit Ask-Preisen, Endzeit der Kerze und weiteren verfügbaren Daten wie historischem Spread und Volumen gefüllt werden soll. Siehe history. Das Array ticks wird in umgekehrter Reihenfolge befüllt, beginnend bei tEnd, bis entweder tStart erreicht oder die Anzahl nTicks ausgeschöpft ist. Der jüngste Tick (nahe tEnd) steht vorn im Array. Bei T1- oder T2-Daten bzw. wenn nur ein einzelner Preis verfügbar ist, müssen alle Preise in einer T6-Struktur gleich sein.

Rückgabewert:

Anzahl der gelieferten Ticks oder 0, falls keine Ticks geliefert werden konnten (z.B. Server offline, Asset nicht abonniert oder Historie nicht verfügbar für den angegebenen Zeitraum).
 

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

Optionale Funktion. Wird regelmäßig von Zorro aufgerufen und soll die aktuellen Kontodaten liefern. Außerdem kann hier das Konto gewechselt werden, falls mehrere Konten unterstützt werden. Ist diese Funktion nicht vorhanden (z.B. bei FIX-APIs), schätzt Zorro Kontostand, Equity und Margin anhand anfänglicher Werte und der realisierten sowie offenen Trades.

Parameter:

Account Eingabe, neue Kontonummer oder NULL für das aktuelle Konto.
pBalance Optionale Ausgabe, aktuelles Kontoguthaben.
pTradeVal Optionale Ausgabe, aktueller Wert aller offenen Trades; die Differenz aus Kontoequity und dem über pBalance gelieferten Guthaben. Falls nicht vorhanden, schätzt Zorro die Equity aus dem Kontostand und den offenen Trades. Wenn kein Guthaben pBalance zurückgegeben wird, kann hier die gesamte Equity stehen.
pMarginVal Optionale Ausgabe, gesamte derzeit gebundene Margin aller offenen Trades.

Rückgabewert:

1, wenn das Konto gefunden wird und gültige Werte liefert, 0, wenn ein falsches Konto angegeben wurde oder kein Konto gefunden werden konnte.
 

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

Sendet eine Order zum Öffnen einer Long- oder Short-Position, entweder als Market-Order oder mit Limit-Preis. Außerdem wird diese Funktion bei NFA-konformen Konten genutzt, um eine Position zu schließen, indem man eine Gegenposition eröffnet. Der Order-Typ (FOK, IOC, GTC) kann zuvor mit SET_ORDERTYPE gesetzt werden. Andere Order-Typen als GTC werden storniert, wenn sie innerhalb der wait time (in der Regel 30 Sekunden) nicht vollständig ausgeführt werden.

Parameter:

Asset Eingabe, Asset-Symbol für den Trade (siehe Symbols).
Amount Eingabe, Anzahl Einheiten, positiv für Long, negativ für Short. Bei Währungen oder CFDs ist dies die Anzahl an Lots multipliziert mit dem LotAmount. Ist LotAmount < 1 (z.B. bei CFDs oder Bruchstücken einer Aktie mit 0.1 Kontrakten), entspricht die Zahl hier den Lots anstatt den Einheiten.
StopDist Optionale Eingabe, Distanz des "safety net" StopLoss zum Eröffnungspreis, falls StopFactor gesetzt ist, oder 0 für keinen Stop, oder -1 als Kennzeichnung, dass hiermit eine Position geschlossen werden soll. Dies ist nicht der eigentliche StopLoss, der wird von Zorro verwaltet. Bei NFA-konformer API, die keinen StopLoss in Buy/Sell unterstützt, kann das ignoriert werden.
Limit Optionale Eingabe, Ausführungspreis für Limit-Orders, über OrderLimit konfiguriert, oder 0 für Market-Orders. Falls die API keine Limit-Orders erlaubt, ignorieren.
pPrice Optionale Ausgabe, durchschnittlicher Ausführungspreis, falls die Order teilweise oder vollständig gefüllt wurde. Wird kein Preis zurückgegeben, nimmt Zorro den aktuellen Preis an.
pFill Optionale Ausgabe, Füllmenge (positiv), oder 0 bei ungefüllter Order. Wird kein Wert übergeben, nimmt Zorro an, dass die Order vollständig ausgeführt wurde.

Rückgabewert:

  • 0 oder 1 bei Ablehnung oder falls eine FOK- oder IOC-Order innerhalb der wait time nicht gefüllt wurde (einstellbar mit SET_WAIT); in diesem Fall muss die Order vom Plugin storniert werden.
  • Eine eindeutige Trade- oder Order-ID, falls die Order erfolgreich platziert wurde. Stellt die API keine ID bereit, sollte das Plugin eine eindeutige 6-stellige ID erzeugen (z.B. über einen Zähler).
  • -1, wenn die Order/Trade-ID ein UUID ist, der anschließend über GET_UUID abgefragt wird.
  • -2 bei keiner Antwort der Broker-API während der wait time, sodass der Orderstatus unbekannt ist. Das Plugin muss die Order dann stornieren. Zorro zeigt "possible orphan" an.
  • -3, wenn die Order akzeptiert wurde, aber noch keine ID vorliegt. Die ID wird dann beim nächsten BrokerBuy-Aufruf, der eine gültige ID liefert, übernommen (verwendet bei Combo-Positionen, die mehrere Orders benötigen).

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

Optionale Funktion, die den Status einer Order oder eines Trades abfragt. Wird von Zorro bei jedem offenen Trade aufgerufen, sobald sich der Kurs um mehr als 1 Pip bewegt, oder durch contractUpdate bzw. contractPrice bei Futures/Optionen.

Parameter:

nTradeID Eingabe, Order/Trade-ID (von BrokerBuy) oder -1, wenn vorher ein UUID via SET_UUID gesetzt wurde.
pOpen Optionale Ausgabe, durchschnittlicher Ausführungspreis, falls die Position teilweise oder vollständig gefüllt wurde. Ist dieser Wert in der API nicht verfügbar, schätzt Zorro ihn anhand des letzten Preises und der Asset-Parameter.
pClose Optionale Ausgabe, aktueller Bid- oder Ask-Kurs zum Schließen der Position. Falls nicht vorhanden, ermittelt Zorro einen geschätzten Wert aus aktuellem Ask-Preis und Spread.
pCost Optionale Ausgabe, bisher angefallene Rollover- (Swap-)Gebühren für diesen Trade. Falls nicht verfügbar, schätzt Zorro den Swap basierend auf den Asset-Parametern.
pProfit Optionale Ausgabe, aktueller Gewinn oder Verlust des Trades in Kontowährung, ohne Rollover und Kommission. Falls nicht verfügbar, berechnet Zorro den Gewinn aus der Differenz von aktuellem Kurs und Ausführungspreis.

Rückgabewert:

  • Aktuelle gefüllte Menge (units oder lots) entsprechend BrokerBuy2.
  • -1 bei komplett geschlossenem Trade.
  • NAY (in trading.h definiert), wenn der Order-/Trade-Status unbekannt ist. Zorro nimmt dann an, dass die Order vollständig gefüllt wurde, und lässt den Trade offen.
  • NAY-1 bei stornierter oder entfernter Order durch den Broker. Zorro storniert in diesem Fall auch den Trade und verbucht den Gewinn/Verlust basierend auf dem aktuellen Preis und letzter Füllmenge.

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

Optionale Funktion zum (vollständigen oder teilweisen) Schließen eines Trades per Market-Order oder Limit-Order. Wenn Teil-Schließen nicht unterstützt wird, wird nAmount ignoriert und der Trade vollständig geschlossen. Nur relevant für nicht NFA-konforme Konten, die ein individuelles Schließen von Trades unterstützen. Falls diese Funktion fehlt oder das NFA-Flag gesetzt ist, schließt Zorro den Trade durch Aufruf von BrokerBuy2 mit negativem Amount und StopDist = -1.

Parameter:

nTradeID Eingabe, Order-/Trade-ID wie bei BrokerBuy2 geliefert, oder -1 für einen zuvor per SET_UUID gesetzten UUID.
nAmount Eingabe, Anzahl Kontrakte oder Lots, die geschlossen werden sollen (positiv bei Long, negativ bei Short, siehe BrokerBuy). Ist das weniger als die Gesamtgröße des Trades, wird nur teilweise geschlossen.
Limit Optionale Eingabe, Ausführungspreis für eine Limit-Order, wie über OrderLimit eingestellt, oder 0 für Market. Falls die API keine Limit-Orders unterstützt, ignorieren.
pClose Optionale Ausgabe, Kurs beim Schließen.
pCost Optionale Ausgabe, aufsummierte Rollover- (Swap-)Gebühren des Trades.
pProfit Optionale Ausgabe, Gesamtgewinn/-verlust in Kontowährung.
pFill Optionale Ausgabe, Menge (positiv), die von der Position geschlossen wurde.

Rückgabewert:

  • Neue Trade-ID, falls der Broker beim teilweisen Schließen eine andere ID für die Restposition vergibt.
  • nTradeID bei unveränderter ID oder vollständigem Schließen.
  • 0 bei nicht gefundenem oder nicht geschlossenem Trade.

BrokerCommand (int Command, ...): var

Optionale Funktion, die direkt durch brokerCommand aufgerufen wird, um spezielle Modi einzustellen oder besondere Informationen aus der Broker-API abzurufen.

 

Anmerkungen:

  • Eine Broker-DLL benötigt mindestens die Funktion BrokerOpen, um von Zorro erkannt zu werden und im Auswahlmenü zu erscheinen.
  • Funktionen mit Endung '2' ersetzen ältere Funktionen, die aber noch unterstützt werden. BrokerHistory2 ersetzt z.B. BrokerHistory, jedoch funktionieren alte Plugins mit BrokerHistory weiterhin.
  • Über den Befehl SET_FUNCTIONS kann das Broker-Plugin auf alle HTTP- und sonstigen Zorro-Funktionen zugreifen. Die ältere Funktion BrokerHTTP ist nicht mehr nötig, wird aber noch unterstützt.
  • Zeit- und Datumswerte sowie historische Zeitstempel sollten in UTC angegeben werden. Falls GET_BROKERZONE unterstützt wird und eine andere Zeitzone zurückliefert, sind diese Werte in dieser Zeitzone zu führen.
  • Bricht die Verbindung ab, ruft Zorro in TickTime-Abständen BrokerTime auf, um zu prüfen, ob sie noch unterbrochen ist. Dauert die Unterbrechung länger, versucht Zorro mehrmals, in zunehmend größer werdenden Zeitabständen (Minuten, dann Stunden) den Login erneut.
  • Werden optionale Funktionen nicht implementiert oder optionale Parameter nicht zurückgegeben, gleicht Zorro das durch Annahmen und Schätzungen aus. Existiert z.B. BrokerSell2 nicht, nimmt Zorro an, dass Trades durch gegengerichtetes Kaufen geschlossen werden. Ohne BrokerTrade kann Zorro die Füllmenge und den Preis einer GTC-Order nicht verfolgen und nimmt an, dass sie zum Einstiegszeitpunkt vollständig gefüllt wurde. Den Wert der Position schätzt es dann aus aktuellem Kurs und Einstiegsniveau.
  • Falls BrokerTrade implementiert ist, wird es regelmäßig für offene Trades aufgerufen, außer bei Kontrakten; dort nur bei contractUpdate bzw. contractPrice und nach einem SET_SYMBOL-Befehl zum entsprechenden Kontraktsymbol.
  • Für ein Skript mit direktem Zugriff auf Brokerfunktionen kann man die oben genannten Funktionen eines Broker-Plugins auch direkt aus dem Skript aufrufen (z.B. per LoadLibrary oder DefineApi, siehe DLL / API implementation). Ein Broker-Plugin kann außerdem weitere Funktionen enthalten, die Zorro selbst nicht nutzt, die aber vom Skript aufgerufen werden können.
  • Für das asynchrone Auslösen einer Kursabfrage kann man WM_APP+1 an das Fenster-Handle senden, das man zuvor per SET_HWND erhalten hat. Für den Aufruf der callback-Funktion sendet man WM_APP+2. So kann man etwa Streaming-Kurse in einem eigenen Thread verarbeiten. Ein Beispiel zum Senden dieser Nachrichten steht unter HWnd.
  • Einige Krypto-Börsen verlangen HMAC-Authentifizierung (Signatur) für Ordertransaktionen. Entsprechenden öffentlichen Beispielcode in C++ findet man auf GitHub, z.B. sha512.cpp.
  • Da Zorro-Broker-Plugins Standard-32-bit-DLLs sind, können sie auch von Drittsoftware genutzt werden, z.B. in Python per ctypes.

Beispiel: siehe Source-Ordner

Siehe auch:

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

► latest version online