2
Seguir
319
Seguidores

Marco de estrategia cuantitativa multidivisa de Python: ideas de diseño e implementación detallada

Creado el: 2025-08-29 13:10:54, Actualizado el: 2025-08-31 09:11:53
comments   0
hits   626

introducción:

Recientemente, un usuario de Xiaocao teacherCómo crear rápidamente una estrategia de trading multidivisa universal después de la actualización de FMZDeja un comentario en la sección de comentarios de este artículo con la esperanza de proporcionar una implementación en Python de este marco estratégico. Para satisfacer las necesidades de los desarrolladores de Python, este artículo se basará en las ideas originales de Xiaocao y las combinará con el entorno de trading simulado de Binance para explicar en detalle cómo construir un marco universal de trading cuantitativo multidivisa.

Este marco tiene las siguientes características:

  • Basado en lenguaje Python, fácil de entender y ampliar.
  • Admite transacciones simultáneas en múltiples monedas
  • Uso de un intercambio simulado de Binance para pruebas de seguridad
  • Proporciona ejemplos de código completos y comentarios detallados.

Esperamos que este artículo te ayude a iniciarte rápidamente en el trading cuantitativo multidivisa. También invitamos a los desarrolladores a innovar y optimizar con base en esta experiencia, creando estrategias de trading aún más completas y personalizadas. ¡Sigamos explorando juntos el camino del trading cuantitativo!

Estrategia de inicialización

En la fase de inicialización de la estrategia comercial, primero definimos las variables globalesSYMBOLSQUOTOINTERVAL, representa la moneda de transacción de destino, la moneda base y el intervalo de tiempo,InfoLas variables se utilizan para almacenar todos los datos clave necesarios durante la operación de la estrategia.InitInfoLa función inicializa estos datos, incluida la información de la cuenta, la gestión del tiempo, los datos del mercado para cada moneda comercial, la información de la orden, la información de la posición, etc. Estos pasos de inicialización garantizan que la estrategia tenga una estructura de datos clara y un estado inicial cuando se ejecuta, sentando las bases para la ejecución posterior de la estrategia.

import time
import json 

SYMBOLS = 'LINK,ETH,TRB'
QUOTO = 'USDT'
INTERVAL = 5

# 全局变量,储存数据
# SYMBOLS代表要交易的币种,格式如"BTC,ETH,LTC"
# QUOTO为基础货币,永续合约常见的有USDT,USDC
# INTERVAL代表循环的间隔
Info = {
    'trade_symbols': SYMBOLS.split(','),  # 交易币种
    'base_coin': QUOTO,                   # 基础货币
    'ticker': {},                         # 行情数据
    'order': {},                          # 订单信息
    'account': {},                        # 账户信息
    'precision': {},                      # 精度信息
    'position': {},                       # 仓位信息
    'time': {},                           # 时间相关数据
    'count': {},                          # 计数器
    'interval': INTERVAL                  # 循环的间隔时间
}

# 初始化策略
def InitInfo():

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

    # 初始化时间数据,控制更新的时间
    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['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
        }

Obtenga información del mercado y establezca la precisión

Este paso garantiza que la precisión de los precios, las cantidades y otros aspectos de las divisas que procesamos, así como la cantidad de la orden, cumpla con los estándares del exchange. Los distintos pares de divisas (como BTC/USD o ETH/USDT) tienen diferentes requisitos mínimos de precisión para precios y cantidades, por lo que necesitamos obtener esta información de la API del exchange para evitar órdenes que no cumplan con los estándares. Por ejemplo, ETH/USDT puede permitir dos decimales, mientras que BTC/USDT puede permitir ocho.

Objetivo:

  • Obtenga precisión de precio y cantidad para cada moneda para garantizar la precisión de los datos del pedido.
  • Prevenir fallos en los pedidos debido a errores de precisión.
# 获取精度信息
def GetPrecision():
    # 获取交易所的市场信息
    for presym in Info['trade_symbols']:
        curcontract = presym + '_USDT.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张代表0.01个币
            }
            
            # 检查合约价值的计价货币是否为symbol,避免币本位情况
            if data['CtValCcy'] != symbol:
                raise Exception("不支持币本位")

GetPrecisionfunción

  • Obtenga información del mercado de los exchanges a través de API, incluidas configuraciones de precisión para pares comerciales.
  • Para los pares comerciales elegibles, registre información como precisión de precios, precisión de cantidad, volúmenes de transacción mínimos y máximos y valor del contrato.
  • Comprueba si se trata de una transacción con margen de monedas y lanza una excepción si es así.

Obtener cotizaciones

Acceda a datos actuales del mercado a través de la API, como el último precio, la mejor oferta, la mejor demanda y la profundidad del libro de órdenes. Esta información es crucial para tomar decisiones de trading posteriores. Según la estrategia, estos datos pueden basarse en gráficos de velas (datos OHLC) o en datos tick a tick.

Objetivo:

  • Obtenga los últimos datos comerciales del mercado actual para que la estrategia pueda tomar decisiones de compra y venta basadas en estos datos.
  • Contiene la adquisición de datos en tiempo real e históricos para el cálculo de indicadores técnicos.
# 更新行情信息
def UpdateTicker():
    
    # 记录当前更新时间戳
    Info['time']['update_ticker_time'] = time.time() * 1000 # 使用time.time()获取当前时间的时间戳
    
    # 遍历获取到的行情数据
    for ticpre in Info['trade_symbols']:
        
        curcontract = ticpre + '_' + QUOTO + '.swap'
        data = exchange.GetTicker(curcontract)
        
        if not data:
            Log("获取行情失败", GetLastError())
            return
        # 提取交易币种,永续合约格式如 'BTC_USDT.swap',这里取币种名 'BTC'
        symbol = data['Symbol'].split('_')[0]
        
        # 过滤掉不是基础货币(Info['base_coin'])的交易对或不是永续合约的交易对
        if not data['Symbol'].split('.')[0].endswith(Info['base_coin']) or symbol not in Info['trade_symbols'] or not data['Symbol'].endswith('swap'):
            continue
        
        # 更新行情的卖出价、买入价和最后成交价
        Info['ticker'][symbol]['ask'] = float(data['Sell'])  # 卖出价
        Info['ticker'][symbol]['bid'] = float(data['Buy'])   # 买入价
        Info['ticker'][symbol]['last'] = float(data['Last']) # 最后成交价
  1. Obtener datos del mercado

    • usarexchange.GetTickersObtenga información del mercado en tiempo real para todos los pares comerciales.tickerLa variable almacena toda la información del par de transacciones.
  2. Manejo de errores

    • Si no se pueden obtener con éxito los datos del mercado, el programa pasaLogRegistros y salidas de funcionesGetLastErrorEl mensaje de error regresó.
  3. Hora de actualización

    • usartime.timePara registrar la marca de tiempo de la hora actual, que se utiliza para marcar la hora en que se actualiza el mercado.
  4. Filtrado de datos

    • Extraiga el nombre de la moneda comercial de los datos del mercado.
    • Filtra los pares comerciales que no cumplen con los requisitos, como los pares comerciales que no se liquidan en la moneda base o los pares comerciales que no son contratos perpetuos.
  5. Actualizar datos del mercado

    • Para las divisas comerciales elegibles, actualice su precio de compra, precio de venta y último precio negociado.

A través de esta función, el sistema puede obtener y actualizar la última información del mercado de la moneda comercial objetivo en tiempo real.

Obtener información sobre la posición de la cuenta

Utilice la API para consultar el saldo de su cuenta y sus tenencias actuales (divisa, cantidad, coste, etc.). Este paso es crucial para evaluar los fondos disponibles, calcular el riesgo y gestionar las posiciones. Por ejemplo, sus tenencias actuales determinarán si debe aumentar o disminuir su posición.

Objetivo:

  • Asegúrese de que haya suficientes fondos o posiciones abiertas en su cuenta para ejecutar la transacción.
  • Determinar el tamaño y la dirección de la transacción según la posición actual y los fondos en la cuenta.
# 更新账户信息
def UpdateAccount():
   
    # 如果上次更新时间距现在不到1分钟,直接返回
    if time.time() - Info['time']['update_account_time'] < 60:
        return
    
    # 记录账户信息更新时间
    Info['time']['update_account_time'] = time.time() * 1000
    
    # 获取账户信息
    account = exchange.GetAccount()
    
    # 如果账户信息获取失败,记录日志并返回
    if account is None:
        Log("更新账户失败")
        return
    
    # 计算账户信息
    Info['account']['margin_used'] = round(account['Equity'] - account['Balance'], 2)  # 使用的保证金
    Info['account']['margin_balance'] = round(account['Equity'], 2)  # 当前账户余额
    Info['account']['margin_free'] = round(account['Balance'], 2)  # 可用余额
    Info['account']['wallet_balance'] = round(account['Equity'] - account['UPnL'], 2)  # 钱包余额
    Info['account']['unrealised_profit'] = round(account['UPnL'], 2)  # 未实现盈亏

    # 初始化账户初始余额
    if not Info['account']['init_balance']:
        if _G("init_balance") and _G("init_balance") > 0:
            Info['account']['init_balance'] = round(_G("init_balance"), 2)
        else:
            Info['account']['init_balance'] = Info['account']['margin_balance']
            _G("init_balance", Info['account']['init_balance'])
    
    # 计算账户利润及利润率
    Info['account']['profit'] = round(Info['account']['margin_balance'] - Info['account']['init_balance'], 2)
    Info['account']['profit_rate'] = round((100 * Info['account']['profit']) / Info['account']['init_balance'], 2)

    # 计算仓位总价值和杠杆率
    Info['count']['total'] = round(Info['count']['long'] + Info['count']['short'], 2)
    Info['count']['leverage'] = round(Info['count']['total'] / Info['account']['margin_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 = data['Symbol'].split("_")[0]
        
        # 过滤掉不符合条件的币种
        if not data['Symbol'].split(".")[0].endswith(Info['base_coin']) or symbol not in Info['trade_symbols']:
            continue
        
        # 如果仓位不为零,则需要单向持仓
        if position_info[symbol]['amount'] != 0:
            raise Exception("需要单向持仓")
        
        # 更新仓位信息
        position_info[symbol] = {
            'amount': data['Amount'] * Info['precision'][symbol]['ctVal'] if data['Type'] == 0 else -data['Amount'] * Info['precision'][symbol]['ctVal'],
            'hold_price': data['Price'],
            'unrealised_profit': data['Profit']
        }

    # 初始化仓位统计数据
    Info['count'] = {'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]['value'], 1),
                " -> ",
                round(info['amount'] * Info['ticker'][symbol]['last'], 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['ticker'][symbol]['last'], 2)
        Info['position'][symbol]['unrealised_profit'] = info['unrealised_profit']

        # 统计多头和空头仓位价值
        if Info['position'][symbol]['amount'] > 0:
            Info['count']['long'] += abs(Info['position'][symbol]['value'])
        else:
            Info['count']['short'] += abs(Info['position'][symbol]['value'])
  1. UpdateAccountfunción

    • Intervalo de comprobación:Cada vez que actualice su cuenta, asegúrese de que la última actualización ocurra hace más de 1 minuto para evitar actualizar con demasiada frecuencia.
    • Actualizar la información de la cuenta: Llamarexchange.GetAccountObtenga información de la cuenta y calcule varios parámetros de la cuenta, comomargin_usedwallet_balanceunrealised_profitesperar.
    • Inicializar saldo: Inicializa el saldo inicial de la cuenta cuando se ejecuta por primera vez y lo guarda en la variable globalInfo['account']['init_balance']medio.
    • Cálculo de beneficios: Calcula la ganancia y el margen de ganancia basándose en el saldo actual y el saldo inicial.
  2. UpdatePositionfunción

    • Obtener información de la posición: Llamarexchange.GetPositions()Obtenga el estado de la posición actual.
    • Actualizar posición:Actualice la información de posición de la moneda de destino en función de los datos de posición adquiridos (comoamounthold_priceunrealised_profitesperar).
    • Cálculo del apalancamientoCalcula el índice de apalancamiento general en función de los valores de las posiciones largas y cortas actuales y del saldo del margen.

A través de estas dos funciones, la estrategia puede monitorear continuamente el estado de la cuenta y los cambios de posición, brindando soporte de datos en tiempo real para decisiones comerciales posteriores.

comercio

Ejecute órdenes de compra o venta según la lógica de la estrategia. Estas pueden ser órdenes de mercado, órdenes limitadas u otros tipos de órdenes. Este paso implica interactuar con la API del exchange para enviar solicitudes de compra o venta. La ejecución exitosa de la orden afecta el saldo y el interés abierto de la cuenta.

Objetivo:

  • Emite instrucciones comerciales a través de API para completar operaciones de compra y venta.
  • Asegúrese de que el tipo y la cantidad del pedido cumplan con los requisitos de la estrategia y las regulaciones cambiarias.
# 订单函数
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  # 记录下单价格
    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(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)
  1. Orderfunción

    • Responsable de crear un pedido. Si se realiza correctamente, se registrará el ID y el precio del pedido. Si falla, se mostrará un mensaje de error.
  2. Tradefunción

    • Ajustar en función del precio del mercado y la cantidad para determinar si se debe cancelar la orden y colocar una nueva para evitar errores de ejecución de la orden u operaciones repetidas.
  3. CancelOrderfunción

    • Es una operación de cancelación de pedido personalizada, encargada de cancelar el pedido pendiente actual.

Visualización de estado

El estado operativo de la estrategia se muestra en tiempo real, incluido el saldo de la cuenta, las posiciones actuales, el estado de ejecución comercial, el precio de mercado actual, etc. Este paso no solo sirve para monitorear el funcionamiento de la estrategia, sino también para comprender rápidamente el rendimiento de la estrategia durante la optimización y depuración de la estrategia.

Objetivo:

  • Mostrar información clave del funcionamiento de la estrategia de manera oportuna para facilitar el seguimiento del usuario.
  • Proporciona un mecanismo de retroalimentación para mostrar si la transacción se ejecutó correctamente o si hubo algún error.
# 更新状态函数
def UpdateStatus():
    
    # 如果距离上次更新的时间小于4秒,则直接返回
    if time.time() * 1000 - Info['time']['update_status_time'] < 4000:
        return
    
    # 更新状态时间
    Info['time']['update_status_time'] = time.time() * 1000

    # 账户信息表格
    table1 = {
        "type": "table",
        "title": "账户信息",
        "cols": [
            "初始余额", "钱包余额", "保证金余额", "已用保证金", "可用保证金",
            "总收益", "收益率", "未实现收益", "总持仓", "已用杠杆", "循环延时"
        ],
        "rows": [
            [
                Info['account']['init_balance'],  # 初始余额
                Info['account']['wallet_balance'],  # 钱包余额
                Info['account']['margin_balance'],  # 保证金余额
                Info['account']['margin_used'],  # 已用保证金
                Info['account']['margin_free'],  # 可用保证金
                Info['account']['profit'],  # 总收益
                str(Info['account']['profit_rate']) + "%",  # 收益率
                round(Info['account']['unrealised_profit'], 2),  # 未实现收益
                round(Info['count']['total'], 2),  # 总持仓
                Info['count']['leverage'],  # 已用杠杆
                str(Info['time']['loop_delay']) + "ms",  # 循环延时
            ],
        ],
    }
    
    # 交易对信息表格
    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",  # 方向
            round(Info['position'][symbol]['amount'], Info['precision'][symbol]['amount_precision'] + 2),  # 数量
            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']),  # 现价
            Info['order'][symbol]['buy']['price'],  # 挂单买价
            Info['order'][symbol]['sell']['price'],  # 挂单卖价
            round(Info['position'][symbol]['unrealised_profit'], 2),  # 未实现盈亏
        ])

    # 输出状态日志
    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"最后执行时间: {time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())}\n"
    )

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

Lógica de transacciones

El proceso principal de toma de decisiones en el trading. Con base en datos de mercado, información de cuentas y posiciones, combinados con indicadores técnicos o modelos cuantitativos, se toman decisiones sobre comprar, vender, aumentar o disminuir posiciones. La lógica de trading varía según la estrategia, como el seguimiento de tendencias, la reversión a la media o las estrategias de ruptura.

Objetivo:

  • Tome decisiones comerciales inteligentes basadas en datos del mercado y el estado de la cuenta.
  • Manejar diversas situaciones de mercado y garantizar que las estrategias puedan operar razonablemente en diferentes entornos de mercado.

Para demostrar la aplicabilidad del marco, la estrategia de trading de este artículo utiliza una lógica simple. Cada orden se fija en 50 USDT y, al ejecutarse, se calcula la cantidad de compra o venta correspondiente con base en los precios de compra y venta actuales del mercado. Las reglas de ejecución de esta estrategia son muy básicas y su objetivo es demostrar cómo aplicar el marco de la estrategia de trading de futuros multidivisa en un entorno real. Para garantizar la simplicidad y la operatividad, se establece una condición de parada: cuando el valor total del interés abierto de un par de divisas alcanza los 2000 USDT, se interrumpen las órdenes. Esto nos permite demostrar fácilmente la estructura básica de la estrategia y cómo interactúa con los datos de mercado de las bolsas.

def MakeOrder():
    
    # 遍历所有交易对
    for symbol in Info['trade_symbols']:
        
        # 获取买价(挂单买价)
        buy_price = Info['ticker'][symbol]['bid']
        
        # 计算买入数量,根据买入金额除以买价
        buy_amount = 50 / buy_price

        # 获取卖价(挂单卖价)
        sell_price = Info['ticker'][symbol]['ask']
        
        # 计算买入数量,根据买入金额除以买价
        sell_amount = 50 / sell_price

        
        # 如果当前持仓的总价值小于2000,则进行买入操作
        if Info['position'][symbol]['value'] < 2000:
            Log('进入交易')
            Log('设定价格:', Info['ticker'][symbol]['bid'])
            Trade(symbol, "buy", buy_price, buy_amount, symbol)  # 执行买入操作
        
        #if Info['position'][symbol]['value'] < 3000:
        #    Trade(symbol, "sell", sell_price, sell_amount, symbol)  # 执行买入操作

Bucle principal

El bucle principal es el núcleo del marco estratégico y se encarga de garantizar su rendimiento consistente y estable en el mercado. Realiza diversas operaciones regularmente a intervalos establecidos, como la obtención de los datos de mercado más recientes, la actualización de la información de las posiciones y la ejecución de decisiones de trading. Gracias al bucle principal, la estrategia puede responder a los cambios del mercado en tiempo real y garantizar que cada ejecución se base en los datos más recientes. Normalmente, el bucle principal se activa una vez por cada nuevo período de tiempo (por ejemplo, cada minuto, cada hora o al generarse una nueva vela).

Objetivo:

  • Garantizar el funcionamiento continuo y estable de la estrategia, obtener datos del mercado en tiempo real y tomar decisiones comerciales.
  • Cada ciclo garantiza la ejecución de la estrategia en tiempo real y con precisión.
def OnTick():
    try:
        # 更新市场行情信息
        UpdateTicker()
        # 更新持仓信息
        UpdatePosition()
        # 执行下单操作
        MakeOrder()
        # 更新状态信息
        UpdateStatus()
    except Exception as error:
        # 记录循环中发生的错误
        Log("循环出错: " + str(error))

def main():
    LogReset(0)  
    apiBase = "https://testnet.binancefuture.com"  # 币安期货仿真交易所        
    exchange.SetBase(apiBase)  # 设置仿真交易所基站
    # 初始化信息
    exchange.IO('dual', False)  # 单向持仓
    InitInfo()
    GetPrecision()
    
    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(5000)

Explicación del código:

  1. OnTickfunciónEsta función es la tarea principal que se ejecuta constantemente dentro del bucle principal. Se encarga de actualizar la información del mercado y de las posiciones, ejecutar operaciones y actualizar el estado de la estrategia. Todas las actualizaciones de operaciones e información se realizan dentro de esta función. Cualquier error durante la ejecución se captura y registra.

  2. mainfunciónLa función principal inicializa la información relevante, configura la estación base de intercambio e inicia un bucle infinito. En cada bucle, el programa comprueba si ha transcurrido el intervalo de tiempo establecido. De ser así,OnTickSe llamará a la función para ejecutar la estrategia. Si aún no se ha alcanzado el intervalo de tiempo, el programa esperará y continuará el bucle para garantizar que la estrategia se ejecute según el intervalo de tiempo predeterminado.

  3. Control de retardoDespués de cada bucle, el programa se pausa durante 5 milisegundos para reducir la carga de la CPU. Esto evita el consumo excesivo de recursos informáticos debido a bucles de alta frecuencia.

Lógica de operación

  • Fase de inicialización:Primero configure la API y otros parámetros necesarios, luego inicialice la información y obtenga la precisión de la moneda.
  • Fase del bucle principal:Ingrese un bucle infinito, cada bucle verificará el intervalo de tiempo para garantizar que el intervalo de tiempo para la ejecución de la política cumpla con las configuraciones preestablecidas.
  • Fase de ejecución:Una vez cumplida la condición del intervalo de tiempo,OnTickLa función se llamará para realizar todas las operaciones de estrategia, incluidas actualizaciones de información del mercado, ejecución de operaciones, etc.

Este diseño de bucle principal garantiza que la estrategia continúe ejecutándose en condiciones de mercado en tiempo real y tome decisiones comerciales oportunas, mejorando así la estabilidad y la precisión de la estrategia.

Resumir

Este marco estratégico está diseñado con modularidad y escalabilidad en mente. Cada paso tiene responsabilidades claras, lo que garantiza la solidez y facilita la expansión y optimización futuras. Al aprovechar las API de los exchanges, las estrategias se pueden optimizar y hacer más consistentes con las pruebas retrospectivas y el trading en tiempo real.

necesidadAvisoTenga en cuenta que este marco de demostración utiliza el exchange simulado de Binance como ejemplo, con el objetivo de proporcionar un marco básico para el desarrollo y la operación de estrategias. En la práctica, será necesaria una optimización basada en la lógica de la estrategia real, como el ajuste dinámico de parámetros según las condiciones del mercado, la optimización de los mecanismos de control de riesgos y la incorporación de la gestión de excepciones. Además, debido a las diferencias en las interfaces API, las reglas de trading, la configuración de precisión y las estructuras de comisiones entre exchanges, será necesaria una optimización y adaptación detalladas según los requisitos específicos del exchange de destino en la implementación real para garantizar la estabilidad y la compatibilidad de la estrategia. Se recomienda probar y verificar completamente la fiabilidad y el rendimiento de su estrategia antes de implementarla en el trading real.

apéndiceDirección del marco multidivisa de Python