2
Подписаться
319
Подписчики

Краткое обсуждение стратегий создания рынка цифровых валют (2): Рыночная стратегия

Создано: 2025-08-01 11:28:35, Обновлено: 2025-08-04 14:15:40
comments   0
hits   692

Предисловие

В нашей предыдущей статье «Стратегии фиктивной торговли криптовалютами» мы подробно описали стратегию накопления объёма торгов путём покупки и продажи по одинаковой цене. Основная цель этой стратегии — получение биржевых скидок или дополнительных бонусов, а не получение прибыли от ценового арбитража. Хотя стратегии фиктивной торговли полезны для изучения торговых фреймворков, их реальная прибыльность ограничена, и они могут быть связаны с рисками несоблюдения нормативных требований.

В этой статье будет представлена еще одна более практичная стратегия создания рынка, основанная на предыдущей статье:Стратегия гандикапаВ отличие от стратегии фиктивной торговли, стратегия маркет-мейкера представляет собой настоящую арбитражную стратегию, которая генерирует прибыль за счет установления спреда между ценами покупки и продажи, что больше соответствует модели получения прибыли традиционными маркет-мейкерами.

⚠️ Важное уведомление

Представленный в этой статье код рыночной стратегии предназначен исключительно в качестве учебной программы и не отражает реальный торговый опыт. Представленные здесь стратегии предназначены исключительно для технического обучения и исследований и не прошли полную проверку в реальных рыночных условиях. Читателям рекомендуется провести тщательное тестирование на исторических данных и оценку рисков перед использованием этой информации. Не следует использовать её напрямую в реальной торговле.


Принципы стратегии гандикапа

Стратегия «рыночная книга ордеров» — это маркет-мейкерская стратегия, использующая рыночную книгу ордеров (то есть глубину рынка) для арбитража. В рамках этой стратегии маркет-мейкеры динамически корректируют цену ордера в пределах разницы между ценами спроса и предложения, основываясь на рыночных колебаниях, размещая и отменяя ордера, тем самым извлекая прибыль из рыночной ликвидности и краткосрочных колебаний цен.

Основные характеристики

  1. Динамически корректировать цены отложенных ордеров:Динамически корректируйте цены ордеров на покупку и продажу на основе глубины рынка и колебаний цен, чтобы увеличить вероятность совершения транзакций.
  2. Контролируйте количество отложенных ордеров: Контролируйте количество отложенных ордеров на основе средств на счете и позиций, чтобы избежать чрезмерной подверженности рыночным рискам.
  3. Управление статусом заказа: Регулярно проверяйте статус заказа и обрабатывайте незавершенные заказы.

Отличия от стратегии «домино»

особенность Стратегия увеличения объема Стратегия гандикапа
Цены покупки и продажи Та же цена Разные цены (с разницей в цене)
Модель прибыли Скидки/поощрения при обмене спред спроса и предложения
Подверженность риску Низкая (транзакция по той же цене) Высокий (риск волатильности цен)
Практичность ограниченный Выше

Преимущества стратегии гандикапа

  • Повышение ликвидности рынка:Размещая ордера на рынке, мы можем увеличить глубину рынка покупок и продаж и привлечь к участию больше трейдеров.
  • Заработайте на спреде между ценой покупки и продажи: Предоставляя ликвидность, маркет-мейкеры могут зарабатывать на спреде между ценой покупки и продажи и, таким образом, получать прибыль.
  • Гибко реагировать на колебания рынка:Рыночная стратегия позволяет динамически корректировать цену отложенного ордера в соответствии с рыночными колебаниями, чтобы снизить рыночные риски.

Проблемы стратегии гандикапа

  • Рыночный риск: Колебания рыночных цен могут привести к неисполнению ордеров маркет-мейкера или даже к убыткам.
  • Финансовое давление:Маркет-мейкерам необходимо достаточное количество средств для поддержания глубины рынка. Недостаток средств может привести к провалу стратегии.
  • Комплексное управление заказами:Рыночная стратегия требует регулярной проверки статуса заказов и обработки невыполненных заказов, что увеличивает сложность стратегии.

Структура стратегии гандикапа

В соответствии со стратегией забастовки код в этой статье реализует стратегию маркет-мейкинга, основанную на стратегии рыночных котировок, которая в основном делится на две категории:

  1. MidClass: Средний уровень биржи отвечает за взаимодействие с интерфейсом биржи для получения рыночных данных, информации о счете, статусе заказа и т. д.
  2. MarketMaker: Класс стратегии создания рынка, отвечающий за реализацию рыночной стратегии, динамическую генерацию цен отложенных ордеров, генерацию отложенных ордеров, проверку статуса ордера, обновление статуса стратегии и т. д.

Процесс стратегии гандикапа

1. Инициализация

существовать MarketMakerВ методе инициализации класса сначала получите информацию о точности биржи и инициализируйте параметры стратегии, такие как точность объема транзакций, точность цены и т. д.

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. Создайте словарь отложенных ордеров.

Суть рыночной стратегии заключается в формировании словаря отложенных ордеров, содержащего цены покупки и продажи, а также объёмы. Код формирует этот словарь, рассчитывая среднюю цену и смещение цены.

3. Движение цен отложенных ордеров

Движение цены отложенного ордера определяется путем расчета смещения цены. Смещение цены основано на ценовом диапазоне (price_range) и минимальный ценовой интервал (min_price_step) рассчитано.

price_offset = price_range - self.pending_order_count * min_price_step  # 计算价格偏移量
do_trade = price_offset > 0
  • price_range: Диапазон цен, указывающий диапазон отклонения между ценой отложенного ордера и средней ценой.
  • min_price_step: Минимальный ценовой интервал, указывающий минимальный шаг корректировки цены каждого отложенного ордера.
  • price_offset: Смещение цены, которое указывает отклонение между текущей ценой ордера и средней ценой.

Если смещение цены больше 0, это означает, что ордер может быть размещен дальше; в противном случае количество отложенных ордеров сбрасывается.

4. Создать словарь отложенных ордеров

На основе смещения цен рассчитываются цены покупки и продажи, а также формируется словарь отложенных ордеров.

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: Цена предложения, рассчитанная как средняя цена за вычетом смещения цены.
  • sell_price: Цена предложения, рассчитанная как средняя цена плюс смещение цены.
  • trade_dict: Словарь отложенных ордеров, включая цены покупки и продажи, а также количество.

5. Совершайте рыночные сделки

В соответствии с сформированным словарем заказов выполните транзакцию заказа.create_orderМетод заключается в одновременном размещении ордеров на покупку и продажу.

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. Проверьте статус заказа

Регулярно проверяйте статус ордеров и обрабатывайте невыполненные. Логика обработки статуса ордеров аналогична стратегии кросс-трейдинга, но из-за разницы цен частичное исполнение может привести к фактической прибыли или убытку.

Основные недостатки стратегии гандикапа

1. Движение цены отложенных ордеров недостаточно гибкое.

Механизм корректировки цен в этой стратегии относительно прост и имеет следующие ограничения:

price_offset = price_range - self.pending_order_count * min_price_step  # 计算价格偏移量
  • Предел линейной корректировки:Ценовое смещение осуществляется по методу линейного убывания и не может динамически корректироваться в соответствии с фактической волатильностью рынка.
  • Параметр затвердеванияprice_range и min_price_stepЭто фиксированный параметр, который не может быть скорректирован в режиме реального времени в соответствии с рыночными условиями.
  • Гистерезис отклика: Когда рыночные цены быстро меняются, корректировка цен стратегии может не поспевать за рыночным ритмом.
  • Недостаточная осведомленность рынка: Он не учитывает факторы микроструктуры рынка, такие как глубина книги заказов и объем торгов.

Направление улучшения

  • Внедрение динамического механизма корректировки цен на основе волатильности
  • Отрегулируйте цены отложенных ордеров на основе глубины рынка и ликвидности
  • Улучшите свое суждение о рыночных тенденциях и избегайте размещения заказов против тренда

2. Риск инвентаризации

Рыночная стратегия сталкивается с серьезными проблемами, связанными с риском потери запасов:

Эффективность риска

  • Риск односторонней транзакции:Когда исполняются только ордера на покупку или только ордера на продажу, это приведет к несбалансированной позиции.
  • Направленный риск: На трендовом рынке может накапливаться большое количество односторонних позиций.
  • Оккупация столицы: Избыточные запасы будут занимать много средств и влиять на эффективность стратегии.

Точки риска в коде

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']  # 只有买单成交,积累多头持仓

Влияние риска инвентаризации

  • Снижение рентабельности: Односторонние позиции приведут к убыткам при неблагоприятных изменениях цен.
  • Давление ликвидности:Для хеджирования рисков, связанных с запасами, необходимы дополнительные средства.
  • Стратегия не работает: В крайних случаях стратегия может не продолжать работать.

Меры управления рисками

  • Ограничения по инвентарю: Установите максимальный лимит позиции, чтобы предотвратить чрезмерное накопление
  • Динамическое хеджирование: Когда запасы превышают пороговое значение, активно закрывайте или хеджируйте
  • Ценовой наклон:Корректировать цены покупки и продажи на основе текущих запасов, чтобы стимулировать обратные транзакции

Резюме стратегии

Стратегия маркет-мейкинга основана на глубине рынка. Она поддерживает ликвидность рынка, динамически корректируя цену и количество ордеров на покупку и продажу. В отличие от стратегии фиктивной торговли, стратегия маркет-мейкинга обладает следующими характеристиками:

✅ Преимущества

  • Получайте реальную арбитражную прибыль за счет разницы цен
  • В соответствии с моделью прибыли традиционных маркет-мейкеров
  • Обеспечение реальной рыночной ликвидности

❌ Вызов

  • Столкнувшись с рисками колебаний рыночных цен
  • Необходимо более сложное управление рисками
  • Более высокие требования к средствам и технологиям
  • Механизм корректировки цен недостаточно гибкий:Механизм линейного движения цен трудно адаптировать к сложной рыночной среде.
  • Значительные риски, связанные с запасами: Односторонние транзакции могут легко привести к несбалансированным позициям, а риск особенно значителен на трендовых рынках.

🔮 Направления будущей оптимизации

Учитывая недостатки текущей стратегии гандикапа, в будущем мы можем оптимизировать и усовершенствовать ее в следующих направлениях:

  1. Стратегия динамического создания рынка

    • Адаптивная корректировка цен на основе волатильности рынка
    • Динамически корректируйте стратегии отложенных ордеров на основе глубины книги ордеров
    • Внедрение машинного обучения для прогнозирования направления рынка
  2. Стратегия управления запасами

    • Мониторинг запасов в режиме реального времени и оценка рисков
    • Механизм динамического хеджирования и алгоритм балансировки запасов
    • Стратегия изменения цен, основанная на состоянии запасов
  3. Стратегия многоуровневого маркет-мейкинга

    • Обеспечение ликвидности на нескольких уровнях цен одновременно
    • Распределите точечные риски и повысьте общую стабильность
    • Ближе к реальной работе профессиональных маркет-мейкеров
  4. Умный риск-менеджмент

    • Мониторинг индикаторов риска в реальном времени
    • Автоматический механизм остановки потерь и контроля рисков
    • Экстренное урегулирование ненормальных рыночных ситуаций

Стратегический код (пересмотренный)

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)