avatar of ianzeng123 ianzeng123
집중하다 사신
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)