
No artigo anterior, falamos sobre scripts de negociação programática. Na verdade, uma estratégia de negociação é um programa de script de negociação. O artigo fala principalmente sobre a necessidade de um portador de hardware para o programa de script de negociação (onde o programa roda), qual linguagem de programação de computador pode ser usada para escrever este programa de script de negociação (listagem o uso da Plataforma de Negociação Quantitativa Inventor Existem três linguagens de programação. Claro, você pode usar qualquer linguagem de programação para implementar estratégias para negociação programática). Neste artigo, continuamos discutindo a análise quantitativa do círculo das criptomoedas e entendemos o conhecimento da análise quantitativa do círculo das criptomoedas.
Tipos de estratégias de negociação Os novatos que são novos em negociação programática e negociação quantitativa podem ficar confusos com vários termos, como estratégias de tendência, estratégias de arbitragem, estratégias de alta frequência, estratégias de grade, etc. Na verdade, os tipos de estratégia comuns de negociação programática e negociação quantitativa podem ser simplesmente descrito da seguinte forma: Várias direções.
O acima é dividido da perspectiva de estratégias de negociação. Da perspectiva do design de estratégia na Inventor Quantitative Trading Platform, as estratégias também podem ser divididas em:
Estratégia de produto único Ou seja, essa estratégia opera apenas um produto, como negociação de BTC ou negociação de ETH.
Estratégia multiproduto Simplificando, é operar múltiplas variedades de acordo com uma lógica estratégica.
Estratégia multi-conta Simplificando, é configurar vários objetos de troca em um disco real (o conceito de troca foi introduzido no artigo anterior, e o objeto de troca com a API KEY configurada representa uma conta de troca). Por exemplo, algumas estratégias de copy trading envolvem múltiplas contas seguindo a operação (pode ser a mesma exchange ou exchanges diferentes). Em resumo, múltiplos objetos de exchange (contas) são gerenciados em uma conta real.
Estratégias lógicas múltiplas Por exemplo, em um mercado real, a estratégia MACD, a estratégia de média móvel, a estratégia de grade, etc. são projetadas ao mesmo tempo (claro, elas operam em diferentes objetos de câmbio. Se você opera o mesmo objeto de câmbio, precisa ver se as estratégias específicas têm conflitos lógicos)
API de troca Como os scripts de negociação programados operam contas de câmbio? A resposta é através da interface API aberta pela exchange. Então, que tipos de interfaces estão abertas para trocas? No artigo anterior, falamos sobre a seção “Exchange”, que dizia que as exchanges geralmente têm interfaces REST e Websocket. Aqui adicionamos alguns conceitos do nível do programa estratégico. As interfaces de troca são divididas em dois tipos: verificadas e não verificadas, dependendo se são verificadas ou não (REST e Websocket).
Interfaces que não requerem autenticação
Geralmente chamado de “interface pública”, esse tipo de interface não requer verificaçãoAPI KEY(Se você esqueceu o que é API KEY, pode consultar o artigo anterior). Esse tipo de interface geralmente é uma interface de mercado, como consulta de informações profundas de mercado, consulta de dados da linha K, consulta de taxas de financiamento, consulta de informações relacionadas a produtos de transações, consulta de registros de data e hora do servidor de câmbio, etc.
Simplificando, uma interface que não tem nada a ver com sua conta pode ser determinada aproximadamente como uma interface pública (nenhuma verificação necessária)
Na plataforma de negociação quantitativa Inventor, ao chamar uma função de API não verificada (encapsulando a interface não verificada da bolsa, interface pública), mesmo que a API KEY esteja configurada incorretamente, os dados retornados pela interface podem ser obtidos normalmente. (Porque não é verificado)
Interfaces que precisam ser verificadas Simplificando, é uma interface que precisa ser verificada (verificada por API KEY). Esse tipo de interface é chamado de interface privada. Esse tipo de interface geralmente está relacionado a algumas operações ou informações da sua conta, como consulta de ativos da conta, consulta de posições da conta, consulta de ordens pendentes, consulta de transferências, transferência de moedas, ajuste de alavancagem, definição de modos de posição, etc. Essas operações devem ser verificadas. Na plataforma de negociação quantitativa do Inventor, ao chamar uma função de API que requer verificação (a interface que a bolsa encapsulada precisa verificar, a interface privada), se a API KEY estiver configurada incorretamente, um erro será relatado ao chamar a interface e um valor nulo será retornado.
Então, como essas interfaces são usadas na Plataforma de Negociação Quantitativa do Inventor?
A Plataforma de Negociação Quantitativa do Inventor encapsula o comportamento de troca e define interfaces consistentes (como interface K-line, interface de mercado profundo, interface de ativo atual de consulta, interface de ordem, interface de retirada de ordem, etc.). Essas interfaces são chamadas de funções de API do A plataforma de negociação quantitativa do Inventor pode ser visualizada consultando a documentação da API (https://www.fmz.com/api).
Então, como usar algumas interfaces de câmbio com comportamentos e definições inconsistentes na Plataforma de Negociação Quantitativa do Inventor?
Essas interfaces de troca incluem: transferência de ativos, confiança condicional, colocação de pedidos em lote, cancelamento de pedidos em lote, modificação de pedidos, etc. Algumas exchanges têm essas interfaces, enquanto outras não. Suas funções e detalhes de uso podem variar muito. Portanto, essas interfaces estão disponíveis na Inventor Quantitative Trading Platform.exchange.IOEsta função é usada para acessar (para mais detalhes, consulte o documento da API da Plataforma de Negociação Quantitativa do Inventor: https://www.fmz.com/api#exchange.io…). Há também alguns exemplos práticos de estratégias de IO na plataforma de negociação quantitativa Inventor Strategy Square.
Todas as funções da API na documentação da API da Plataforma de Negociação Quantitativa do Inventor geram solicitações de rede?
Digamos primeiro que a interface da API de troca tem um limite de frequência para acesso (por exemplo, 5 vezes por segundo). O acesso não pode ser muito frequente, caso contrário, um erro http 429 será relatado e o acesso será negado (a maioria das trocas relata 429 ) . A mesma limitação também se aplica à chamada da interface de troca empacotada na Inventor Quantitative Trading Platform. Não há tal limitação para funções de API na Inventor Quantitative Trading Platform que não geram solicitações de rede. Nem todas as funções de API da Inventor Quantitative Trading Platform gerarão solicitações de rede. Algumas das funções de API do Inventor apenas modificam algumas configurações locais, como definir o par de negociação atual, definir o código do contrato, função de cálculo do indicador, obter o nome do objeto de troca, etc. Basicamente, você pode julgar se uma solicitação de rede ocorre a partir do propósito da função. Desde que seja para obter dados de troca, operar em contas de troca, etc., uma solicitação de rede será gerada. Você precisa prestar atenção à chamada frequência dessas interfaces.
Vamos falar sobre alguns problemas e experiências comuns ao usar funções de API na Plataforma de Negociação Quantitativa do Inventor.

Ao escrever estratégias, precisamos julgar e verificar os dados retornados pela interface. Por exemplo, esta linha de código é usada para obter informações de mercado na Inventor Quantitative Trading Platform (o mesmo é verdadeiro ao escrever um programa para acessar diretamente a bolsa interface):var ticker = exchange.GetTicker()Se precisarmos usar issotickerVariável (veja a estrutura retornada pela função GetTicker)Last(último preço) dados, precisamos usarvar newPrice = ticker.LastObtenha os dados assim (o que é newPrice? new: latest, Price: price, sim! Coloque-os juntos!) Neste momento, seGetTicker()Não há problema se a função retornar dados normais, mas se o tempo limite da solicitação expirar, ocorrerem erros de rede, a central desconectar o cabo de rede, o cabo for cortado, uma criança desobediente puxar o interruptor de energia, etc., isso causaráGetTicker()Função Retornanull. Neste momentotickerO valor de énullVisitarei novamente.LastOcorrerá uma exceção de programa, fazendo com que o programa de políticas seja interrompido.
Parece que a falha da chamada da interface (a chamada GetTicker falhou e retornou nulo) não é a causa direta da parada real da estratégia de negociação (a causa direta é acessar umnullPropriedades variáveis, falha de chamada de interface e erro não farão com que a negociação real pare (ênfase adicionada).
Então, o que podemos fazer para evitar a suspensão anormal de negociações reais?
A resposta é fazer processamento de tolerância a falhas nos dados retornados pela interface. É muito simples apenas determinar se os dados retornados sãonull(JavaScript é usado como exemplo, outras linguagens são basicamente as mesmas)
Escreva um pequeno trecho de código para explicar (esta é apenas uma explicação, não funcionará se você executá-lo diretamente!)
var ticker = exchange.GetTicker()
if (ticker) {
var newPrice = ticker.Last
Log("打印最新价格:", newPrice)
} else {
// 数据为null,不做操作就不会出问题
}
Não somenteGetTickerA interface precisa ser tolerante a falhas. Todas as interfaces com requisições de rede precisam ser tolerantes a falhas para valores de retorno (se você usar o valor de retorno da função)
Existem muitas maneiras de tolerar falhas, você pode usar_C()Função (consulte a documentação da API do FMZ), escreva sua própria função tolerante a falhas e projete seu próprio mecanismo e lógica tolerantes a falhas.
sobre_C()Ao usar funções, muitos alunos novos provavelmente as usarão incorretamente._C()Parâmetros de função são referências de função, não chamadas de função. Em termos simples:
_C(funcName, param1, param2), a chamada está correta, funcName não tem parênteses, param1 e param2 são os parâmetros a serem passados para a função funcName.
_C(funcName(param1, param2)), erro de chamada, geralmente novatos que não leem a documentação da API do FMZ com atenção escreverão assim.
LTC_USDT function main() {
exchange.IO("simulate", true) // 切换为OKEX交易所的模拟盘
exchange.Buy(-1, 1) // 价格是-1,表示下的订单为市价单,数量为1表示下单量是1USDT
}
Como as exchanges geralmente têm limites de valor de pedido, pedidos menores que o limite não serão enviados (por exemplo, a Binance Spot exige que cada pedido seja maior que 5 USDT para ser enviado com sucesso). Portanto, fazer um pedido como este resultará em um erro:
错误 Buy(-1, 1): map[code:1 data:[map[clOrdId: ordId: sCode:51020 sMsg:Order amount should be greater than the min available amount. tag:]] msg:]

Como a função de ordem só temBuy,Sell. No entanto, os futuros (claro, não há problema com spot, spot só tem compra e venda) têm direções como abertura longa, fechamento longo, abertura curta e fechamento curto. Obviamente, Comprar/Vender não pode representar operações em tantas direções . Neste momento, é necessário introduzir a configuração da direção de negociação de futuros. Esta funçãoexchange.SetDirection()。
Na FMZ
exchange.SetDirection("buy")(defina a direção primeiro) eexchange.BuyQuando usados juntos, significam que a ordem colocada é uma ordem para abrir uma posição longa.
E assim por diante:
exchange.SetDirection("sell")eexchange.SellQuando usados juntos, significam que a ordem colocada é uma ordem para abrir uma posição vendida.
exchange.SetDirection("closebuy")eexchange.SellQuando usados juntos, significam que a ordem colocada é uma ordem para fechar uma posição longa.
exchange.SetDirection("closesell")eexchange.BuyQuando usados juntos, significam que a ordem colocada é uma ordem para fechar uma posição vendida.
Normalmente os novatos irãoexchange.SetDirection("sell")eexchange.BuyUsado em conjunto com outros ou outras combinações incorretas. Então ele relatou um erro (o backtesting pode não relatar um erro, mas esse é obviamente um erro lógico, e pessoas com transtorno obsessivo-compulsivo não conseguem tolerá-lo…).
Outro erro comum cometido por novatos
function main() {
exchange.SetContractType("quarter") // 设置当前合约为季度合约
exchange.SetDirection("sell")
var id = exchange.Sell(-1, 1)
Log("看我市价单下单了,成交了,就有持仓了", exchange.GetPosition())
exchange.SetDirection("closebuy") // closebuy 和Sell 搭配使用,嗯没错~
exchange.Sell(-1, 1)
}

Vendo isso, você pode perguntar: “Por que eu tenho uma posição e uso closebuy e sell juntos, mas dá erro e não consigo fechar a posição?” Eu responderia: “Fechei na direção errada! Fechei a posição comprada.”
Outra situação possível para o erro acima é: a direção de fechamento está definida corretamente, a função de ordem é usada corretamente e a posição é mantida nessa direção, mas esse erro ainda é relatado.
O motivo é que seu programa pode ter feito várias ordens, mas a ordem inicial não foi executada, e a ordem de fechamento estava pendurada no mercado esperando para ser executada. Neste momento, o programa continua a fechar a posição, e ele irá solicitar um erro de exceder a posição de fechamento.
print。
JavaScriptconsole.log。
Golangfmt.Println()。
C++coutVamos falar sobre as informações exibidas na plataforma FMZ. Na Inventor Quantitative Trading Platform, há dois locais principais onde as informações são exibidas.
- Barra de status
Após o disco real estar em execução, a página do disco real é como mostrado na figura

A parte de exibição é a informação da barra de status. A barra de status é usada principalmente para exibir alguns dados de mudança em tempo real (porque mudanças em tempo real precisam ser observadas em tempo real, e elas não podem ser impressas em logs todas as vezes, então esse tipo de dados podem ser exibidos na barra de status. Se cada um for impresso O log conterá muitos dados repetidos e sem sentido, o que afetará a consulta).
Exibir o uso de dados na barra de status`LogStatus`Função, consulte a documentação da API do FMZ para obter detalhes.
- Coluna de log
Também na página do mercado real, conforme mostrado na figura:

A parte de exibição é a barra de log, que é usada principalmente para registrar permanentemente determinados dados em um determinado momento, ou para registrar uma determinada operação de uma estratégia em um determinado momento.
Existem vários tipos de logs:
1. Log comum: a estratégia FMZ usa a função Log para gerar e imprimir no log de estratégia.

2. Log de pedidos, usado na estratégia FMZ`exchange.Sell`/`exchange.Buy`Será registrado automaticamente na saída do log.

3. Registro de cancelamento de pedidos, usado na estratégia FMZ`exchange.CancelOrder`, o log de cancelamento do pedido será automaticamente emitido no log.

4. Log de erros. Quando a estratégia FMZ estiver em execução, se ocorrer um erro de chamada na interface para solicitação de rede ou uma exceção for lançada (como uma instrução como throw), um log de erros será automaticamente emitido no log.

As funções da API FMZ que podem gerar saída de log, como Log(…), exchange.Buy(Price, Amount), exchange.CancelOrder(Id), etc., podem ser seguidas por alguns parâmetros de saída adicionais após os parâmetros necessários, como: troca. CancelOrder(pedidos[j].Id, orders[j]) Isto é para cancelar os pedidos[j] Ao fazer este pedido, as informações do pedido serão exibidas.
function main() {
Log("数据1", "数据2", "数据3", "...")
var data2 = 200
var id = exchange.Sell(100000, 0.1, "附带数据1", data2, "...")
exchange.CancelOrder(id, "附带数据1", data2, "...")
LogProfit(100, "附带数据1", data2, "...")
}
JavaScriptA estratégia de linguagem será exibida ao imprimir os dados do indicador calculadonull。Há um exemplo de ensino no Strategy Square: https://www.fmz.com/strategy/125770 No backtesting deste exemplo de estratégia do tutorial, você pode ver o gráfico gerado pelo sistema de backtesting e a média móvel de 10 períodos:

Desenho personalizado de estratégia, gráfico de K-line e média móvel desenhado:

P: E se eu quiser a média móvel de 10 horas? Resposta: Os dados da linha K podem usar os dados da linha K do período horário.
Em termos leigos, a linha K que vemos é uma matriz depois de digitalizá-la (se você não entende o conceito de matriz, pode pesquisar no Baidu), na qual cada elemento é uma coluna da linha K, que é organizada em ordem. O primeiro elemento é o mais distante do tempo atual, e o último elemento do array é o mais próximo do tempo atual. Normalmente, a última barra de dados da linha K é a barra do período atual, que muda em tempo real e não é finalizada (você pode observar as mudanças acessando a página de uma bolsa e observando sua linha K). Os indicadores calculados também correspondem um a um às barras da linha K. No exemplo acima, você pode ver que um valor de indicador corresponde a uma barra da linha K. Observe que a última coluna da linha K muda em tempo real, e os indicadores calculados também mudarão com as alterações na coluna da linha K.
Na plataforma de negociação quantitativa Inventor, você pode usar a biblioteca TA (uma biblioteca implementada pela plataforma FMZ, integrada no custodiante e pode ser usada diretamente em vários idiomas) ou a biblioteca talib (talib é uma biblioteca de indicadores bem estabelecida, integrado com JS e C++, e Python precisa ser escrito por você) Instalar). Por exemplo, no exemplo acima, a média móvel é calculada: Usando a biblioteca TA:
function main() {
var records = exchange.GetRecords()
var ma = TA.MA(records, 10)
Log(ma) // 打印均线
}
Usando a biblioteca talib:
function main() {
var records = exchange.GetRecords()
var ma = talib.MA(records, 10)
Log(ma) // 打印均线
}
Os dados do indicador calculado ma são uma matriz, cada elemento da qual corresponde à matriz K-line (registros), ou seja,ma[ma.length -1]corresponderrecords[records.length - 1], e assim por diante.
O mesmo se aplica a outros indicadores complexos, e você precisa prestar atenção a indicadores como o MACD.
var macd = TA.MACD(records) // 这样只传入K线数据,不传入指标参数,指标参数采用的就是默认值,其它指标函数也是同理
Neste momento, a variável macd é um array bidimensional (se você não entende o conceito, pode pesquisar no Baidu). Simplificando, um array bidimensional é um array e cada elemento dele também é um array . Pergunta: Por que os dados do indicador macd são uma matriz bidimensional? Resposta: Como o indicador MACD é composto por duas linhas (linha DIF e linha DEA) e um conjunto de barras de volume (barra de volume MACD, na verdade, esses dados da barra de volume também podem ser considerados uma linha). Então a variável macd pode ser dividida em:
var dif = macd[0]
var dea = macd[1]
var macdColumn = macd[2]
Há também um exemplo de ensino pronto aqui, se você estiver interessado, estude-o: https://www.fmz.com/strategy/151972
