In the previous article, we implemented a simple spot order supervising bot, and today we are going to implement a contract version of a simple order supervising bot.
Design Idea
There is a big difference between the order supervising bot of the contract version and the spot version. The spot order supervising can mainly be realized by monitoring the changes of account assets. The futures version needs to monitor the position changes in an account.
Therefore, the situation of the futures version is more complicated, because there are different contracts for long and short positions of futures, which needs to deal with a series of details. The core idea is to monitor the position changes, and to trigger the order-supervising action based on the position changes. It was originally designed to deal with long and short positions together, but we found it would be complicated to deal with that. After analyzing the problem, it is decided to deal with the long and short positions separately.
Strategy Implementation
Strategy Parameter:
/upload/asset/269123b8ee22e45da92df.png
It supports backtest, and can directly use the default settings to backtest for observation.
Source code:
/*backtest start: 2021-03-18 00:00:00 end: 2021-04-07 00:00:00 period: 1d basePeriod: 1h exchanges: [{"eid":"Futures_OKCoin","currency":"BTC_USD"},{"eid":"Futures_OKCoin","currency":"BTC_USD"},{"eid":"Futures_OKCoin","currency":"BTC_USD"}] */ function test() { // test function var ts = new Date().getTime() if (ts % (1000 * 60 * 60 * 6) > 1000 * 60 * 60 * 5.5) { Sleep(1000 * 60 * 10) var nowPosAmount = getPosAmount(_C(exchange.GetPosition), refCt) var longPosAmount = nowPosAmount.long var shortPosAmount = nowPosAmount.short var x = Math.random() if (x > 0.7) { exchange.SetDirection("buy") exchange.Buy(-1, _N(Math.max(1, x * 10), 0), "the reference account tests ordering#FF0000") } else if(x < 0.2) { exchange.SetDirection("sell") exchange.Sell(-1, _N(Math.max(1, x * 10), 0), "the reference account tests ordering#FF0000") } else if(x >= 0.2 && x <= 0.5 && longPosAmount > 4) { exchange.SetDirection("closebuy") exchange.Sell(-1, longPosAmount, "the reference account tests closing positions#FF0000") } else if(shortPosAmount > 4) { exchange.SetDirection("closesell") exchange.Buy(-1, _N(shortPosAmount / 2, 0), "he reference account tests closing position#FF0000") } } } function getPosAmount(pos, ct) { var longPosAmount = 0 var shortPosAmount = 0 _.each(pos, function(ele) { if (ele.ContractType == ct && ele.Type == PD_LONG) { longPosAmount = ele.Amount } else if (ele.ContractType == ct && ele.Type == PD_SHORT) { shortPosAmount = ele.Amount } }) return {long: longPosAmount, short: shortPosAmount} } function trade(e, ct, type, delta) { var nowPosAmount = getPosAmount(_C(e.GetPosition), ct) var nowAmount = type == PD_LONG ? nowPosAmount.long : nowPosAmount.short if (delta > 0) { // open position var tradeFunc = type == PD_LONG ? e.Buy : e.Sell e.SetDirection(type == PD_LONG ? "buy" : "sell") tradeFunc(-1, delta) } else if (delta < 0) { // close position var tradeFunc = type == PD_LONG ? e.Sell : e.Buy e.SetDirection(type == PD_LONG ? "closebuy" : "closesell") if (nowAmount <= 0) { Log("no position detected") return } tradeFunc(-1, Math.min(nowAmount, Math.abs(delta))) } else { throw "error" } } function main() { LogReset(1) if (exchanges.length < 2) { throw "no platform with order supervision" } var exName = exchange.GetName() // detect the platform for reference if (!exName.includes("Futures_")) { throw "only support futures order supervising" } Log("start monitoring", exName, "platform", "#FF0000") // detect the order supervising platform for (var i = 1 ; i < exchanges.length ; i++) { if (exchanges[i].GetName() != exName) { throw "The order supervising platform is different from the reference platform!" } } // set trading pair and contract _.each(exchanges, function(e) { if (!IsVirtual()) { e.SetCurrency(refCurrency) if (isSimulate) { if (e.GetName() == "Futures_OKCoin") { e.IO("simulate", true) } } } e.SetContractType(refCt) }) var initRefPosAmount = getPosAmount(_C(exchange.GetPosition), refCt) while(true) { if (IsVirtual()) { // only simulate during backtest test() // test function, which simulates a reference account to trade automatically, to trigger the order supervising of the account } Sleep(5000) var nowRefPosAmount = getPosAmount(_C(exchange.GetPosition), refCt) var tbl = { type : "table", title : "position", cols : ["name", "label", "long", "short", "account asset (Stocks)", "account assest (Balance)"], rows : [] } _.each(exchanges, function(e) { var pos = getPosAmount(_C(e.GetPosition), refCt) var acc = _C(e.GetAccount) tbl.rows.push([e.GetName(), e.GetLabel(), pos.long, pos.short, acc.Stocks, acc.Balance]) }) LogStatus(_D(), "\n`" + JSON.stringify(tbl) + "`") // calculate the position amount of change var longPosDelta = nowRefPosAmount.long - initRefPosAmount.long var shortPosDelta = nowRefPosAmount.short - initRefPosAmount.short // detect the change if (longPosDelta == 0 && shortPosDelta == 0) { continue } else { // detect the position change for (var i = 1 ; i < exchanges.length ; i++) { // execute the action of long if (longPosDelta != 0) { Log(exchanges[i].GetName(), exchanges[i].GetLabel(), "Execute long order supervising, amount of change:", longPosDelta) trade(exchanges[i], refCt, PD_LONG, longPosDelta) } // execute the action of short if (shortPosDelta != 0) { Log(exchanges[i].GetName(), exchanges[i].GetLabel(), "Execute short order supervising, amount of change:", shortPosDelta) trade(exchanges[i], refCt, PD_SHORT, shortPosDelta) } } } // after the operation of order supervising, update initRefPosAmount = nowRefPosAmount } }
Test
In consideration of the fact that after OKEX updated the V5 interface, and the OKEX simulated bot can be used, I used API KAYs of two OKEX simulated bots to test, very conveniently.
The first exchange object to be added is the reference platform, and the order supervising platform follows the account of the reference platform to operate.
On the OKEX simulated bot page, the reference platform account manually places 3 ETH quarterly crypto-margined contracts.
/upload/asset/16152cb2e5d69bbfcc2d.png
It can be seen that the bot detected the position changes, and the following operations.
/upload/asset/17227c05ad1e89ef9eea.png
Let's try to close the 2 contract positions that we just opened. The positions after closing the positions are shown in the figure:
/upload/asset/1724bfe7273de2bee9a9.png
The bot followed to operate and closed 2 contracts.
/upload/asset/16a3d99f373d056c650e.png
The strategy is designed in a simple and easy-to-understand way without optimization. The improved part also needs to deal with details such as asset detection when supervising orders. In order to simplify the design, market orders are used for order supervising orders. The strategy only provides learning ideas, and the bot can be optimized according to your needs.
Strategy address: https://www.fmz.com/strategy/270012
Welcome to leave your comments.