No artigo anterior, implementamos um robô simples de pagamentos instantâneos, e hoje implementamos um robô simples de pagamentos por contrato.
A versão contratual de um registro robótico e a versão em tempo real diferem muito. O registro em tempo real pode ser realizado principalmente através do monitoramento das mudanças nos ativos da conta. A versão de futuros requer monitorar as mudanças nas posições da conta. Assim, a versão de futuros é um pouco mais complexa, pois os futuros possuem várias posições, posições vazias e diferentes contratos. É necessário lidar com os detalhes desta série. A ideia central é monitorar a variação da posição. A partir da variação da posição, a sequência de movimentos é desencadeada. O projeto inicialmente foi planejado para processar várias cabeças e vazios juntos, mas descobriu que isso seria muito complicado. Depois de um problema de análise, a decisão foi feita para processar várias cabeças e vazios separadamente.
Parâmetros da estratégia:
Suporte para retesting, pode ser usado diretamente para a configuração padrão de retesting observação.
O código da estratégia:
/*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
}
}
Dado que o OKEX atualizou a interface V5 para permitir o uso de discos de simulação OKEX, eu usei dois discos de simulação OKEX API KEY para testes muito convenientes.
O primeiro objecto de troca adicionado é o de referência, e todas as trocas seguem essa conta. Na página do OKEX Analog Disc, a conta de referência do exchange é a manualmente acionada de 3 contratos de locação de moeda trimestral de ETH.
Como você pode ver, o disco real detecta as mudanças de depósito da conta da bolsa de referência e segue a operação.
A partir de agora, vamos tentar estabilizar as duas posições do contrato que acabamos de abrir, e a posição após a estabilização é a seguinte:
O disco real segue a operação, eliminando dois contratos.
Esta estratégia foi projetada de forma simples e fácil de entender, sem fazer otimização, a parte perfeita também precisa lidar com detalhes como a detecção de ativos no momento do pagamento. Para simplificar o design, o pagamento é feito apenas com a lista de preços de mercado.
A estratégia é endereçada:https://www.fmz.com/strategy/270012
Mas o que é que ele está a fazer?
Pw1013Dois mercados diferentes não podem fazer isso.
Mingxi1005Quando é que os inventores vão conseguir juntar moedas e ganhar contratos futuros?
aclcEspero que haja uma versão de pagamento do Bitcoin usdt.
Lau99Queremos uma versão de contrato permanente do Bitcoin usdt, API do executor?????
ZhousoneO Bitcoin é uma moeda de troca, mas não é uma moeda de troca.
QQlove23Muito obrigado pela sua partilha, vale a pena aprender.
Inventor quantificado - sonho pequenoComo as especificações dos contratos podem ser diferentes, o código do pedido pode ser ajustado de acordo com as circunstâncias específicas.
Pw1013A bibox é a plataforma que eu uso, com 80% de comissão, e a FMZ é perfeitamente apoiada.
Pw1013Como é que posso mudar o bibox futuro que eu uso agora, se eu quiser fazer a parceria com outra pessoa na bolsa okx, onde é que eu preciso mudar?
Inventor quantificado - sonho pequenoA partir de agora, o Google já está trabalhando com o Google Analytics para criar um novo aplicativo para o Google Analytics.
Inventor quantificado - sonho pequenoNo entanto, a maioria das pessoas não tem acesso ao site, e a maioria não tem acesso ao site.