2
フォロー
319
フォロワー

デジタル通貨のマーケットメイク戦略に関する簡単な議論(2):市場戦略

作成日:: 2025-08-01 11:28:35, 更新日:: 2025-08-04 14:15:40
comments   0
hits   692

序文

前回の記事「仮想通貨におけるウォッシュトレード戦略」では、同じ価格で売買することで取引量を積み上げる戦略フレームワークを詳しく説明しました。この戦略の主な目的は、価格裁定取引による利益ではなく、取引所のリベートやティア特典の獲得です。ウォッシュトレード戦略は取引フレームワークを学ぶ上で有益ですが、実際の収益性は限られており、コンプライアンスリスクに直面する可能性があります。

この記事では、前回の記事に基づいて、さらに実践的なマーケット メイク戦略を紹介します。ハンディキャップ戦略ウォッシュ・トレーディング戦略とは異なり、マーケット・メーカー戦略は、買値と売値のスプレッドを設定することで利益を生み出す真の裁定取引戦略であり、従来のマーケット・メーカーの利益モデルに近いものです。

⚠️重要なお知らせ

この記事で紹介する市場戦略コードは、学習フレームワークとしてのみ提供されており、実際の取引経験を反映したものではありません。ここで紹介する戦略は、技術的な学習および研究のみを目的としており、実際の市場環境において完全に検証されていません。読者の皆様は、この情報を使用する前に、徹底的なバックテストとリスク評価を実施することをお勧めします。また、実際の取引で直接使用することは避けてください。


ハンディキャップ戦略の原則

成行注文板戦略は、成行注文板(つまり市場の厚み)を裁定取引に利用するマーケットメイク戦略です。この戦略では、マーケットメーカーは市場の変動に基づいて、ビッド価格とアスク価格の差額内で注文価格を動的に調整し、注文を発注・キャンセルすることで、市場流動性と短期的な価格変動を利用して利益を上げます。

コア機能

  1. 保留中の注文価格を動的に調整する:市場の深さや価格変動に基づいて売買注文の価格を動的に調整し、取引の確率を高めます。
  2. 保留中の注文の数を制御する: 市場リスクへの過度の露出を避けるために、口座資金とポジションに基づいて保留注文の数を制御します。
  3. 注文状況管理: 注文状況を定期的に確認し、未完了の注文を処理します。

ノックオン戦略との違い

特徴 ボリュームブースト戦略 ハンディキャップ戦略
売買価格 同じ価格 異なる価格(価格差あり)
利益モデル 交換リベート/インセンティブ ビッド・アスク・スプレッド
リスクエクスポージャー 低(同価格取引) 高(価格変動リスク)
実用性 限定 より高い

ハンディキャップ戦略の利点

  • 市場流動性の向上:市場に注文を出すことで、市場の売買の深さを増やし、より多くのトレーダーの参加を促します。
  • ビッド・アスク・スプレッドを獲得流動性を提供することで、マーケットメーカーは売買スプレッドを獲得し、利益を上げることができます。
  • 市場の変動に柔軟に対応する:市場戦略は、市場の変動に応じて保留注文の価格を動的に調整し、市場リスクを軽減します。

ハンディキャップ戦略の課題

  • 市場リスク: 市場価格の変動により、マーケットメーカーの注文が執行されなかったり、損失が発生したりする場合があります。
  • 財政的圧力:マーケットメーカーは市場の売買の厚みを維持するために十分な資金を必要とします。資金が不足すると、戦略が失敗する可能性があります。
  • 複雑な注文管理:市場戦略では、注文状況を定期的に確認し、未完了の注文を処理する必要があり、戦略の複雑さが増します。

ハンディキャップ戦略構造

ストライク戦略と一致して、この記事のコードは、主に 2 つのカテゴリに分けられる市場見積もり戦略に基づくマーケット メイク戦略を実装します。

  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)