2
focar em
20
Seguidores

Implementação quantitativa da estratégia de arbitragem de taxas de venda a descoberto baseada em moeda

Criado em: 2025-01-21 17:06:52, atualizado em: 2025-02-17 11:25:01
comments   0
hits   455

Implementação quantitativa da estratégia de arbitragem de taxas de venda a descoberto baseada em moeda

Imagine ter uma estratégia que pode permanecer estável em meio às grandes flutuações do mercado de criptomoedas e pode lhe trazer retornos positivos sustentados, independentemente dos mercados de alta ou de baixa. Parece uma fantasia? Na verdade, não é. A estratégia de arbitragem de vender a moeda a descoberto com uma taxa única é uma ferramenta mágica para ganhar dinheiro sem fazer nada.

Ao utilizar de forma inteligente as propriedades exclusivas dos contratos baseados em moedas e o mecanismo de taxa de financiamento, essa estratégia pode não apenas obter retornos estáveis ​​em um mercado em alta, mas também evitar riscos de forma eficaz em um mercado em baixa, obtendo retornos estáveis ​​em todos os ciclos de mercado. A natureza “protegida por dinheiro” dos contratos baseados em moedas garante que o valor total da estratégia permaneça estável mesmo que os preços de mercado flutuem significativamente. A taxa de financiamento, como mecanismo central dos contratos perpétuos, fornece uma fonte adicional de renda para a estratégia. Este artigo analisará profundamente a lógica central, o processo de implementação, as vantagens e desvantagens da estratégia de venda a descoberto baseada em moedas para ajudar os investidores a entender como obter “renda passiva” por meio dessa estratégia no mercado de moeda digital. Seja você um novato em negociação quantitativa ou um investidor experiente, vale a pena entender e testar essa estratégia em profundidade.

Venda a descoberto baseada em moedas

Características do padrão monetário

A unidade do contrato com margem em moeda é medida em folhas, e o valor de cada folha é fixo (por exemplo, 1 contrato de BTC vale 100 USD e 10 USD de ETH). Esse recurso significa que, no caso de alavancagem de 1x, mesmo que o preço de mercado flutue muito, teoricamente não haverá chamada de margem.

Análise de lucros e perdas

Supondo que o preço atual seja 100 USD, 10 contratos curtos de margem de moeda são abertos, e seu valor é igual a 100 USD, que é convertido em 1 unidade de moeda:

  1. Queda de preço

    • O preço cai para 50 USD e a taxa de retorno é: [ \text{Taxa de retorno} = \frac{100 - 50}{50} = 100% ] O número de moedas mantidas torna-se 2, e o valor total permanece: [ 2 \times 50 = 100 , \text{USD} ]
  2. Aumento de preço

    • O preço sobe para 200 USD e a taxa de retorno é: [ \text{Taxa de retorno} = \frac{100 - 200}{200} = -50% ] O número de moedas mantidas torna-se 0,5, e o valor total permanece: [ 0.5 \times 200 = 100 , \text{USD} ]

Portanto, até certo ponto, o valor total das vendas a descoberto baseadas em moeda permanece estável, o que é uma operação de preservação de caixa. Então de onde vem o lucro dessa estratégia? Vamos introduzir o próximo conceito:Taxa de financiamento

Taxa de financiamento

Na estratégia de venda a descoberto baseada em moeda,Taxa de financiamentoÉ um dos principais impulsionadores dos retornos da estratégia, e suas características e mudanças afetam diretamente a estabilidade e a lucratividade da estratégia. Ao utilizar adequadamente as características das taxas de financiamento, as estratégias podem manter um bom desempenho em diferentes ambientes de mercado, mas também é necessário atentar para suas potenciais limitações.

Definição e Características da Taxa de Financiamento

A taxa de financiamento é um mecanismo regulatório no mercado de contratos perpétuos, que visa equilibrar os custos de manutenção das partes longas e curtas e evitar que o preço do contrato perpétuo se desvie do preço à vista por um longo período. Na verdade, amigos que estudaram CFA ainda se lembrarão do nome original do contrato perpétuo, swap. A inspiração do design do mecanismo de taxa de financiamento de contratos perpétuos é em grande parte derivada do swap de taxa de juros nas finanças tradicionais. Em um swap de taxa de juros, duas partes trocam pagamentos de juros em intervalos regulares com base em uma taxa de juros acordada (por exemplo, taxa fixa vs. taxa flutuante) para proteger o risco de flutuações na taxa de juros. Da mesma forma, o mecanismo de taxa de financiamento de contratos perpétuos também equilibra os custos de manutenção de partes longas e curtas, pagando ou cobrando taxas regularmente, garantindo que a diferença entre o preço do contrato e o preço à vista não seja muito grande.

Implementação quantitativa da estratégia de arbitragem de taxas de venda a descoberto baseada em moeda

A introdução da taxa de financiamento visa essencialmente resolver o problema básico entre contratos perpétuos e preços à vista. Quando o preço do contrato perpétuo é maior que o preço à vista, a taxa de financiamento é positiva, e os comprados pagam taxas aos vendidos; quando o preço do contrato perpétuo é menor que o preço à vista, a taxa de financiamento é negativa, e os vendidos pagam taxas aos comprados. Esse mecanismo não apenas se baseia no conceito central de swaps de taxas de juros, mas também combina as características do mercado de moeda digital para formar uma ferramenta única de regulação de mercado. No campo da moeda digital, suas principais características incluem:

  1. A oferta e a procura do mercado determinam:A taxa de financiamento é determinada pela relação de oferta e demanda entre posições compradas e vendidas no mercado e é o resultado do jogo entre forças compradas e vendidas.
  2. Pagamento periódico:A taxa de financiamento é paga em um determinado período (como 8 horas) e as taxas são transferidas entre posições longas e curtas.
  3. Reflexão emocional:Uma taxa de financiamento positiva geralmente indica que o sentimento do mercado é otimista e o preço do contrato perpétuo é maior que o preço à vista; uma taxa de financiamento negativa geralmente indica que o sentimento do mercado é pessimista e o preço do contrato perpétuo é menor que o preço à vista.

Taxa de Financiamento Positiva (Taxa de Financiamento > 0)

  • Desempenho:Em um ambiente de taxa de financiamento positiva, os comprados precisam pagar taxas aos vendidos.
  • Lógica de Receita:Com o pagamento estável da taxa de financiamento, a estratégia continua a coletar taxas de financiamento mantendo posições vendidas e, mesmo que o preço de mercado suba, isso não terá um impacto negativo significativo nos retornos. Por exemplo, quando a taxa de financiamento é de 0,02%/8 horas, manter um contrato avaliado em US$ 10.000 renderá o seguinte retorno diário: [ Receita diária = 10.000 \vezes 0,02% \times 3 = 6 , \text{USDT} ] Essa fonte de renda é relativamente estável e menos correlacionada com flutuações de preços.

Taxa de Financiamento Negativa (Taxa de Financiamento < 0)

  • Desempenho:Quando a taxa de financiamento é negativa, posições curtas precisam pagar taxas para posições longas, e os retornos da estratégia podem ser comprimidos ou até mesmo resultar em perdas.
  • Pontos de Risco:Quando taxas de financiamento negativas persistem por muito tempo ou flutuam muito, como em um mercado de baixa prolongado, a estratégia pode enfrentar custos mais altos devido ao pagamento de taxas de financiamento, resultando em um retorno geral incapaz de cobrir os custos operacionais.

Fontes estratégicas de lucro

Como disse o Mestre Zinan, no estágio inicial da construção da estratégia, é necessário entender as fontes de retorno e os riscos da estratégia. Com base no exposto acima, entendemos que o valor total das vendas a descoberto no padrão monetário deve permanecer estável, portanto a fonte de renda é o financiamento da arbitragem de taxas. Alguns alunos podem estar curiosos: a taxa de financiamento continuará trazendo retornos positivos estáveis? Realizamos trabalho de análise de dados na Estação Internacional DATADATA:

SELECT 
    Exchange,
    Symbol,
    toDateTime(Time / 1000) AS Time,  -- 将毫秒时间戳转换为时间戳
    Rate,
    SUM(Rate) OVER (PARTITION BY Exchange, Symbol ORDER BY Time) AS CumulativeRate  -- 计算累加的 Rate
FROM 
    klines.funding
WHERE 
    Exchange = '{{exchange}}' 
    AND Symbol = '{{symbol}}'
ORDER BY 
    Time;

Os parâmetros dinâmicos usam a bolsa Binance, e o contrato seleciona o contrato padrão Bitcoin (btc_usd) para exibir a taxa de financiamento cumulativa. Pode-se observar que, de 2020 até o presente, a receita da taxa de financiamento apresentou um nível de aumento constante, com a receita acumulada de cinco anos atingindo 50%. Embora não possa ser comparado aos lucros de centenas ou milhares, ele é relativamente estável, então podemos identificar as fontes de lucro dessa estratégia.

Na estratégia de venda a descoberto baseada em moedas, a taxa de financiamento é a principal fonte de lucro. Como as unidades dos contratos com margem em moeda são fixas, mesmo que os preços de mercado flutuem, as alterações no valor do contrato para vendedores a descoberto geralmente são controláveis, de modo que a taxa de financiamento se torna a principal fonte de lucro para a estratégia. A seguir estão os efeitos específicos das taxas de financiamento nas estratégias:

  1. Fase de mercado em alta (taxa de financiamento positiva)

    • Fenômeno de mercado:Em um mercado em alta, devido ao alto sentimento do mercado, os investidores geralmente tendem a operar comprados, resultando em um aumento nas posições compradas, empurrando assim a taxa de financiamento para um valor positivo.
    • Lógica de Receita: Neste caso, os vendedores a descoberto se beneficiarão da taxa de financiamento paga pelos comprados, o que se tornará a principal fonte de lucro para a estratégia. Como a taxa de financiamento é positiva, posições vendidas podem continuar a gerar lucros e, ao utilizar a taxa de financiamento obtida, você pode continuar a abrir posições vendidas e obter mais benefícios da taxa de financiamento.
    • Impacto específico: Se a taxa de financiamento for positiva e estável, os shorts receberão a taxa de financiamento regularmente e não serão muito afetados pelas flutuações de preço. Mesmo que o preço de mercado suba, os vendedores a descoberto podem enfrentar grandes perdas aparentes no contrato, mas, no geral, o valor líquido dos fundos permanece relativamente estável. Isso ocorre porque a fonte de lucro da estratégia depende principalmente da coleta de taxas de financiamento e não das flutuações de preços. Embora as flutuações de preço possam afetar a perda aparente do contrato, uma vez que as mudanças no valor do contrato da posição vendida são controláveis, o principal lucro dos fundos ainda vem da cobrança regular de taxas de financiamento, e não das flutuações de preço de mercado. Isso permite que a estratégia compense o risco de flutuações de preços até certo ponto e mantenha a valorização estável dos fundos.
  2. Fase de Mercado de Baixa (Taxa de Financiamento Negativa)

    • Fenômeno de mercado: Em um mercado em baixa, os preços de mercado caem rapidamente e as posições vendidas geralmente aumentam, fazendo com que a taxa de financiamento se torne negativa, o que significa que as posições vendidas precisam pagar as posições compradas. No entanto, devido ao crescimento do mercado de moedas digitais nos últimos anos, as fases de baixa do mercado são relativamente raras.
    • Lógica de Receita:Embora a taxa de financiamento seja negativa e os shorts precisem pagar taxas, as características de hedge da estratégia ainda são válidas porque a unidade do contrato curto é fixa e o valor do contrato da posição curta muda pouco. Flutuações violentas de preço não levarão a grandes perdas. Ao mesmo tempo, o fardo das taxas de financiamento é relativamente controlável, e a estratégia ainda pode permanecer estável até certo ponto.

Por meio da análise desses dois ambientes de mercado, pode-se observar que a lucratividade e o risco da estratégia de venda a descoberto baseada em moeda são afetados principalmente pela taxa de financiamento. Quando a taxa de financiamento é positiva no mercado em alta, os vendedores a descoberto podem se beneficiar dela; enquanto no mercado em baixa, embora a taxa de financiamento seja negativa, a estratégia ainda tem uma forte capacidade de preservar valor porque as mudanças no valor do contrato são controláveis.

Arquitetura lógica de política

Uma estrutura de estratégia robusta é a chave para a implementação bem-sucedida de uma estratégia. Ela fornece uma estrutura de execução clara para garantir que a estratégia possa operar de forma estável sob várias condições de mercado e lidar efetivamente com riscos e volatilidade. Aqui nos referimos à estrutura de estratégia de contrato multimoeda baseada em U da Xiaocao Dashen e fazemos certas modificações e melhorias no padrão monetário.

'''backtest
start: 2024-11-20 00:00:00
end: 2024-11-20 01:00:00
period: 1d
basePeriod: 1m
exchanges: [{"eid":"Futures_OKX","currency":"BTC_USD"}]
'''

import time
import json 

# 全局变量,储存数据
SYMBOLS = 'BTC'     # SYMBOLS代表要交易的币种,格式如"BTC,ETH,LTC"
QUOTO = 'USD'       # QUOTO为基础货币, 币本位为USD
INTERVAL = 5        # INTERVAL代表循环的间隔
ICEMONEY = 2000     # 冰山下单金额
ROLLINGNUM = 1      # 滚动盈利加仓数量


Info = {
    'trade_symbols': SYMBOLS.split(','),  # 交易币种
    'base_coin': QUOTO,                   # 基础货币
    'ticker': {},                         # 行情数据
    'order': {},                          # 订单信息
    'account': {},                        # 账户信息
    'precision': {},                      # 精度信息
    'position': {},                       # 仓位信息
    'time': {},                           # 时间相关数据
    'count': {},                          # 计数器
    'interval': INTERVAL                  # 循环的间隔时间
}

# 初始化策略
def InitInfo():

    # 初始化时间数据,控制更新的时间
    Info['time'] = {
        'update_ticker_time': 0,    # 更新行情的时间
        'update_pos_time': 0,       # 更新仓位的时间
        'update_profit_time': 0,    # 更新利润的时间
        'update_account_time': 0,   # 更新账户信息的时间
        'update_status_time': 0,    # 更新状态的时间
        'last_loop_time': 0,        # 上一次主循环的时间
        'loop_delay': 0,            # 循环延迟
        'start_time': time.time()   # 起始时间
    }

    # 初始化每个交易币种的数据
    for symbol in Info['trade_symbols']:

        Info['account'][symbol] = {
            'init_balance': 0,  # 初始余额
            'margin_balance': 0,  # 保证金余额
            'margin_used': 0,  # 已用保证金
            'margin_free': 0,  # 可用保证金
            'profit': 0,  # 总收益
            'profit_rate': 0,  # 收益率
            'unrealised_profit': 0,  # 未实现收益
        } # 初始化账户信息,初始余额为0

        Info['ticker'][symbol] = {'last': 0, 'ask': 0, 'bid': 0}  # 行情
        Info['order'][symbol] = {                                 # 订单信息
            'buy': {'id': 0, 'price': 0, 'amount': 0},
            'sell': {'id': 0, 'price': 0, 'amount': 0}
        }
        Info['position'][symbol] = {                              # 仓位信息
            'amount': 0, 'hold_price': 0, 'unrealised_profit': 0, 'open_time': 0, 'value': 0
        }
        Info['precision'][symbol] = {}  # 精度信息初始化为空
        Info['position'][symbol] = {                              # 仓位信息
            'amount': 0, 'hold_price': 0, 'unrealised_profit': 0, 'open_time': 0, 'value': 0
        }

# 获取精度信息
def GetPrecision():
    # 获取交易所的市场信息

    # 回测系统需要获取行情信息后, 才能获取市场信息,实盘系统可忽略
    for symbol in Info['trade_symbols']:
         curcontract = symbol + '_' + QUOTO + '.swap'
         exchange.GetTicker(curcontract) 
        
    exchange_info = exchange.GetMarkets()
    
    # 遍历市场中的所有交易对
    for pair, data in exchange_info.items():
        symbol = pair.split('_')[0]  # 永续合约交易对的格式为 BTC_USDT.swap
        
        # 检查该交易对是否为我们要交易的币种,基础货币是否匹配,且是永续合约
        if symbol in Info['trade_symbols'] and pair.split('.')[0].endswith(Info['base_coin']) and pair.endswith('swap'):
            # 获取该交易对的精度信息
            Info['precision'][symbol] = {
                'tick_size': data['TickSize'],                  # 价格精度
                'amount_size': data['AmountSize'],              # 数量精度
                'price_precision': data['PricePrecision'],      # 价格小数位精度
                'amount_precision': data['AmountPrecision'],    # 数量小数位精度
                'min_qty': data['MinQty'],                      # 最小下单数量
                'max_qty': data['MaxQty'],                      # 最大下单数量
                'min_notional': data['MinNotional'],            # 最小交易额
                'ctVal': data['CtVal']                          # 合约价值,如1张代表100USD
            }

            Log(f"初始化币种信息: {symbol}, "
                 f"价格精度: {Info['precision'][symbol]['tick_size']}, "
                 f"数量精度: {Info['precision'][symbol]['amount_size']}, "
                 f"价格小数位精度: {Info['precision'][symbol]['price_precision']}, "
                 f"数量小数位精度: {Info['precision'][symbol]['amount_precision']}, "
                 f"最小下单数量: {Info['precision'][symbol]['min_qty']}, "
                 f"最大下单数量: {Info['precision'][symbol]['max_qty']}, "
                 f"最小交易额: {Info['precision'][symbol]['min_notional']}, "
                 f"合约价值(张): {Info['precision'][symbol]['ctVal']}")


# 更新行情信息
def UpdateTicker():
    
    # 记录当前更新时间戳
    Info['time']['update_ticker_time'] = time.time() * 1000 # 使用time.time()获取当前时间的时间戳
    
    # 遍历获取到的行情数据
    for symbol in Info['trade_symbols']:
        
        curcontract = symbol + '_' + QUOTO + '.swap'
        data = exchange.GetTicker(curcontract)
        
        if not data:
            Log("获取行情失败", GetLastError())
            return
        
        # 更新行情的卖出价、买入价和最后成交价
        Info['ticker'][symbol]['ask'] = float(data['Sell'])  # 卖出价
        Info['ticker'][symbol]['bid'] = float(data['Buy'])   # 买入价
        Info['ticker'][symbol]['last'] = float(data['Last']) # 最后成交价


# 更新账户信息
def UpdateAccount():
    # 遍历所有交易币种,更新账户信息
    for symbol in Info['trade_symbols']:    
        curcontract = symbol + '_' + QUOTO  # 拼接币种和报价货币,形成合约标识
        exchange.SetCurrency(curcontract)  # 设置当前合约
        
        # 获取账户信息
        account = exchange.GetAccount()
        
        # 如果账户信息获取失败,记录日志并结束函数
        if account is None:
            Log(curcontract, ": 更新账户失败")
            return
        
        # 计算账户的关键信息
        # 'Stocks': 可用余额, 'FrozenStocks': 冻结余额, 'Equity': 总权益, 'UPnL': 未实现盈亏, 区别U本位(Balance)
        Info['account'][symbol]['margin_used'] = account['Equity'] - account['Stocks']  # 已用保证金
        Info['account'][symbol]['margin_balance'] = account['Equity']  # 当前账户总权益
        Info['account'][symbol]['margin_free'] = account['Stocks']  # 当前可用余额
        Info['account'][symbol]['unrealised_profit'] = account['UPnL']  # 未实现盈亏

        # 从全局存储中读取账户初始余额字典
        accDict = _G("init_balance")
        if accDict is None:
            accDict = {}  # 如果全局存储为空,则初始化为空字典

        # 初始化账户初始余额(仅在第一次运行时设置)
        if not Info['account'][symbol]['init_balance']:
            # 如果全局存储有记录且余额大于0,则使用该记录作为初始余额
            if accDict and accDict.get(symbol) and accDict[symbol] > 0:
                Info['account'][symbol]['init_balance'] = round(accDict[symbol], 2)
            else:
                # 否则,将当前保证金余额作为初始余额
                Info['account'][symbol]['init_balance'] = Info['account'][symbol]['margin_balance'] * Info['ticker'][symbol]['last']
                accDict[symbol] = Info['account'][symbol]['init_balance']  # 更新全局存储
                _G("init_balance", accDict)

        # 计算账户利润及利润率
        Info['account'][symbol]['profit'] = round(Info['account'][symbol]['margin_balance'] * Info['ticker'][symbol]['last'] - Info['account'][symbol]['init_balance'], 2)  # 当前利润
        Info['account'][symbol]['profit_rate'] = round((100 * Info['account'][symbol]['profit']) / Info['account'][symbol]['init_balance'], 2)  # 当前利润率(百分比)

# 更新仓位信息
def UpdatePosition():
    
    # 获取永续合约的仓位信息
    # 调用接口获取指定币种的仓位信息
    pos = exchange.GetPositions(Info['base_coin'] + ".swap")
    
    # 记录仓位信息的更新时间(单位:毫秒)
    Info['time']['update_pos_time'] = time.time() * 1000

    # 初始化仓位信息
    # 为每个交易币种创建默认的仓位信息
    position_info = {symbol: {'amount': 0, 'hold_price': 0, 'unrealised_profit': 0} for symbol in Info['trade_symbols']}

    # 遍历获取到的仓位信息,更新对应币种的仓位数据
    for data in pos:
        # 提取币种名称(Symbol)的一部分作为标识
        symbol = data['Symbol'].split("_")[0]
        
        # 过滤掉不属于指定基准币种或不在交易列表中的币种
        if not data['Symbol'].split(".")[0].endswith(Info['base_coin']) or symbol not in Info['trade_symbols']:
            continue
        
        # 更新仓位信息,区分多头和空头(通过 Type 字段)
        position_info[symbol] = {
            'amount': data['Amount'] if data['Type'] == 0 else -data['Amount'],  # 多头为正,空头为负
            'hold_price': data['Price'],  # 仓位持有价格
            'unrealised_profit': data['Profit']  # 未实现盈亏
        }

    # 初始化每个币种的仓位统计数据
    # long: 多头价值, short: 空头价值, total: 总仓位价值, leverage: 杠杆率
    for symbol in Info['trade_symbols']:
        Info['count'][symbol] = {'long': 0, 'short': 0, 'total': 0, 'leverage': 0}

    # 遍历更新后的仓位信息
    for symbol, info in position_info.items():
        # 计算仓位变化量
        deal_volume = abs(info['amount'] - Info['position'][symbol]['amount'])
        # 计算变化方向(正数为增仓,负数为减仓)
        direction = 1 if info['amount'] - Info['position'][symbol]['amount'] > 0 else -1
        
        # 如果仓位发生变化,记录成交信息
        if deal_volume:
            # 获取成交价格(买入或卖出)
            deal_price = Info['order'][symbol]['buy']['price'] if direction == 1 else Info['order'][symbol]['sell']['price']
            # 打印仓位更新日志
            Log(
                symbol,
                "仓位更新:",
                round(Info['position'][symbol]['amount'], 1),
                " -> ",
                round(info['amount'], 1),
                ", 买" if direction == 1 else ", 卖",
                ", 成交价:",
                deal_price,
                ", 成本价:",
                round(Info['position'][symbol]['hold_price'], Info['precision'][symbol]['price_precision']),
            )

        # 更新仓位信息
        Info['position'][symbol]['amount'] = info['amount']  # 更新仓位数量
        Info['position'][symbol]['hold_price'] = info['hold_price']  # 更新持仓价格
        Info['position'][symbol]['value'] = round(Info['position'][symbol]['amount'] * Info['precision'][symbol]['ctVal'], 2)  # 仓位价值
        Info['position'][symbol]['unrealised_profit'] = info['unrealised_profit']  # 更新未实现盈亏

        # 统计多头和空头仓位价值
        if Info['position'][symbol]['amount'] > 0:
            # 如果为多头,增加多头仓位价值
            Info['count'][symbol]['long'] += abs(Info['position'][symbol]['value'])
        else:
            # 如果为空头,增加空头仓位价值
            Info['count'][symbol]['short'] += abs(Info['position'][symbol]['value'])

        # 计算仓位总价值(按最新价格计算)
        Info['count'][symbol]['total'] = round((Info['count'][symbol]['long'] + Info['count'][symbol]['short']) / Info['ticker'][symbol]['last'], 2)
        # 计算杠杆率(总仓位价值与账户保证金的比值)
        Info['count'][symbol]['leverage'] = round(Info['count'][symbol]['total'] / Info['account'][symbol]['margin_balance'], 2)

# 订单函数
def Order(symbol, direction, price, amount, msg):
    pair = f"{symbol}_{Info['base_coin']}.swap"  # 构造交易对名称
    ret = exchange.CreateOrder(pair, direction, price, amount, msg)  # 执行下单操作
    
    # 判断是否下单成功
    if ret:
        Info['order'][symbol][direction]['id'] = ret  # 记录订单ID
        Info['order'][symbol][direction]['price'] = price  # 记录下单价格
        Log('记录下单价格:', price, direction, Info['order'][symbol][direction]['price'], )
    else:
        Log(f"{symbol} {direction} {price} {amount} 下单异常")  # 输出异常信息

# 交易函数
def Trade(symbol, direction, price, amount, msg):
    
    # 根据最小价格变动调整价格
    price = round(price - (price % Info['precision'][symbol]['tick_size']), Info['precision'][symbol]['price_precision'])
    
    # 计算调整后的交易数量
    amount = amount / Info['precision'][symbol]['ctVal']  # 计算真实合约数量
    amount = round(amount - (amount % Info['precision'][symbol]['amount_size']), Info['precision'][symbol]['amount_precision'])

    # 限制最大交易数量
    if Info['precision'][symbol]['max_qty'] > 0:
        amount = min(amount, Info['precision'][symbol]['max_qty'])
    
    new_order = False
    
    # 如果新价格与之前的订单价格差异大于0.0001,则重新下单

    if Info['order'][symbol][direction]['price'] > 0 and abs(price - Info['order'][symbol][direction]['price']) / price > 0.0001:
        Log('已持订单,订单价格发生变化')
        new_order = True
    
    # 如果交易数量为0或者当前订单ID为0,则撤单
    if amount <= 0 or Info['order'][symbol][direction]['id'] == 0:
        Log('新订单产生')
        new_order = True
    
    # 如果需要新订单
    if new_order:
        # 如果有原有订单,撤销它
        if Info['order'][symbol][direction]['id'] != 0:
            exchange.CancelOrder(Info['order'][symbol][direction]['id'])
            Info['order'][symbol][direction]['id'] = 0
            Info['order'][symbol][direction]['price'] = 0
            Log('撤单成功:', symbol)
        
        
        # 如果更新仓位或ticker的延迟太高,则不下单
        #if (time.time() * 1000 - Info['time']['update_pos_time'] > 2 * Info['interval'] * 1000 or 
        #    time.time() * 1000 - Info['time']['update_ticker_time'] > 2 * Info['interval'] * 1000):
        #    Log('仓位更新时间', time.time() * 1000, Info['time']['update_pos_time'], time.time() * 1000 - Info['time']['update_pos_time'])
        #    Log('Ticker更新时间', time.time() * 1000, Info['time']['update_ticker_time'], time.time() * 1000 - Info['time']['update_ticker_time'])
        #    Log('延迟过高')
        #    return
        
        # 如果订单金额或数量过低,不执行下单操作
        if price * amount <= Info['precision'][symbol]['min_notional'] or amount < Info['precision'][symbol]['min_qty']:
            Log(f"{symbol} 下单量太低", price * amount)
            return
        
        # 执行下单操作
        Log('order下单:', symbol)
        Order(symbol, direction, price, amount, msg)


# 更新状态函数
def UpdateStatus():
    
    # 更新状态时间
    Info['time']['update_status_time'] = time.time() * 1000

    # 账户信息表格
    table1 = {
        "type": "table",
        "title": "账户信息",
        "cols": [
            "币种", "初始权益", "实时权益", "可用余额", 
            "总收益", "收益率"
        ],
        "rows": [],
    }

    # 遍历每个交易对,填充交易对信息
    for symbol in Info['trade_symbols']:
        table1['rows'].append([
            symbol,  # 币种
            round(Info['account'][symbol]['init_balance'], 2),  # 初始权益
            round(Info['account'][symbol]['margin_balance'] *  Info['ticker'][symbol]['last'], 2),  # 实时权益
            round(Info['account'][symbol]['margin_free'] *  Info['ticker'][symbol]['last'], 2), # 可用余额
            round(Info['account'][symbol]['profit'], 2),  # 总收益
            str(Info['account'][symbol]['profit_rate']) + "%"  # 收益率
        ])

    # 交易对信息表格
    table2 = {
        "type": "table",
        "title": "交易对信息",
        "cols": [
            "币种", "方向", "数量", "持仓价格", "持仓价值", 
            "现价"
        ],
        "rows": [],
    }

    # 遍历每个交易对,填充交易对信息
    for symbol in Info['trade_symbols']:
        table2['rows'].append([
            symbol,  # 币种
            "LONG" if Info['position'][symbol]['amount'] > 0 else "SHORT",  # 方向
            Info['position'][symbol]['amount'],  # 数量
            round(Info['position'][symbol]['hold_price'], Info['precision'][symbol]['price_precision']),  # 持仓价格
            round(Info['position'][symbol]['value'], 2),  # 持仓价值
            round(Info['ticker'][symbol]['last'], Info['precision'][symbol]['price_precision'])  # 现价
        ])

    # 输出状态日志
    LogStatus(
        f"初始化时间: {time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(Info['time']['start_time']))}\n",
        f"`{json.dumps(table1)}`\n" + f"`{json.dumps(table2)}`\n",
        f"循环延时: {str(Info['time']['loop_delay']) + 'ms'}\n",
        f"最后执行时间: {_D()}\n"
    )

    totalprofit = 0
    for symbol in Info['trade_symbols']:
        totalprofit += Info['account'][symbol]['profit']  

    # 每10秒钟更新一次账户信息
    if time.time() * 1000 - Info['time']['update_profit_time'] > 10 * 1000:
        LogProfit(round(totalprofit, 3), '&')  # 输出收益日志
        Info['time']['update_profit_time'] = time.time() * 1000  # 更新收益时间


def MakeOrder():
    
    # 遍历所有交易对
    for symbol in Info['trade_symbols']:
        
        availBal = Info['account'][symbol]['margin_free'] *  Info['ticker'][symbol]['last'] #可用金额
        sell_price = Info['ticker'][symbol]['ask'] #卖出价格

        if availBal > ICEMONEY: #可用金额大于冰山挂单数量,起始建仓
            Trade(symbol, "sell", sell_price, ICEMONEY, symbol)  # 执行买入操作
        elif availBal > ROLLINGNUM * Info['precision'][symbol]['ctVal']: #可用盈利大于滚动加仓数量,逐步下单
            Trade(symbol, "sell", sell_price, ROLLINGNUM * Info['precision'][symbol]['ctVal'], symbol)  # 执行买入操作

def OnTick():
         
    # 更新市场行情信息
    UpdateTicker()

    # 更新账户信息
    UpdateAccount()
     
    # 更新持仓信息
    UpdatePosition()

    # 执行下单操作
    MakeOrder()
    
    # 更新状态信息
    UpdateStatus()

def main():

    LogReset(0)                # 日志重置
    Log('策略起始#0000ff')
    # 初始化信息
    InitInfo()                 # 初始化币种信息
    GetPrecision()             # 获取精度信息
    exchange.SetMarginLevel(1) # 设置杠杆倍数
    
    while True:  # 无限循环
        
        loop_start_time = time.time() * 1000  # 获取当前时间(毫秒)
        
        # 检查上次循环时间与设定的间隔时间是否已过
        if time.time() * 1000 - Info['time']['last_loop_time'] > Info['interval'] * 1000:
            
            OnTick()  # 调用 OnTick 函数

            # 更新最后一次循环时间
            Info['time']['last_loop_time'] = time.time() * 1000
            # 计算当前循环的延迟时间
            Info['time']['loop_delay'] = time.time() * 1000 - loop_start_time
        
        # 暂停5毫秒,避免过度消耗CPU资源
        Sleep(5)

1. Variáveis ​​globais e descrição de funções

A estratégia é baseada em definições simples de variáveis ​​e implementa adições de posição contínua e monitoramento de status por meio de funções modulares.

  • SYMBOLS: Moeda de negociação (como “BTC”).
  • QUOTO:Moeda base, o padrão monetário geralmente é o USD.
  • INTERVAL: O intervalo de tempo entre os ciclos de políticas.
  • ICEMONEY: Valor do pedido inicial, usado para pedidos iceberg.
  • ROLLINGNUM: O número de posições adicionadas após lucros contínuos.

2. Módulos funcionais principais

A seguir, uma breve descrição de cada módulo funcional:

  1. Função de inicialização (InitInfo)
    Usado para carregar informações de moeda de transação e status inicial da conta.

  2. Obtenha informações de precisão (GetPrecision)
    Obtenha o tamanho mínimo do pedido e o valor do contrato para cada par de negociação por meio da API da bolsa.

  3. AtualizarTicker
    Obtenha informações atuais do mercado regularmente, incluindo o melhor preço de compra, o melhor preço de venda e o preço mais recente.

  4. Atualizações de conta e posição (UpdateAccount, UpdatePosition)
    A sincronização em tempo real dos saldos das contas e informações de posição fornece uma base para decisões de negociação.

  5. Negociação e Gestão de Ordens (Ordem, Negociação)
    Funções unificadas de colocação e execução de ordens, com suporte a ordens limitadas e ordens de mercado.

  6. Monitoramento de status (UpdateStatus)
    Acompanhe o status da estratégia, incluindo lucros e perdas atuais e pedidos não atendidos.

3. Lógica de ordem de estratégia (MakeOrder)

O cerne da estratégia éPosição inicial(Posição do Iceberg) ePosição de rolamento(Controlado pelo parâmetro de posição de rolamento ROLLINGNUM). A seguir está uma descrição detalhada da lógica específica:

  1. Verificação da posição inicial:Verifique se o saldo da conta é maior que o valor inicial de abertura do iceberg (ICEMONEY). Se as condições forem atendidas, as posições serão abertas gradualmente em lotes para reduzir o deslizamento excessivo de preços causado pela abertura de uma posição de uma só vez.
  2. Estratégia de posição de rolamento:De acordo com a lucratividade da conta (receita da taxa de financiamento), aumente a posição razoavelmente, otimize a renda por meio do aumento contínuo da posição, de modo a melhorar a lucratividade geral da estratégia.

Implementação quantitativa da estratégia de arbitragem de taxas de venda a descoberto baseada em moeda

De acordo com os resultados do backtesting da estratégia, podemos ver que a estratégia alcançou retornos estáveis ​​em vários ciclos de mercado, especialmente no mercado em alta, onde a taxa de financiamento foi positiva por um longo tempo. Portanto, essa estratégia é muito adequada para a gestão de grandes fundos até certo ponto. Suas características de baixa volatilidade e retornos estáveis ​​podem atender às necessidades duplas de grandes fundos para controle de risco e retornos estáveis. Ao mesmo tempo, a estratégia adota alavancagem de 1x, o que evita o risco de liquidação causado pela alta alavancagem e aumenta ainda mais sua segurança.

Análise das vantagens e desvantagens da estratégia

vantagem

  1. A estratégia é simples e fácil de executar
    A lógica é clara e não são necessários cálculos complicados, o que o torna adequado para a gestão de grandes fundos por fundos de hedge ou investidores individuais.

  2. Forte resistência ao risco
    A alavancagem de 1x pode evitar o risco de liquidação, e as características baseadas em moeda garantem que o valor do dólar americano permaneça constante, independentemente de grandes flutuações do mercado.

  3. Renda estável
    Em um mercado em alta, a taxa de financiamento é mais alta e tem forte escalabilidade, e as moedas resultantes podem ser usadas para outros investimentos (como staking).

deficiência

  1. Forte dependência da moeda e das condições de mercado
    Esta é uma falha. Quando a taxa de financiamento de uma moeda é positiva por um longo período (shorts pagam longs), como contratos BNB, use DATADATA para selecionar contratos baseados em moedas BNB. Você pode ver que, devido às configurações da bolsa, a taxa de financiamento acumula para um valor negativo. Além disso, quando o grande ciclo está em um mercado de baixa de longo prazo (2022) e a taxa de financiamento é negativa, os retornos podem não ser capazes de cobrir o custo da operação da estratégia.

  1. Falta de rigidez estratégica
    A estratégia atual não inclui lógica de ajuste dinâmico, como a falta de medidas de resposta (como estratégias de stop-loss ou take-profit) ao alternar entre mercados de alta e baixa.

  2. Margens de lucro limitadas
    É adequado para cobrar taxas “deitado plano”, e não pode capturar retornos excedentes em grandes flutuações no mercado. Em alguns casos, a taxa de retorno não é tão boa quanto a dos fundos de títulos tradicionais.

Conclusão

A estratégia de arbitragem de taxas de venda a descoberto única baseada em moedas faz uso total das propriedades especiais dos contratos baseados em moedas e fornece uma solução de baixo risco para preservação de capital e valorização estável. Entretanto, diante dos diferentes estágios do mercado, as estratégias precisam ter um certo grau de flexibilidade para lidar com flutuações nas taxas de financiamento e riscos potenciais. As direções futuras de otimização podem incluir:

  1. Adicionar medidas de gestão dinâmica para alternar mercados de alta e baixa;
  2. Ajuste o ritmo de adição de posições de acordo com as mudanças nas taxas de financiamento.

Mas, em essência, esta estratégia tem certascontradição. A suposição inicial da estratégia é que o mercado de moeda digital estará em um mercado altista de longo prazo, e a venda a descoberto de contratos baseados em moeda pode ser usada para manter um fluxo de caixa estável e obter benefícios na taxa de financiamento. No entanto, se assumirmos que o mercado está em alta no longo prazo, por que não escolher simplesmente acumular moedas (hlod) e esperar pela alta constante do Bitcoin? É claro que essa estratégia ainda é confiável para aqueles que buscam retornos estáveis. O objetivo deste artigo é apresentar essa ideia de design e fornecer uma estrutura de estratégia de investimento quantitativa, na qual você pode melhorá-la e otimizá-la ainda mais. Espera-se que essa estratégia possa se tornar uma ferramenta eficaz para investidores quantitativos em moedas digitais.

Referências

Como construir rapidamente uma estratégia de negociação multimoeda universal após a atualização do FMZ

Diário de Práticas de Negociação Algorítmica (19) - Série Explicação Detalhada da Estratégia de Arbitragem (1): Arbitragem de Taxas de Venda a Descoberto Baseada em Moeda

Dicas gentis: O investimento é arriscado, tenha cuidado ao entrar no mercado. Os investidores são aconselhados a alocar fundos de forma razoável e controlar rigorosamente as posições e a alavancagem com base em uma compreensão completa da lógica da estratégia e dos riscos, de acordo com sua própria tolerância ao risco. O conteúdo deste artigo é apenas para referência e não constitui nenhum conselho de investimento.