2
Seguir
319
Seguidores

Breve análisis sobre las estrategias de creación de mercado de divisas digitales (2): Estrategia de mercado

Creado el: 2025-08-01 11:28:35, Actualizado el: 2025-08-04 14:15:40
comments   0
hits   692

Prefacio

En nuestro artículo anterior, “Estrategias de Wash Trading en Criptomonedas”, detallamos un marco estratégico para acumular volumen de operaciones comprando y vendiendo al mismo precio. El objetivo principal de esta estrategia es obtener descuentos en las bolsas o beneficios de nivel, en lugar de beneficiarse del arbitraje de precios. Si bien las estrategias de wash trading son valiosas para aprender sobre los marcos de trading, su rentabilidad real es limitada y pueden presentar riesgos de cumplimiento normativo.

Este artículo presentará otra estrategia de creación de mercado más práctica basada en el artículo anterior:Estrategia de handicapA diferencia de la estrategia de wash trading, la estrategia de creador de mercado es una verdadera estrategia de arbitraje que genera ganancias al establecer un diferencial entre los precios de compra y venta, lo que está más en línea con el modelo de ganancias de los creadores de mercado tradicionales.

⚠️ Aviso importante

El código de estrategia de mercado presentado en este artículo se ofrece únicamente como marco de aprendizaje y no refleja ninguna experiencia real en trading. Las estrategias aquí presentadas tienen como único fin el aprendizaje técnico y la investigación, y no han sido completamente validadas en condiciones reales de mercado. Se recomienda a los lectores realizar pruebas retrospectivas exhaustivas y una evaluación de riesgos antes de utilizar esta información, y no deben usarla directamente en el trading real.


Principios de la estrategia de handicap

La estrategia de libro de órdenes de mercado es una estrategia de creación de mercado que aprovecha la profundidad del mercado para arbitraje. Con esta estrategia, los creadores de mercado ajustan dinámicamente el precio de la orden dentro del diferencial entre los precios de compra y venta en función de las fluctuaciones del mercado, colocando y cancelando órdenes, aprovechando así la liquidez del mercado y las fluctuaciones de precios a corto plazo para generar ganancias.

Características principales

  1. Ajustar dinámicamente los precios de las órdenes pendientes:Ajuste dinámicamente los precios de las órdenes de compra y venta en función de la profundidad del mercado y las fluctuaciones de precios para aumentar la probabilidad de transacción.
  2. Controlar el número de órdenes pendientes:Controle el número de órdenes pendientes en función de los fondos y posiciones de la cuenta para evitar una exposición excesiva a los riesgos del mercado.
  3. Gestión del estado de los pedidos: Verifique periódicamente el estado del pedido y procese los pedidos no terminados.

Diferencias con la estrategia de reacción en cadena

característica Estrategia para aumentar el volumen Estrategia de handicap
Precios de compra y venta Mismo precio Precios diferentes (con diferencia de precio)
Modelo de ganancias Reembolsos/incentivos de cambio diferencial entre oferta y demanda
Exposición a riesgos Bajo (transacción al mismo precio) Alto (riesgo de volatilidad de precios)
Sentido práctico limitado Más alto

Ventajas de la estrategia de handicap

  • Mejorar la liquidez del mercado:Al colocar órdenes en el mercado, podemos aumentar la profundidad de compra y venta del mercado y atraer a más comerciantes para que participen.
  • Gane el diferencial entre oferta y demandaAl proporcionar liquidez, los creadores de mercado pueden ganar el diferencial entre oferta y demanda y así obtener ganancias.
  • Responder con flexibilidad a las fluctuaciones del mercado:La estrategia de mercado puede ajustar dinámicamente el precio de la orden pendiente de acuerdo con las fluctuaciones del mercado para reducir los riesgos del mercado.

Desafíos de la estrategia de handicap

  • Riesgo de mercado:Las fluctuaciones del precio del mercado pueden provocar que las órdenes del creador de mercado no se ejecuten o incluso produzcan pérdidas.
  • Presión financieraLos creadores de mercado necesitan fondos suficientes para mantener la profundidad de compra y venta del mercado. La falta de fondos puede provocar el fracaso de la estrategia.
  • Gestión de pedidos complejos:La estrategia de mercado requiere la verificación periódica del estado de los pedidos y el procesamiento de los pedidos no completados, lo que aumenta la complejidad de la estrategia.

Estructura de la estrategia de handicap

En consonancia con la estrategia de strike, el código de este artículo implementa una estrategia de creación de mercado basada en la estrategia de cotización del mercado, que se divide principalmente en dos categorías:

  1. MidClass:La capa intermedia de intercambio es responsable de interactuar con la interfaz de intercambio para obtener datos del mercado, información de la cuenta, estado del pedido, etc.
  2. MarketMaker:Clase de estrategia de creación de mercado, responsable de ejecutar la estrategia de mercado, generar dinámicamente precios de órdenes pendientes, generar órdenes pendientes, verificar el estado de las órdenes, actualizar el estado de la estrategia, etc.

Proceso de estrategia de handicap

1. Inicialización

existir MarketMakerEn el método de inicialización de clase, primero se obtiene la información de precisión del intercambio e inicializa los parámetros de la estrategia, como la precisión del volumen de transacciones, la precisión del precio, etc.

self.precision_info = self.exchange_mid.get_precision()  # 获取精度信息
self.price_precision = self.precision_info['price_precision']  # 价格精度
self.amount_precision = self.precision_info['amount_precision']  # 交易量精度

2. Generar un diccionario de órdenes pendientes

La base de la estrategia de mercado es generar un diccionario de órdenes pendientes, que contiene los precios y las cantidades de compra y venta. El código genera este diccionario calculando el precio medio y el diferencial de precio.

3. Movimiento de precios de órdenes pendientes

El movimiento del precio de la orden pendiente se obtiene calculando la compensación del precio. Esta compensación se basa en el rango de precios (price_range) y el intervalo de precio mínimo (min_price_step) calculado.

price_offset = price_range - self.pending_order_count * min_price_step  # 计算价格偏移量
do_trade = price_offset > 0
  • price_range:Rango de precios, que indica el rango de desviación entre el precio de la orden pendiente y el precio medio.
  • min_price_step:Intervalo de precio mínimo, que indica el paso de ajuste mínimo del precio de cada orden pendiente.
  • price_offset:Desplazamiento de precio, que indica la desviación entre el precio del pedido actual y el precio medio.

Si el desplazamiento de precio es mayor a 0, significa que la orden puede seguir colocándose; de lo contrario, se restablece el número de órdenes pendientes.

4. Generar diccionario de órdenes pendientes

En función del desplazamiento de precios, se calculan los precios de compra y venta y se genera un diccionario de órdenes pendientes.

if do_trade:
    buy_price = mid_price - price_offset  # 计算买价
    buy_price = round(buy_price, self.price_precision)  # 四舍五入买价
    
    sell_price = mid_price + price_offset  # 计算卖价
    sell_price = round(sell_price, self.price_precision)  # 四舍五入卖价

    trade_dict = {
        'do_trade': do_trade,
        'buy_price': buy_price,
        'sell_price': sell_price,
        'amount': trade_amount
    }

    Log('返回盘口挂单字典:', trade_dict)
    return trade_dict
else:
    self.pending_order_count = 0  # 重置挂单次数
  • buy_price:Precio de oferta, calculado como el precio medio menos el precio de compensación.
  • sell_price:Precio de venta, calculado como el precio medio más el precio de compensación.
  • trade_dict:Diccionario de órdenes pendientes, incluyendo precios de compra y venta y cantidades.

5. Ejecutar operaciones de mercado

De acuerdo con el diccionario de órdenes generado, ejecute la transacción de orden.create_orderMétodo, colocar órdenes de compra y órdenes de venta al mismo tiempo.

def make_trade_by_dict(self, trade_dict):
    if trade_dict['do_trade']:
        buy_id = self.exchange_mid.create_order('buy', trade_dict['buy_price'], trade_dict['amount'])  # 挂买单
        sell_id = self.exchange_mid.create_order('sell', trade_dict['sell_price'], trade_dict['amount'])  # 挂卖单
        
        self.traded_pairs['pan_kou'].append({
            'buy_id': buy_id, 'sell_id': sell_id, 'init_time': time.time(), 'amount': trade_dict['amount']
        })

6. Verificar el estado del pedido

Verifique periódicamente el estado de los pedidos y procese los pedidos incumplidos. La lógica de procesamiento del estado de los pedidos es similar a la de la estrategia de trading cruzado, pero debido a las diferencias de precio, la ejecución parcial puede generar ganancias o pérdidas.

Las principales desventajas de la estrategia de handicap

1. El movimiento de precios de las órdenes pendientes no es lo suficientemente flexible

El mecanismo de ajuste de precios en esta estrategia es relativamente simple, con las siguientes limitaciones:

price_offset = price_range - self.pending_order_count * min_price_step  # 计算价格偏移量
  • Límite de ajuste lineal:La compensación de precios adopta un método de disminución lineal y no se puede ajustar dinámicamente según la volatilidad real del mercado.
  • Solidificación de parámetrosprice_range y min_price_stepEs un parámetro fijo y no se puede ajustar en tiempo real según las condiciones del mercado.
  • Histéresis de respuesta:Cuando los precios del mercado cambian rápidamente, el ajuste de precios de la estrategia puede no seguir el ritmo del mercado.
  • Falta de conocimiento del mercado:No tiene en cuenta factores de microestructura del mercado, como la profundidad de la cartera de órdenes y el volumen de operaciones.

Dirección de mejora

  • Introducción de un mecanismo dinámico de ajuste de precios basado en la volatilidad
  • Ajustar los precios de las órdenes pendientes en función de la profundidad del mercado y la liquidez
  • Mejore su juicio sobre las tendencias del mercado y evite colocar órdenes en contra de la tendencia.

2. Riesgo de inventario

La estrategia de mercado se enfrenta a graves problemas de riesgo de inventario:

Rendimiento de riesgo

  • Riesgo de transacción unilateral:Cuando solo se ejecutan órdenes de compra o de venta, se generará una posición desequilibrada.
  • Riesgo direccional:En un mercado en tendencia, se puede acumular una gran cantidad de posiciones unidireccionales.
  • Ocupación de capital:Un inventario excesivo ocupará muchos fondos y afectará la eficiencia de la estrategia.

Puntos de riesgo en el código

if buy_order_status['Status'] == ORDER_STATE_PENDING:
    self.sell_amount += traded_pair['amount']  # 只有卖单成交,积累空头持仓
elif sell_order_status['Status'] == ORDER_STATE_PENDING:
    self.buy_amount += traded_pair['amount']  # 只有买单成交,积累多头持仓

El impacto del riesgo de inventario

  • Rentabilidad en descenso:Las posiciones unilaterales resultarán en pérdidas cuando se produzcan cambios de precios desfavorables.
  • Presión de liquidez:Se necesitan fondos adicionales para cubrir los riesgos de inventario
  • La estrategia no funcionó:En casos extremos, la estrategia puede no seguir ejecutándose.

Medidas de gestión de riesgos

  • Restricciones de inventario:Establezca un límite de posición máxima para evitar una acumulación excesiva
  • Cobertura dinámica:Cuando el inventario excede el umbral, cierre o cubra activamente
  • Inclinación de precios:Ajustar los precios de compra y venta en función del inventario actual para fomentar las transacciones inversas

Resumen de la estrategia

La estrategia de creación de mercado se basa en la profundidad del mercado. Mantiene la liquidez del mercado ajustando dinámicamente el precio y la cantidad de órdenes de compra y venta. En comparación con la estrategia de lavado de activos, la estrategia de creación de mercado presenta las siguientes características:

✅ Ventajas

  • Obtenga ganancias reales de arbitraje a través de las diferencias de precios
  • En línea con el modelo de ganancias de los creadores de mercado tradicionales
  • Proporcionar liquidez real al mercado

❌ Desafío

  • Ante los riesgos de fluctuación de los precios del mercado
  • Se necesita una gestión de riesgos más sofisticada
  • Mayores exigencias de fondos y tecnología
  • El mecanismo de ajuste de precios no es lo suficientemente flexible:El mecanismo de movimiento de precios lineal es difícil de adaptar al complejo entorno del mercado.
  • Riesgos de inventario importantesLas transacciones unilaterales pueden fácilmente llevar a posiciones desequilibradas, y el riesgo es particularmente significativo en mercados con tendencia.

🔮 Direcciones futuras de optimización

En vista de las deficiencias de la actual estrategia de handicap, podemos optimizarla y mejorarla en las siguientes direcciones en el futuro:

  1. Estrategia de creación de mercado dinámico

    • Ajustes de precios adaptativos en función de la volatilidad del mercado
    • Ajustar dinámicamente las estrategias de órdenes pendientes en función de la profundidad del libro de órdenes
    • Introducción del aprendizaje automático para predecir la dirección del mercado
  2. Estrategia de gestión de inventario

    • Monitoreo de inventario en tiempo real y evaluación de riesgos
    • Mecanismo de cobertura dinámica y algoritmo de equilibrio de inventario
    • Estrategia de inclinación de precios basada en el estado del inventario
  3. Estrategia de creación de mercado multinivel

    • Proporcionar liquidez en múltiples niveles de precios simultáneamente
    • Dispersar los riesgos puntuales y mejorar la estabilidad general
    • Más cerca del funcionamiento real de los creadores de mercado profesionales
  4. Gestión inteligente de riesgos

    • Monitoreo de indicadores de riesgo en tiempo real
    • Mecanismo automático de stop-loss y control de riesgos
    • Manejo de emergencia de situaciones anormales de mercado

Código de Estrategia (Revisado)

import time, json

class MidClass:
    def __init__(self, exchange_instance):
        '''
        初始化交易所中间层
        
        Args:
            exchange_instance: FMZ的交易所结构
        '''
        self.init_timestamp = time.time()  # 记录初始化时间
        self.exchange = exchange_instance  # 保存交易所对象
        self.exchange_name = self.exchange.GetName()  # 获取交易所名称
        self.trading_pair = self.exchange.GetCurrency()  # 获取交易对名称(如 BTC_USDT)

    def get_precision(self):
        '''
        获取交易对的精度信息
        
        Returns:
            返回包含精度信息的字典,失败时返回 None
        '''
        symbol_code = self.exchange.GetCurrency()
        ticker = self.exchange.GetTicker(symbol_code)  # 回测系统需要
        exchange_info = self.exchange.GetMarkets()
        data = exchange_info.get(symbol_code)

        if not data:
            Log("获取市场信息失败", GetLastError())
            return None

        # 获取该交易对的精度信息
        self.precision_info = {
            'tick_size': data['TickSize'],                  # 价格精度
            'amount_size': data['AmountSize'],              # 数量精度
            'price_precision': data['PricePrecision'],      # 价格小数位精度
            'amount_precision': data['AmountPrecision'],    # 数量小数位精度
            'min_qty': data['MinQty'],                      # 最小下单数量
            'max_qty': data['MaxQty']                       # 最大下单数量
        }

        return self.precision_info

    def get_account(self):
        '''
        获取账户信息
        
        Returns:
            获取信息成功返回 True,获取信息失败返回 False
        '''

        self.balance = '---'  # 账户余额
        self.amount = '---'  # 账户持仓量
        self.frozen_balance = '---'  # 冻结余额
        self.frozen_stocks = '---'  # 冻结持仓量
        self.init_balance = None
        self.init_stocks = None
        self.init_equity = None

        try:
            account_info = self.exchange.GetAccount()  # 获取账户信息
            self.balance = account_info['Balance']  # 更新账户余额
            self.amount = account_info['Stocks']  # 更新持仓量
            self.frozen_balance = account_info['FrozenBalance']  # 更新冻结余额
            self.frozen_stocks = account_info['FrozenStocks']  # 更新冻结持仓量
            self.equity = self.balance + self.frozen_balance + (self.amount + self.frozen_stocks) * self.last_price
            
            if not self.init_balance or not self.init_stocks or not self.init_equity:
                if _G("init_balance") and _G("init_balance") > 0 and _G("init_stocks") and _G("init_stocks") > 0:
                    self.init_balance = round(_G("init_balance"), 2)
                    self.init_stocks = round(_G("init_stocks"), 2)
                    self.init_equity = round(_G("init_equity"), 2)
                else:
                    self.init_balance = round(self.balance + self.frozen_balance, 2)
                    self.init_stocks = self.amount + self.frozen_stocks
                    self.init_equity = round(self.init_balance + (self.init_stocks * self.last_price), 2)
                    _G("init_balance", self.init_balance)
                    _G("init_stocks", self.init_stocks)
                    _G("init_equity", self.init_equity)

                    Log('获取初始eqity', self.init_equity)

            self.profit = self.equity - self.init_equity
            self.profitratio = round((self.equity - self.init_equity)/self.init_equity, 4) * 100

            return True
        except:
            return False  # 获取账户信息失败

    def get_ticker(self):
        '''
        获取市价信息(如买一价、卖一价、最高价、最低价等)
        
        Returns:
            获取信息成功返回 True,获取信息失败返回 False
        '''
        self.high_price = '---'  # 最高价
        self.low_price = '---'  # 最低价
        self.sell_price = '---'  # 卖一价
        self.buy_price = '---'  # 买一价
        self.last_price = '---'  # 最新成交价
        self.volume = '---'  # 成交量
        
        try:
            ticker_info = self.exchange.GetTicker()  # 获取市价信息
        
            self.high_price = ticker_info['High']  # 更新最高价
            self.low_price = ticker_info['Low']  # 更新最低价
            self.sell_price = ticker_info['Sell']  # 更新卖一价
            self.buy_price = ticker_info['Buy']  # 更新买一价
            self.last_price = ticker_info['Last']  # 更新最新成交价
            self.volume = ticker_info['Volume']  # 更新成交量
            return True
        except:
            return False  # 获取市价信息失败
        
    def get_depth(self):
        '''
        获取深度信息(买卖盘的挂单列表)
        
        Returns:
            获取信息成功返回 True,获取信息失败返回 False
        '''
        self.ask_orders = '---'  # 卖盘挂单列表
        self.bid_orders = '---'  # 买盘挂单列表
        
        try:
            depth_info = self.exchange.GetDepth()  # 获取深度信息
            self.ask_orders = depth_info['Asks']  # 更新卖盘挂单列表
            self.bid_orders = depth_info['Bids']  # 更新买盘挂单列表
            return True
        except:
            return False  # 获取深度信息失败
        
    def get_ohlc_data(self, period=PERIOD_M5):
        '''
        获取K线信息
        
        Args:
            period: K线周期,PERIOD_M1 指1分钟, PERIOD_M5 指5分钟, PERIOD_M15 指15分钟,
            PERIOD_M30 指30分钟, PERIOD_H1 指1小时, PERIOD_D1 指一天。
        '''
        self.ohlc_data = self.exchange.GetRecords(period)  # 获取K线数据
        
    def create_order(self, order_type, price, amount):
        '''
        提交一个挂单信息
        
        Args:
            order_type:挂单类型,'buy'指挂买单,'sell'指挂卖单
            price:挂单价格
            amount:挂单数量
            
        Returns:
            挂单Id号,可用以取消挂单
        '''
        if order_type == 'buy':
            try:
                order_id = self.exchange.Buy(price, amount)  # 提交买单
            except:
                return False  # 买单提交失败
            
        elif order_type == 'sell':
            try:
                order_id = self.exchange.Sell(price, amount)  # 提交卖单
            except:
                return False  # 卖单提交失败
        
        return order_id  # 返回订单ID
    
    def get_orders(self):
        '''
        获取未完成的订单列表
        
        Returns:
            未完成的订单列表
        '''
        self.open_orders = self.exchange.GetOrders()  # 获取未完成订单
        return self.open_orders
    
    def cancel_order(self, order_id):
        '''
        取消一个挂单信息
        
        Args:
            order_id:希望取消的挂单ID号
            
        Returns:
            取消挂单成功返回 True,取消挂单失败返回 False
        '''
        return self.exchange.CancelOrder(order_id)  # 取消订单
        
    def refresh_data(self):
        '''
        刷新信息(账户、市价、深度、K线)
        
        Returns:
            刷新信息成功返回 'refresh_data_finish!' 否则返回相应刷新失败的信息提示
        '''

        if not self.get_ticker():  # 刷新市价信息
            return 'false_get_ticker'

        if not self.get_account():  # 刷新账户信息
            return 'false_get_account'
        
        if not self.get_depth():  # 刷新深度信息
            return 'false_get_depth'
        
        try:
            self.get_ohlc_data()  # 刷新K线信息
        except:
            return 'false_get_K_line_info'
        
        return 'refresh_data_finish!'  # 刷新成功


class MarketMaker:
    def __init__(self, mid_class):
        '''
        初始化做市策略
        
        Args:
            mid_class: 交易所中间层对象
        '''
        self.exchange_mid = mid_class  # 交易所中间层对象
        self.precision_info = self.exchange_mid.get_precision()  # 获取精度信息

        self.done_amount = {'pan_kou': 0}  # 已完成交易量
        # 修正:正确分配精度信息
        self.price_precision = self.precision_info['price_precision']  # 价格精度
        self.amount_precision = self.precision_info['amount_precision']  # 交易量精度
        
        self.traded_pairs = {'pan_kou': []}  # 已挂单的交易对
        self.pending_orders = []  # 未完成的订单状态
        self.pending_order_count = 0  # 挂单次数

        self.buy_amount = 0
        self.sell_amount = 0

        self.fee = 0
        self.fee_rate = 0.08 / 100

        self.chart = {
            "__isStock": True,
            "tooltip": {"xDateFormat": "%Y-%m-%d %H:%M:%S, %A"},
            "title": {"text": "挂单数量"},
            "xAxis": {"type": "datetime"},
            "yAxis": {
                "title": {"text": "挂单数量"},
                "opposite": False
            },
            "series": [
                {"name": "挂单买量", "id": "挂单买量", "data": []},
                {"name": "挂单卖量", "id": "挂单卖量", "dashStyle": "shortdash", "data": []}
            ]
        }

    def refresh_data(self):
        '''
        刷新数据(账户、市价、深度、K线)
        '''
        self.exchange_mid.refresh_data()  # 刷新交易所数据
        self.position_amount = 0 if isinstance(self.exchange_mid.amount, str) else self.exchange_mid.amount  # 持仓量
        self.available_balance = 0 if isinstance(self.exchange_mid.balance, str) else self.exchange_mid.balance  # 账户余额

        self.can_buy_amount = self.available_balance / float(self.exchange_mid.buy_price)  # 可买的数量
        self.mid_price = (self.exchange_mid.sell_price + self.exchange_mid.buy_price) / 2  # 中间价

    def make_trade_by_dict(self, trade_dict):
        '''
        根据交易字典执行交易
        
        Args:
            trade_dict: 交易字典
        '''
        Log('4按照字典开始交易')
        self.refresh_data()  # 刷新数据
        
        if trade_dict['do_trade']:
            Log('当前账户资金: 币数余额: ', self.position_amount, '资金余额: ', self.can_buy_amount)
            Log('检查开仓: 币数限制: ', self.position_amount > trade_dict['amount'], '资金限制: ', self.can_buy_amount > trade_dict['amount'])
            if self.position_amount > trade_dict['amount'] and self.can_buy_amount > trade_dict['amount']:
                buy_id = self.exchange_mid.create_order('buy', trade_dict['buy_price'], trade_dict['amount'])  # 挂买单
                sell_id = self.exchange_mid.create_order('sell', trade_dict['sell_price'], trade_dict['amount'])  # 挂卖单
                
                self.traded_pairs['pan_kou'].append({
                    'buy_id': buy_id, 'sell_id': sell_id, 'init_time': time.time(), 'amount': trade_dict['amount']
                })
                    
                self.last_time = time.time()  # 更新上次交易时间
        
    def handle_pending_orders(self):
        '''
        处理未完成的订单
        '''
        pending_orders = self.exchange_mid.get_orders()  # 获取未完成订单
        if len(pending_orders) > 0:
            for order in pending_orders:
                self.exchange_mid.cancel_order(order['Id'])  # 取消未完成订单
                
    def make_pankou_dict(self, price_range, min_price_step, trade_amount):
        
        '''
        生成盘口挂单字典
        
        Args:
            price_range: 价格范围
            min_price_step: 最小价格间隔
            trade_amount: 每次交易量
        
        Returns:
            盘口挂单字典列表
        '''
        Log('3制作盘口挂单字典', '移动盘口次数', self.pending_order_count)
        mid_price = self.mid_price  # 中间价
        
        price_offset = price_range - self.pending_order_count * min_price_step  # 计算价格偏移量
        do_trade = price_offset > 0

        if do_trade:
            buy_price = mid_price - price_offset  # 计算买价
            buy_price = round(buy_price, self.price_precision)  # 四舍五入买价
            
            sell_price = mid_price + price_offset  # 计算卖价
            sell_price = round(sell_price, self.price_precision)  # 四舍五入卖价

            trade_dict = {
                'do_trade': do_trade,
                'buy_price': buy_price,
                'sell_price': sell_price,
                'amount': trade_amount
            }

            Log('返回盘口挂单字典:', trade_dict)
            return trade_dict
        else:
            Log('重置移动盘口次数:', self.pending_order_count)
            self.pending_order_count = 0  # 重置移动盘口次数
            # 修正:当不能交易时返回None或空字典
            return None
            
    
    def check_order_status(self, current_time):
        '''
        检查订单状态
        
        Args:
            current_time: 当前时间戳
        '''
        Log('1开始订单信息检查')
        Log(self.traded_pairs['pan_kou'])
        self.buy_pending = 0
        self.sell_pending = 0
        for traded_pair in self.traded_pairs['pan_kou'].copy():
            Log('检查订单:', traded_pair['buy_id'], traded_pair['sell_id'])

            try:
                buy_order_status = self.exchange_mid.exchange.GetOrder(traded_pair['buy_id'])  # 获取买单状态
                sell_order_status = self.exchange_mid.exchange.GetOrder(traded_pair['sell_id'])  # 获取卖单状态
            except:
                Log(traded_pair, '取消')
                self.exchange_mid.cancel_order(traded_pair['buy_id'])  # 取消买单
                self.exchange_mid.cancel_order(traded_pair['sell_id'])  # 取消卖单
                self.traded_pairs['pan_kou'].remove(traded_pair)  # 移除订单
                return

            Log('检查订单:', traded_pair['buy_id'], buy_order_status, traded_pair['sell_id'], sell_order_status, [sell_order_status['Status'], buy_order_status['Status']])
            if [sell_order_status['Status'], buy_order_status['Status']] == [0, 0]:
                self.buy_pending += 1
                self.sell_pending += 1
                if current_time % 5 == 0:
                    Log('检查挂单,取消挂单(两未完)', buy_order_status['Status'], sell_order_status['Status'], current_time % 5)
                    self.exchange_mid.cancel_order(traded_pair['buy_id'])  # 取消买单
                    self.exchange_mid.cancel_order(traded_pair['sell_id'])  # 取消卖单
                    self.pending_order_count += 1  # 移动盘口次数次数加1
                    self.traded_pairs['pan_kou'].remove(traded_pair)  # 移除订单

            elif {sell_order_status['Status'], buy_order_status['Status']} == {1, 0}:
                if buy_order_status['Status'] == ORDER_STATE_PENDING:
                    self.buy_pending += 1
                if sell_order_status['Status'] == ORDER_STATE_PENDING:
                    self.sell_pending += 1
                if current_time % 5 == 0:
                    Log('检查挂单,取消挂单(一未完)', buy_order_status['Status'], sell_order_status['Status'])
                    self.done_amount['pan_kou'] += traded_pair['amount']  # 更新交易量
                    if buy_order_status['Status'] == ORDER_STATE_PENDING:
                        self.sell_amount += traded_pair['amount']
                        self.fee += sell_order_status['Amount'] * self.fee_rate * sell_order_status['Price']
                        Log('取消该买订单,增加未完成买列表', traded_pair['buy_id'])
                        self.exchange_mid.cancel_order(traded_pair['buy_id'])  # 取消买单
                        self.pending_orders.append(['buy', buy_order_status['Status']])  # 记录未完成订单
                        Log('清除前:', self.traded_pairs['pan_kou'])
                        Log('清除id:', traded_pair)
                        self.traded_pairs['pan_kou'].remove(traded_pair)  # 移除订单
                        Log('清除后:', self.traded_pairs['pan_kou'])
                    elif sell_order_status['Status'] == ORDER_STATE_PENDING:
                        self.buy_amount += traded_pair['amount']
                        self.fee += buy_order_status['Amount'] * self.fee_rate * buy_order_status['Price']
                        Log('取消该卖订单,增加未完成卖列表', traded_pair['sell_id'])
                        self.exchange_mid.cancel_order(traded_pair['sell_id'])  # 取消卖单
                        self.pending_orders.append(['sell', sell_order_status['Status']])  # 记录未完成订单
                        Log('清除前:', self.traded_pairs['pan_kou'])
                        Log('清除id:', traded_pair)
                        self.traded_pairs['pan_kou'].remove(traded_pair)  # 移除订单
                        Log('清除后:', self.traded_pairs['pan_kou'])
                
            elif [sell_order_status['Status'], buy_order_status['Status']] == [1, 1]:
                Log('两订单都已完成')
                Log('完成状态:', buy_order_status['Status'], sell_order_status['Status'], traded_pair['amount'])
                self.done_amount['pan_kou'] += 2 * traded_pair['amount']  # 更新交易量
                self.buy_amount += traded_pair['amount']
                self.sell_amount += traded_pair['amount']
                self.fee += buy_order_status['Amount'] * self.fee_rate * buy_order_status['Price']
                self.fee += sell_order_status['Amount'] * self.fee_rate * sell_order_status['Price']
                self.traded_pairs['pan_kou'].remove(traded_pair)  # 移除订单
            else:
                Log('两订单处于未知状态:', buy_order_status, sell_order_status)
                Log('未知订单状态:', buy_order_status['Status'], sell_order_status['Status'])
                Log('未知订单信息:', traded_pair)

    def update_status(self):

        self.exchange_mid.refresh_data()

        table1 = {
            "type": "table",
            "title": "账户信息",
            "cols": [
                "初始资金", "现存资金", "盘口买入数量", "盘口卖出数量", "费率", "总收益", "收益率"
            ],
            "rows": [
                [   
                    self.exchange_mid.init_equity,
                    self.exchange_mid.equity,
                    round(self.buy_amount, 4),
                    round(self.sell_amount, 4),
                    round(self.fee, 2),
                    self.exchange_mid.profit,
                    str(self.exchange_mid.profitratio) + "%"
                ],
            ],
        }

        LogStatus(
            f"初始化时间: {time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(self.exchange_mid.init_timestamp))}\n",
            f"`{json.dumps(table1)}`\n",
            f"最后执行时间: {_D()}\n"
        )

        LogProfit(round(self.exchange_mid.profit, 3), '&')

    def plot_pending(self):
        
        Log('盘口挂单数量:', self.buy_pending, self.sell_pending)
        self.obj_chart = Chart(self.chart)
        now_time = int(time.time() * 1000)
        # 更新挂单买量数据
        self.obj_chart.add(0, [now_time, self.buy_pending])
        # 更新挂单卖量数据
        self.obj_chart.add(1, [now_time, self.sell_pending])

def main():
    '''
    主函数,运行做市策略
    '''
    exchange.IO('simulate', True) #OKX现货模拟账户
    exchange.IO("trade_super_margin")

    current_time = 0
    target_amount = 1  # 目标交易量
    
    price_range = 5  # 价格范围
    min_price_step = 1  # 最小价格间隔
    trade_amount = 0.01  # 每次交易量
    
    exchange_mid = MidClass(exchange)  # 初始化交易所中间层
    Log(exchange_mid.refresh_data())  # 刷新数据
    market_maker = MarketMaker(exchange_mid)  # 初始化做市策略
    
    # 修正:初始化trade_dict
    trade_dict = None
    
    while market_maker.done_amount['pan_kou'] < target_amount:  # 循环直到完成目标交易量
        Log(market_maker.traded_pairs['pan_kou'])
        market_maker.check_order_status(current_time)  # 检查订单状态
        Sleep(1000)  # 等待1秒
        market_maker.refresh_data()  # 刷新数据
        
        if len(market_maker.traded_pairs['pan_kou']) < 1: # 价格移动,盘口挂单撤销,等待至所有挂单完毕,制定新的挂单字典
            
            Log('2盘口交易对数量小于1')
            trade_dict = market_maker.make_pankou_dict(price_range, min_price_step, trade_amount)  # 生成盘口挂单字典
            Log('新交易字典', trade_dict)
        
        # 修正:确保trade_dict存在且不为None
        if trade_dict and trade_dict.get('do_trade', False):
            market_maker.make_trade_by_dict(trade_dict)  # 执行交易

        Log('盘口做市数量:', market_maker.done_amount['pan_kou'])  # 记录交易量

        market_maker.plot_pending()
        market_maker.update_status()
        current_time += 1
        
    Log(market_maker.position_amount, market_maker.can_buy_amount)  # 记录持仓量和可买数量
    Log('现存订单:', exchange.GetOrders())  # 记录现存订单

def onexit():
    Log("执行扫尾函数")

    _G("init_balance", None)
    _G("init_stocks", None)
    _G("init_equity", None)