Martingale strategy design for cryptocurrency futures (1)

in fmz •  last year 

Recently, there are many Martingale strategies discussed in the FMZ official group, and there are not many Martingale strategies of cryptocurrency contracts on the platform. Therefore, I took this opportunity to design a simple Martingale strategy for cryptocurrency futures. Why is it called a Martingale strategy? Because the potential risks of the Martin strategy are indeed not small, it is not designed exactly according to the Martin strategy. However, this type of strategy still has a lot of risks, and the parameter settings of the Martin-type strategy are closely related to the risk, and the risk should not be ignored.

This article mainly explains and learns from the design of Martin-type strategies. Since the strategy idea is very clear, as a user of FMZ, we consider strategy design more.

Obtain total equity
Total equity is often used when designing cryptocurrency futures strategies. This is because returns have to be calculated, especially when you need to calculate floating returns. Since the position is occupied with margin, the pending order is also occupied. At this time, the API interface exchange.GetAccount() of the FMZ platform is called to obtain the available assets and pending order frozen assets. In fact, most cryptocurrency futures exchanges provide the data of total equity, but this attribute is not uniformly packaged on FMZ.

So we design functions to obtain this data according to different exchanges:

// OKEX V5 obtain total equity
function getTotalEquity_OKEX_V5() {
    var totalEquity = null 
    var ret = exchange.IO("api", "GET", "/api/v5/account/balance", "ccy=USDT")
    if (ret) {
        try {
            totalEquity = parseFloat(ret.data[0].details[0].eq)
        } catch(e) {
            Log("failed to obtain the total equity of the account!")
            return null
        }
    }
    return totalEquity
}

// Binance futures
function getTotalEquity_Binance() {
    var totalEquity = null 
    var ret = exchange.GetAccount()
    if (ret) {
        try {
            totalEquity = parseFloat(ret.Info.totalWalletBalance)
        } catch(e) {
            Log("failed to obtain the total equity of the account!")
            return null
        }
    }
    return totalEquity
}

The totalEquity in the code is the total equity we need. Then we write a function as the call entry, and call the corresponding function according to the name of the exchange.

function getTotalEquity() {
    var exName = exchange.GetName()
    if (exName == "Futures_OKCoin") {
        return getTotalEquity_OKEX_V5()
    } else if (exName == "Futures_Binance") {
        return getTotalEquity_Binance()
    } else {
        throw "This exchange is not supported"
    }
}

Design some auxiliary functions
Before designing the main function and main logic, we need to do some preparations and design some auxiliary functions.

Cancel all current pending orders

function cancelAll() {
    while (1) {
        var orders = _C(exchange.GetOrders)
        if (orders.length == 0) {
            break
        }
        for (var i = 0 ; i < orders.length ; i++) {
            exchange.CancelOrder(orders[i].Id, orders[i])
            Sleep(500)
        }
        Sleep(500)
    }
}

This function is familiar to those who often read the strategy example code on the FMZ strategy square, and many strategies have used similar designs. The function is to get the current pending order list, and then cancel them one by one.

Placement operations for futures

function trade(distance, price, amount) {
    var tradeFunc = null 
    if (distance == "buy") {
        tradeFunc = exchange.Buy
    } else if (distance == "sell") {
        tradeFunc = exchange.Sell
    } else if (distance == "closebuy") {
        tradeFunc = exchange.Sell
    } else {
        tradeFunc = exchange.Buy
    }
    exchange.SetDirection(distance)
    return tradeFunc(price, amount)
}

function openLong(price, amount) {
    return trade("buy", price, amount)
}

function openShort(price, amount) {
    return trade("sell", price, amount)
}

function coverLong(price, amount) {
    return trade("closebuy", price, amount)
}

function coverShort(price, amount) {
    return trade("closesell", price, amount)
}

There are four directions for futures trading: openLong, openShort, coverLong andcoverShort. So we designed four order functions corresponding to these operations. If you consider only the order, then there are several necessary factors: direction, order price and order volume.
So we also designed a function named: trade to handle the operation when distance, price, amount are specified.
The function calls to openLong, openShort, coverLong and coverShort are ultimately completed by the trade function, that is, placing an order on a futures exchange based on the established distance, price, and quantity.

Main function
The strategy idea is very simple, take the current price as the baseline, and place sell (short) and buy orders (long) at a certain distance up or down. Once the transaction is completed, all remaining orders will be cancelled, and then a new closing order will be placed at a certain distance according to the price of the position, and an increase order will be placed at the updated current price, but the order volume will not be doubled for additional positions.

Initial work
Because of the pending order, we need two global variables to record the order ID.

var buyOrderId = null
var sellOrderId = null

Then the strategy interface parameters are designed to use the OKEX_V5 simulated bot option, so some processing needs to be done in the code:

var exName = exchange.GetName()    
// Switch OKEX V5 simulated bot
if (isSimulate && exName == "Futures_OKCoin") {
    exchange.IO("simulate", true)
}

To be continued...

Authors get paid when people like you upvote their post.
If you enjoyed what you read here, create your account today and start earning FREE STEEM!