When beginner designs a cryptocurrency quantitative trading strategy, there are often various functions requirements. Regardless of the programming languages and platforms, they all will encounter various designing requirements. For example, sometimes multiple trading varieties of rotation are required, sometimes multi-platform hedging is required, and sometimes different trading varieties are required to be concurrent. Let’s share some of the designing experience when implementing the strategy writhing requirements.
The learning platform still uses the FMZ Quant trading platform (https://www.fmz.com), and the market is selected as the cryptocurrency market.
Most of these demand situations are prepared for multi-cryptocurrency trend and grid strategies, which need to be executed on the market with different trading iteration methods.
Usually designed like this:
function Process (symbol) {
exchange.IO("currency", symbol)
var ticker = _C(exchange.GetTicker)
Log("has switched trading pairs, processing trading pairs according to strategy logic:", symbol, "quotes: ", ticker)
// ...
// ..
// .
}
function main(){
var symbols = ["BTC_USDT", "LTC_USDT", "ETH_USDT"]
while (true) {
for (var i = 0 ; i < symbols.length; i++) {
Process(symbols[i])
Sleep(500)
}
}
}
We configure the robot:
It can be seen that this realizes that an exchange object is configured on the robot, and the trading pair is switched; the market of different trading pairs is obtained, and the multi-trading variety market is executed; and it executed under a strategy logic.
It can be seen that the three trading pairs we define: BTC_USDT, LTC_USDT, ETH_USDT, in the loop, iteratively obtain the market quote, and after obtaining the information, it can specifically detect the market and trigger the trading logic designed by the strategy.
Some readers may ask: “I don’t like to switch trading pairs, it feels a bit troublesome, and the strategy logic is not clear.”
There are indeed other design options, which we will introducing it at below.
The market data of different trading pairs is obtained through multiple exchange objects, and is executed in the iterative strategy logic.
For example, configure the robot by configuring three exchange objects for the robot. The trading pairs are set to BTC_USDT, LTC_USDT, and ETH_USDT respectively.
The name is the “OKEX Spot V3 Test” exchange object, on the Dashboard page, the exchange configuration page:
All done.
We changed a little bit of these code, because this time we added multiple exchange objects to the robot, which are the exchange objects of the trading pair BTC_USDT, LTC_USDT, ETH_USDT.
function Process (e) {
var ticker = _C(e.GetTicker)
Log("exchange", e.GetName(), "Process trading pairs according to strategy logic:", e.GetCurrency(), "Quotes:", ticker)
// ...
// ..
// .
}
function main(){
while (true) {
for (var i = 0 ; i < exchanges.length; i++) {
Process(exchanges[i])
Sleep(500)
}
}
}
Run the robot:
The example we described above, whether switching trading pairs or adding a trading object for multiple different trading pairs of a configuration account. All of these are just using an exchange account configuration (using a configured exchange).
So how do you use multiple exchange accounts in one strategy?
Some strategies such as multi-exchange cross-market hedging, multiple-account strategies within a single exchange.
For example, we have configured 2 exchanges on the Dashboard -> Exchange -> Adding Exchange page.
we can access to the asset information of the accounts configured by these two exchanges in the strategy.
function main(){
Log(exchanges[0].GetAccount()) // Print the account asset information of the first exchange object.
Log(exchanges[1].GetAccount()) // ... Print the asset information of the Bit-Z exchange
}
Of course, I can also add a second and third account exchange configuration to an exchange.
For example, we add another account for Huobi Futures.
As you can see, this configures the accounts of the two “Huobi Futures” exchanges.
When the strategy is created, a Huobi Futures Exchange object appears in the Robot’s Modify Configuration option for selection.
For example, this allows two accounts to be selling first and then buying with typical grid strategy (up) or buying first then selling (down).
Through the above two examples
Here is the difference between configuring multiple exchange objects on the robot and “Configuring multiple exchange objects for the same exchange account for the robot”:
This slamming and above-mentioned example of “The same exchange account has multiple exchange objects for the robot” is somewhat similar, but there are differences.
The difference is that the example above is an exchange configuration, ie:
When the robot configures the exchange object, it always uses:
This configuration.
It’s just that when you add an exchange object, the trading pair settings are different.
If the GetAccount function is called, the asset information of the same account is always accessed.
however:
The two huobi futures exchange objects thus configured, although they are all huobi futures, represent different exchange accounts.
Sometimes in the strategy of cryptocurrency contract hedging, in order to seize the fleeting trading opportunities, many scenarios need to be placed concurrently. However, because the contract is different, you need to switch to the corresponding contract when you get the market quote and place an order. When using the exchange.Go
function to execute a placing order function or get the quote, there is a problem with synchronization, not very fast. And the design of the switch contract also makes the logic not so simple. Is there a better way?
Of course there are, We can add two exchange objects to the robot by following the “Configure multiple exchange objects for the robot in the same exchange account”.
Then use this exchange configuration to add another exchange object.
A prompt box will pop up!
An exchange account configuration, you can not add exchange objects of the same currency or trading pair.
What should I do? It seems that the strategy robot can’t use two exchange objects, and the exchange object is bound to an exchange account number?
There is still a way!
Let’s go to the “Dashboard” -> “Exchange”, and then add an OKEX futures exchange configuration.
Click Save when configured.
This way we have two exchange configurations, but the same API KEY configuration information is used.
What are the benefits of this?
when writing a strategy, the design will be very simple!
function main(){
exchanges[0].SetContractType("quarter") // Set the first added exchange object. The current contract is a quarterly contract.
exchanges[1].SetContractType("this_week") // Set the second added exchange object, the current contract is the current week contract
while (true) {
var beginTime = new Date().getTime() // Record the timestamp from which this time the market quote was taken.
var rA = exchanges[0].Go("GetTicker") // Create a concurrent thread to get the first exchange object, which is the market data for the quarterly contract.
var rB = exchanges[1].Go("GetTicker") // Create a concurrent thread to get the second exchange object, which is the market data for the weekly contract.
var tickerA = rA.wait() // The two threads executing each other perform their own tasks, waiting to get the data. When A waits, the B task is also executing.
var tickerB = rB.wait() // So it seems to be sequential execution, actually at the bottom of the concurrency. Only when you get the order is to get A first, and get B.
var endTime = new Date().getTime() // Record the timestamp at the end of the two contract quotes.
if (tickerA && tickerB) { // If there is no problem with the data obtained, execute the following logic.
var diff = tickerA.Last - tickerB.Last // calculate the difference
$.PlotLine("diff", diff) // Use the line drawing library to plot the difference on the chart.
if (diff > 500) { // If the spread is greater than 500, hedge arbitrage (of course, the difference of 500 is relatively large, rarely seen.)
// Hedging
rA = exchanges[0].Go("Sell", tickerA.Buy, 1) // Concurrent threads create a selling order under the quarterly contract
rB = exchanges[1].Go("Buy", tickerB.Sell, 1) // Concurrent thread create a buying order under the weekly contract
var idA = rA.wait() // Waiting for the return of placing order results, returning the order ID
var idB = rB.wait() // ...
}
// ...
}
LogStatus(_D(), "Concurrently get two contract quotes taking time:", endTime - beginTime, "millisecond.") // Shows the time on the status bar to know that the program is executing.
Sleep(500)
}
Is this design strategy much simpler and clearer?
Real market operation:
As you can see, it takes only about 50 milliseconds to get the price of two contracts each time.