Контракты цифровых валют просты в обращении с роботами

Автор:Маленькие мечты, Создано: 2021-04-07 21:30:05, Обновлено: 2023-09-24 19:35:33

img

Контракты цифровых валют просты в обращении с роботами

В предыдущей статье мы реализовали простой робот для оплаты на месте, а сегодня мы реализовали простой робот для оплаты контракта.

Идеи дизайна

Контрактная версия ведения данных сильно отличается от текущей версии, которая может осуществляться путем мониторинга изменения активов счетов. Фьючерсная версия требует мониторинга изменения позиций счетов. Таким образом, ситуация с фьючерсными версиями сложнее, поскольку фьючерсы имеют несколько позиций, пустые позиции и различные контракты. Сначала планировалось обрабатывать многоголовые и пустоголовые вместе, но обнаружилось, что это становится очень сложным. После анализа проблемы было решено обрабатывать многоголовые и пустоголовые раздельно.

Реализация стратегии

Параметры стратегии:

img

Поддержка повторного тестирования, можно напрямую установить повторное тестирование наблюдений с помощью по умолчанию.

Источник стратегии:

/*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() {
    // 测试函数
    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), "参考账户测试开单#FF0000")
        } else if(x < 0.2) {
            exchange.SetDirection("sell")
            exchange.Sell(-1, _N(Math.max(1, x * 10), 0), "参考账户测试开单#FF0000")
        } else if(x >= 0.2 && x <= 0.5 && longPosAmount > 4) {
            exchange.SetDirection("closebuy")
            exchange.Sell(-1, longPosAmount, "参考账户测试平仓#FF0000")
        } else if(shortPosAmount > 4) {
            exchange.SetDirection("closesell")
            exchange.Buy(-1, _N(shortPosAmount / 2, 0), "参考账户测试平仓#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) {
        // 开仓
        var tradeFunc = type == PD_LONG ? e.Buy : e.Sell
        e.SetDirection(type == PD_LONG ? "buy" : "sell")
        tradeFunc(-1, delta)
    } else if (delta < 0) {
        // 平仓
        var tradeFunc = type == PD_LONG ? e.Sell : e.Buy
        e.SetDirection(type == PD_LONG ? "closebuy" : "closesell")
        if (nowAmount <= 0) {
            Log("未检测到持仓")
            return 
        }
        tradeFunc(-1, Math.min(nowAmount, Math.abs(delta)))
    } else {
        throw "错误"
    }
}

function main() {
    LogReset(1)
    if (exchanges.length < 2) {
        throw "没有跟单的交易所"
    }
    var exName = exchange.GetName()
    // 检测参考交易所
    if (!exName.includes("Futures_")) {
        throw "仅支持期货跟单"
    }
    Log("开始监控", exName, "交易所", "#FF0000")
    
    // 检测跟单交易所
    for (var i = 1 ; i < exchanges.length ; i++) {
        if (exchanges[i].GetName() != exName) {
            throw "跟单的期货交易所和参考交易所不同!"
        }
    }
    
    // 设置交易对、合约
    _.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()) {    // 回测时才模拟
            test()            // 测试函数,模拟参考账户主动交易,触发跟单账户跟单        
        }
        Sleep(5000)
        var nowRefPosAmount = getPosAmount(_C(exchange.GetPosition), refCt)
        var tbl = {
            type : "table", 
            title : "持仓",
            cols : ["名称", "标签", "多仓", "空仓", "账户资产(Stocks)", "账户资产(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) + "`")
        
        // 计算仓位变动量
        var longPosDelta = nowRefPosAmount.long - initRefPosAmount.long
        var shortPosDelta = nowRefPosAmount.short - initRefPosAmount.short

        // 检测变动
        if (longPosDelta == 0 && shortPosDelta == 0) {
            continue
        } else {
            // 检测到仓位变动
            for (var i = 1 ; i < exchanges.length ; i++) {
                // 执行多头动作
                if (longPosDelta != 0) {
                    Log(exchanges[i].GetName(), exchanges[i].GetLabel(), "执行多头跟单,变动量:", longPosDelta)
                    trade(exchanges[i], refCt, PD_LONG, longPosDelta)
                }
                // 执行空头动作
                if (shortPosDelta != 0) {
                    Log(exchanges[i].GetName(), exchanges[i].GetLabel(), "执行空头跟单,变动量:", shortPosDelta)
                    trade(exchanges[i], refCt, PD_SHORT, shortPosDelta)
                }
            }
        }

        // 执行跟单操作后,更新
        initRefPosAmount = nowRefPosAmount
    }
}

Тесты

С учетом того, что после обновления интерфейса V5 OKEX можно использовать диски OKEX, я очень удобно проверил их с помощью двух дисков OKEX API KEY.

Первый добавленный объект биржи является справочной биржей, после которой все биржи будут работать с учетной записью этой биржи. На странице OKEX Analogue, ссылка на учетную запись биржи, вручную запустить 3 квартальных контракта на биткоины ETH.

img

Вы можете видеть, что реальный диск обнаруживает изменения в балансе счета ссылки, и затем следует за операцией.

img

Если мы снова сравним две позиции, которые мы только что открыли, и попробуем их сравнять, то мы увидим следующее:

img

В результате, по результатам операций, 2 контракта были расторгнуты.

img

Эта стратегия разработана на основе простого и понятного способа, без оптимизации, а также для усовершенствования части, требующей обработки деталей, таких как проверка активов при оплате. Для простоты разработки, цена на рынке.

Политический адрес:https://www.fmz.com/strategy/270012

Приветствую комментарии.


Связанные

Больше

pw1013Два разных рынка не могут работать вместе.

Мингси1005Когда изобретатели смогут выиграть контрактные фьючерсы на пары монет?

АКЛКЯ надеюсь, что у нас есть плата за версию.

Лау99Хотелось бы иметь версию постоянного контракта, API исполнителя?????

зоусонЯ надеюсь, что у нас есть версия USDT для постоянного контракта.

- Я не знаю.Спасибо, что поделились этим, это очень полезно учиться.

Маленькие мечтыПоскольку контрактные спецификации могут отличаться в разных биржах, код запроса может быть изменен в зависимости от конкретных обстоятельств.

pw1013Би-бокс, который я использую, имеет 80% комиссионных, FMZ идеально поддерживает.

pw1013Если вы не знаете, где именно я могу изменить бибокс-фьючерс, который я использую сейчас, если я хочу связаться с кем-то еще на обменной площадке okx, где мне нужно изменить?

Маленькие мечтыЭто может быть реализовано, если изменить код.

Маленькие мечтыНа данный момент нет никаких сообщений от экспертов по этой бирже.