No artigo anterior, realizamos uma triagem preliminar de moedas na plataforma DATADATA com base na amplitude e na ascensão e queda. A seguir, exploraremos um fator-chave na negociação de redes: definir o número de redes. O número de grades determina a frequência das transações e a quantidade de fundos para cada transação, o que por sua vez afeta o retorno total e o nível de risco da negociação da grade. Portanto, como definir razoavelmente o número de grades para atingir o melhor ponto de equilíbrio é uma questão importante que todo comerciante de grade precisa considerar.
Poucas grades: Se o número de grades for definido muito pequeno, os intervalos entre as grades serão maiores, o que significa que o preço precisa flutuar mais para chegar à próxima grade. Embora o valor da transação de cada grade seja maior e possa capturar maiores lucros de flutuação, devido a menos oportunidades de negociação, alguns lucros trazidos por flutuações menores podem ser perdidos. Portanto, a lucratividade geral pode ser menor do que o esperado.
Muitas grades:Quando o número de grades é muito grande, a faixa de preço de cada grade é menor, as oportunidades de negociação aumentam e a compra e venda podem ser realizadas com mais frequência. No entanto, devido à pequena quantidade de capital envolvida em cada transação, tais estratégias geralmente exigem negociações de alta frequência para gerar lucro. Isso pode facilmente levar a taxas de transação mais altas, e negociações muito frequentes podem fazer com que pequenas flutuações de mercado sejam a principal fonte de lucro, com um limite máximo limitado para os lucros.
Número razoável de grades: O número apropriado de grades precisa levar em consideração a volatilidade do mercado, o tamanho da conta e a frequência de negociação esperada. Quando a volatilidade do mercado é alta, aumentar adequadamente o número de grades pode capturar melhor as flutuações, enquanto quando os fundos são grandes, definir um número menor de grades pode resultar em valores maiores de transações individuais e reduzir a pressão sobre as taxas de transação. Ao equilibrar o espaçamento da grade e o custo de negociação frequente, os retornos e o controle de risco da estratégia podem ser maximizados.
Uma característica fundamental da negociação de grade é alocar fundos para cada intervalo definindo vários intervalos de grade. Ao determinar o número de grades, primeiro você precisa calcular o intervalo entre cada grade e a quantidade de fundos em cada grade. A definição do número de grades não afeta apenas a quantidade de fundos em cada grade, mas também determina a faixa de preço de compra e venda de cada grade.
Os fundos da conta são um fator importante na determinação do número de grades. Fundos de conta maiores permitem que mais grades sejam configuradas, enquanto fundos de conta menores exigem um limite no número de grades para evitar alocação muito dispersa de fundos, resultando em uma quantidade muito pequena de fundos em cada grade e incapacidade de obter lucros efetivos.
Além disso, a estratégia de gerenciamento de risco da negociação de rede também precisa levar em consideração a definição do número de redes. Especialmente quando o mercado flutua violentamente, muitas redes podem levar a perdas maiores, então o número de redes deve ser controlado razoavelmente para evitar negociações excessivas.
Na aplicação real de estratégias de negociação de grade, especialmente ao otimizar o equilíbrio entre o número de grades e a taxa de retorno, o DQL (Datadata Query Language) da plataforma Datadata oferece grande flexibilidade. O DQL não apenas oferece suporte a consultas, processamentos e análises de dados eficientes, mas também ajuda os traders a simular e testar o desempenho das estratégias de negociação de grade para encontrar o número de grade mais adequado e outras configurações de parâmetros.
Por meio do DQL, podemos obter facilmente dados históricos da linha K de diversas bolsas (como a Binance) e ajustar estratégias de negociação de grade com base nesses dados. Dessa forma, a estratégia ideal de negociação de rede pode ser selecionada com precisão de acordo com diferentes ambientes de mercado e a volatilidade de moedas específicas.
Antes de começarmos a testar nossa estratégia de negociação de grade, primeiro precisamos obter dados de mercado para a moeda-alvo. A seguir está o código para consultar os dados da linha K de uma moeda especificada no banco de dados:
# 获取目标币种的K线数据
data = query("select * from klines.spot_1d where Exchange = 'Binance' and Symbol = '???_usdt' order by Time")
Explicação:
???_usdt
) na plataforma de negociação Binance (incluindo hora, preço de abertura, preço mais alto, preço mais baixo e preço de fechamento, etc.). Isso fornece dados básicos para a execução da estratégia.O núcleo da estratégia de negociação de grade é negociar usando uma quantidade de grade e uma faixa de preço predefinidas. As etapas específicas são as seguintes:
Calcular o intervalo da grade (lacuna) e o valor da transação por grade (nocional):
Espaçamento da grade (lacuna): Calculado com base na razão entre os preços mais altos e mais baixos do mercado. A fórmula é a seguinte:
[
\text{gap} = \frac{\log(\text{max_p} / \text{min_p})}{\text{grid_num}}
]
em,max_p
Pelo preço mais alto,min_p
Pelo menor preço,grid_num
é o número de grades.
Valor da transação por grade (nocional):O valor da transação de cada grade é calculado pelos fundos totais e pelo número de grades. A fórmula é: [ \text{notional} = \frac{\text{balance}}{\text{grid_num}} ]
Preços de início e fim da rede:
exp(gap)
, e assim por diante.Operações de negociação:
Taxas de transação: Supondo que a taxa de manuseio para cada transação seja 0,0001, precisamos calcular e acumular a taxa de manuseio para cada transação.
def grid_trading_strategy(
raw,
grid_num, # 网格数量
min_p, # 最低价格
max_p, # 最高价格
):
"""
执行网格交易策略的函数
"""
# 初始化变量
balance = 1000 # 初始资金
raw = raw[['Time', 'Open', 'High', 'Low', 'Close']] # 只选择相关列
# 网格交易策略的设置
gap = math.log(max_p / min_p) / grid_num # 计算网格间隔
notional = balance / grid_num # 每个网格的交易额
# 初始化网格
net = []
for i in range(grid_num):
net.append({
'start_p': min_p * math.exp(i * gap), # 每个网格的起始价格
'end_p': min_p * math.exp((i + 1) * gap), # 每个网格的结束价格
'amt': notional / (min_p * math.exp(i * gap)), # 每个网格的购买量
'status': 'idle' # 初始状态为闲置
})
# 记录状态
state = {
'stock': 0, # 当前持仓
'fee': 0, # 交易费用
'longTradeVol': 0, # 长期交易量
'shortTradeVol': 0, # 短期交易量
'profitTbl': [], # 存储每个时刻的利润
'feeTbl': [], # 存储每个时刻的费用
'netCnt': 0, # 记录净交易次数
'idx': 0 # 当前数据的索引
}
# 检查开盘交易
def check_open_orders(state, net):
for i in range(len(net)):
if net[i]['status'] == 'idle' and raw['Low'][state['idx']] <= net[i]['start_p'] and raw['Open'][state['idx']] > net[i]['start_p']:
net[i]['status'] = 'taken' # 网格被占用
tradeVol = net[i]['amt'] * net[i]['start_p']
state['stock'] += net[i]['amt']
state['longTradeVol'] += tradeVol
state['fee'] += tradeVol * 0.0001 # 假设手续费为0.0001
# 检查平仓交易
def check_close_orders(state, net):
for i in range(len(net)):
if net[i]['status'] == 'taken' and raw['High'][state['idx']] >= net[i]['end_p'] and raw['Open'][state['idx']] < net[i]['end_p']:
net[i]['status'] = 'idle' # 网格状态恢复为空闲
tradeVol = net[i]['amt'] * net[i]['end_p']
state['stock'] -= net[i]['amt']
state['shortTradeVol'] += tradeVol
state['fee'] += tradeVol * 0.0001 # 假设手续费为0.0001
state['netCnt'] += 1
# 日志记录利润和费用
def log(state):
addVol = state['stock'] * raw['Close'][state['idx']] # 当前仓位的总价值
pl = state['shortTradeVol'] - state['longTradeVol'] + addVol # 计算利润
state['profitTbl'].append(pl)
state['feeTbl'].append(state['fee'])
# 主交易循环
for i in range(len(raw)):
state['idx'] = i
if raw['Close'][state['idx']] >= raw['Open'][state['idx']]:
check_open_orders(state, net)
check_close_orders(state, net)
else:
check_close_orders(state, net)
check_open_orders(state, net)
log(state)
# 将利润和费用数据整理为DataFrame
pl = DataFrame({'pl' : state['profitTbl'], 'fee' : state['feeTbl']})
pl['time'] = raw['Time']
pl['pl-net'] = pl['pl'] - pl['fee']
return pl
Para a moeda alvo, escolhemos a moeda ‘oax_usdt’. Após verificar o código no artigo anterior, essa moeda mantém uma alta amplitude por um longo período de tempo sem mostrar uma tendência unilateral significativa. Podemos tentar usar diferentes números de grade (por exemplo: 5, 10, 15, etc.) para backtesting simulado para ver os efeitos de diferentes números de grade e, então, encontrar um número de grade adequado. Por exemplo, ao calcular o lucro líquido (pl-net) para cada número de grade, podemos avaliar quais números de grade podem trazer os melhores retornos no ambiente de mercado atual. Aqui está o código para executar o backtest:
grid_nums = [5*i+5 for i in range(5)]
out = []
for g in grid_nums:
pl = grid_trading_strategy(
data,
grid_num=g,
min_p=min(data['Close']),
max_p=max(data['Close'])
)
out.append({
'num': g,
'pl-net': pl['pl-net'][-1],
'min_pl': min(pl['pl-net']),
'max_pl': max(pl['pl-net'])
})
return out
Após o backtesting com diferentes configurações de números de grade, obtivemos os seguintes resultados:
Análise:
Definir corretamente o número de grades é uma tarefa importante na estratégia de negociação de grades. Ao otimizar o número de redes, o desempenho do lucro das estratégias de negociação de redes pode ser efetivamente melhorado e os riscos podem ser melhor controlados. Este artigo analisa as configurações do número da grade e fornece métodos de cálculo específicos e códigos de amostra, na esperança de ajudar todos a otimizar as estratégias de negociação da grade e melhorar a estabilidade e a lucratividade das estratégias.
Nota: O código de backtesting da grade neste artigo foi adaptado de Zhihu Da Shen Halcyon, consulte o artigo para obter uma explicação do código-fonteDiário de Práticas de Negociação Algorítmica (XVIII) - Detalhes em Negociação em Grade: A Relação entre Número de Grade e Retorno de Longo Prazo。