2
tập trung vào
319
Người theo dõi

Thảo luận ngắn gọn về Chiến lược tạo lập thị trường tiền kỹ thuật số (2): Chiến lược thị trường

Được tạo ra trong: 2025-08-01 11:28:35, cập nhật trên: 2025-08-04 14:15:40
comments   0
hits   692

Lời nói đầu

Trong bài viết trước, “Chiến lược giao dịch rửa tiền trong tiền kỹ thuật số”, chúng tôi đã trình bày chi tiết một khuôn khổ chiến lược để tích lũy khối lượng giao dịch bằng cách mua và bán ở cùng một mức giá. Mục đích chính của chiến lược này là để nhận được chiết khấu giao dịch hoặc lợi ích theo cấp bậc, thay vì kiếm lời từ chênh lệch giá. Mặc dù các chiến lược giao dịch rửa tiền rất hữu ích để tìm hiểu về khuôn khổ giao dịch, nhưng lợi nhuận thực tế của chúng bị hạn chế và có thể phải đối mặt với rủi ro tuân thủ.

Bài viết này sẽ giới thiệu một chiến lược tạo lập thị trường thực tế hơn dựa trên bài viết trước:Chiến lược chấpKhông giống như chiến lược giao dịch rửa tiền, chiến lược tạo lập thị trường là một chiến lược chênh lệch giá thực sự tạo ra lợi nhuận bằng cách thiết lập mức chênh lệch giữa giá mua và giá bán, phù hợp hơn với mô hình lợi nhuận của các nhà tạo lập thị trường truyền thống.

⚠️ Thông báo quan trọng

Mã chiến lược thị trường được trình bày trong bài viết này chỉ nhằm mục đích cung cấp một khuôn khổ học tập và không phản ánh bất kỳ kinh nghiệm giao dịch thực tế nào. Các chiến lược được trình bày ở đây chỉ nhằm mục đích học tập và nghiên cứu kỹ thuật và chưa được kiểm chứng đầy đủ trong điều kiện thị trường thực tế. Người đọc được khuyến cáo nên thực hiện kiểm tra ngược và đánh giá rủi ro kỹ lưỡng trước khi sử dụng thông tin này, và không nên áp dụng trực tiếp vào giao dịch thực tế.


Nguyên tắc chiến lược chấp

Chiến lược sổ lệnh thị trường là một chiến lược tạo lập thị trường, khai thác sổ lệnh thị trường (tức là độ sâu thị trường) để kinh doanh chênh lệch giá. Theo chiến lược này, các nhà tạo lập thị trường sẽ chủ động điều chỉnh giá lệnh trong khoảng chênh lệch giữa giá mua và giá bán dựa trên biến động thị trường, đặt và hủy lệnh, từ đó tận dụng tính thanh khoản của thị trường và biến động giá ngắn hạn để tạo ra lợi nhuận.

Các tính năng cốt lõi

  1. Điều chỉnh giá lệnh chờ một cách linh hoạt:Điều chỉnh giá lệnh mua và bán một cách linh hoạt dựa trên độ sâu thị trường và biến động giá để tăng khả năng giao dịch.
  2. Kiểm soát số lượng lệnh đang chờ xử lý: Kiểm soát số lượng lệnh chờ dựa trên số tiền trong tài khoản và vị thế để tránh tiếp xúc quá mức với rủi ro thị trường.
  3. Quản lý trạng thái đơn hàng: Kiểm tra trạng thái đơn hàng thường xuyên và xử lý các đơn hàng chưa hoàn thành.

Sự khác biệt so với chiến lược tiếp thị lan tỏa

tính năng Chiến lược tăng khối lượng Chiến lược chấp
Giá mua và giá bán Cùng giá Giá khác nhau (có chênh lệch giá)
Mô hình lợi nhuận Hoàn tiền/khuyến khích đổi hàng chênh lệch giá mua-bán
Tiếp xúc rủi ro Thấp (giao dịch cùng giá) Cao (rủi ro biến động giá)
Tính thực tiễn giới hạn Cao hơn

Ưu điểm của Chiến lược Chấp

  • Cải thiện tính thanh khoản của thị trường:Bằng cách đặt lệnh trên thị trường, chúng ta có thể tăng độ sâu mua và bán của thị trường và thu hút nhiều nhà giao dịch tham gia hơn.
  • Kiếm được chênh lệch giá mua-bán:Bằng cách cung cấp thanh khoản, các nhà tạo lập thị trường có thể kiếm được chênh lệch giá mua-bán và do đó kiếm được lợi nhuận.
  • Linh hoạt ứng phó với biến động của thị trường:Chiến lược thị trường có thể điều chỉnh giá lệnh chờ một cách linh hoạt theo biến động của thị trường để giảm thiểu rủi ro thị trường.

Những thách thức của Chiến lược Chấp

  • Rủi ro thị trường: Biến động giá thị trường có thể khiến lệnh của nhà tạo lập thị trường không được thực hiện hoặc thậm chí dẫn đến thua lỗ.
  • Áp lực tài chính:Nhà tạo lập thị trường cần đủ vốn để duy trì độ sâu mua và bán của thị trường. Thiếu vốn có thể khiến chiến lược thất bại.
  • Quản lý đơn hàng phức tạp:Chiến lược thị trường đòi hỏi phải kiểm tra thường xuyên trạng thái đơn hàng và xử lý các đơn hàng chưa hoàn thành, điều này làm tăng tính phức tạp của chiến lược.

Cấu trúc chiến lược chấp

Phù hợp với chiến lược tấn công, mã trong bài viết này triển khai chiến lược tạo lập thị trường dựa trên chiến lược báo giá thị trường, chủ yếu được chia thành hai loại:

  1. MidClass: Lớp trung gian trao đổi có trách nhiệm tương tác với giao diện trao đổi để lấy dữ liệu thị trường, thông tin tài khoản, trạng thái lệnh, v.v.
  2. MarketMaker: Lớp chiến lược tạo lập thị trường, chịu trách nhiệm thực hiện chiến lược thị trường, tạo giá lệnh chờ xử lý một cách linh hoạt, tạo lệnh chờ xử lý, kiểm tra trạng thái lệnh, cập nhật trạng thái chiến lược, v.v.

Quy trình chiến lược chấp

1. Khởi tạo

hiện hữu MarketMakerTrong phương pháp khởi tạo lớp, trước tiên hãy lấy thông tin về độ chính xác của sàn giao dịch và khởi tạo các tham số chiến lược, chẳng hạn như độ chính xác về khối lượng giao dịch, độ chính xác về giá, v.v.

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. Tạo một từ điển các đơn hàng đang chờ xử lý

Cốt lõi của chiến lược thị trường là tạo ra một từ điển các lệnh chờ, bao gồm giá mua và giá bán cùng số lượng. Mã tạo ra từ điển này bằng cách tính toán giá trung bình và chênh lệch giá.

3. Biến động giá lệnh chờ

Biến động giá của lệnh chờ được thực hiện bằng cách tính toán chênh lệch giá. Chênh lệch giá được tính dựa trên phạm vi giá (price_range) và khoảng giá tối thiểu (min_price_step) đã được tính toán.

price_offset = price_range - self.pending_order_count * min_price_step  # 计算价格偏移量
do_trade = price_offset > 0
  • price_range: Phạm vi giá, biểu thị phạm vi chênh lệch giữa giá lệnh chờ và giá trung bình.
  • min_price_step: Khoảng giá tối thiểu, cho biết bước điều chỉnh tối thiểu của mỗi mức giá lệnh chờ.
  • price_offset: Chênh lệch giá, biểu thị độ lệch giữa giá lệnh hiện tại và giá trung bình.

Nếu chênh lệch giá lớn hơn 0, điều đó có nghĩa là lệnh có thể tiếp tục được đặt; nếu không, số lượng lệnh đang chờ xử lý sẽ được đặt lại.

4. Tạo từ điển đơn hàng đang chờ xử lý

Dựa trên chênh lệch giá, giá mua và giá bán sẽ được tính toán và từ điển các lệnh đang chờ xử lý sẽ được tạo ra.

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: Giá thầu, được tính bằng giá trung bình trừ đi giá chênh lệch.
  • sell_price: Giá chào bán, được tính bằng giá trung bình cộng với giá chênh lệch.
  • trade_dict: Từ điển các lệnh đang chờ xử lý, bao gồm giá mua và giá bán cũng như số lượng.

5. Thực hiện giao dịch thị trường

Theo từ điển lệnh đã tạo, hãy thực hiện giao dịch lệnh.create_orderPhương pháp đặt lệnh mua và lệnh bán cùng lúc.

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. Kiểm tra trạng thái đơn hàng

Thường xuyên kiểm tra trạng thái lệnh và xử lý các lệnh chưa được thực hiện. Logic xử lý trạng thái lệnh tương tự như chiến lược giao dịch chéo, nhưng do chênh lệch giá, việc thực hiện một phần lệnh có thể dẫn đến lãi hoặc lỗ thực tế.

Những nhược điểm chính của chiến lược chấp

1. Biến động giá của các lệnh chờ không đủ linh hoạt

Cơ chế điều chỉnh giá trong chiến lược này tương đối đơn giản, với những hạn chế sau:

price_offset = price_range - self.pending_order_count * min_price_step  # 计算价格偏移量
  • Giới hạn điều chỉnh tuyến tính:Giá bù trừ áp dụng phương pháp giảm tuyến tính và không thể điều chỉnh động theo biến động thực tế của thị trường
  • Sự đông đặc của tham sốprice_rangemin_price_stepĐây là một tham số cố định và không thể điều chỉnh theo thời gian thực theo điều kiện thị trường
  • Độ trễ phản ứng: Khi giá thị trường thay đổi nhanh chóng, việc điều chỉnh giá của chiến lược có thể không theo kịp nhịp độ thị trường
  • Thiếu nhận thức về thị trường: Nó không tính đến các yếu tố vi mô của thị trường như độ sâu của sổ lệnh và khối lượng giao dịch

Hướng cải tiến

  • Giới thiệu cơ chế điều chỉnh giá năng động dựa trên sự biến động
  • Điều chỉnh giá lệnh chờ dựa trên độ sâu thị trường và tính thanh khoản
  • Cải thiện khả năng phán đoán xu hướng thị trường của bạn và tránh đặt lệnh ngược xu hướng

2. Rủi ro hàng tồn kho

Chiến lược thị trường phải đối mặt với các vấn đề rủi ro tồn kho nghiêm trọng:

Hiệu suất rủi ro

  • Rủi ro giao dịch đơn phương:Khi chỉ có lệnh mua hoặc lệnh bán được thực hiện, điều này sẽ dẫn đến vị thế mất cân bằng
  • Rủi ro định hướng: Trong một thị trường có xu hướng, một lượng lớn các vị thế một chiều có thể tích lũy
  • Chiếm đóng thủ đô: Hàng tồn kho quá mức sẽ chiếm nhiều tiền và ảnh hưởng đến hiệu quả của chiến lược

Điểm rủi ro trong mã

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

Tác động của rủi ro hàng tồn kho

  • Lợi nhuận giảm sút: Các vị thế đơn phương sẽ dẫn đến thua lỗ khi giá cả thay đổi bất lợi
  • Áp lực thanh khoản:Cần thêm vốn để phòng ngừa rủi ro hàng tồn kho
  • Chiến lược thất bại: Trong những trường hợp cực đoan, chiến lược có thể không tiếp tục chạy

Các biện pháp quản lý rủi ro

  • Hạn chế hàng tồn kho: Đặt giới hạn vị trí tối đa để ngăn ngừa tích lũy quá mức
  • Phòng ngừa rủi ro động: Khi hàng tồn kho vượt quá ngưỡng, hãy chủ động đóng vị thế hoặc phòng ngừa rủi ro
  • Giá nghiêng:Điều chỉnh giá mua và giá bán dựa trên hàng tồn kho hiện tại để khuyến khích giao dịch ngược

Tóm tắt chiến lược

Chiến lược tạo lập thị trường là chiến lược tạo lập thị trường dựa trên độ sâu thị trường. Chiến lược này duy trì tính thanh khoản của thị trường bằng cách điều chỉnh linh hoạt giá và khối lượng lệnh mua và lệnh bán. So với chiến lược giao dịch rửa tiền, chiến lược tạo lập thị trường có những đặc điểm sau:

✅ Ưu điểm

  • Thu được lợi nhuận chênh lệch giá thực tế thông qua chênh lệch giá
  • Phù hợp với mô hình lợi nhuận của các nhà tạo lập thị trường truyền thống
  • Cung cấp thanh khoản thị trường thực sự

❌ Thử thách

  • Đối mặt với rủi ro biến động giá thị trường
  • Cần quản lý rủi ro phức tạp hơn
  • Yêu cầu cao hơn về vốn và công nghệ
  • Cơ chế điều chỉnh giá chưa đủ linh hoạt:Cơ chế biến động giá tuyến tính khó có thể thích ứng với môi trường thị trường phức tạp
  • Rủi ro hàng tồn kho nổi bật:Các giao dịch một chiều có thể dễ dàng dẫn đến các vị thế mất cân bằng và rủi ro này đặc biệt đáng kể trong các thị trường có xu hướng.

🔮 Hướng tối ưu hóa trong tương lai

Trước những hạn chế của chiến lược chấp hiện tại, chúng ta có thể tối ưu hóa và cải thiện nó theo những hướng sau trong tương lai:

  1. Chiến lược tạo lập thị trường năng động

    • Điều chỉnh giá thích ứng dựa trên sự biến động của thị trường
    • Điều chỉnh động các chiến lược đặt lệnh đang chờ xử lý dựa trên độ sâu của sổ lệnh
    • Giới thiệu máy học để dự đoán hướng đi của thị trường
  2. Chiến lược quản lý hàng tồn kho

    • Giám sát hàng tồn kho theo thời gian thực và đánh giá rủi ro
    • Cơ chế phòng ngừa rủi ro động và thuật toán cân bằng hàng tồn kho
    • Chiến lược điều chỉnh giá dựa trên tình trạng hàng tồn kho
  3. Chiến lược tạo lập thị trường đa cấp

    • Cung cấp thanh khoản ở nhiều mức giá cùng lúc
    • Phân tán rủi ro tại một điểm và cải thiện tính ổn định tổng thể
    • Gần hơn với hoạt động thực tế của các nhà tạo lập thị trường chuyên nghiệp
  4. Quản lý rủi ro thông minh

    • Giám sát chỉ số rủi ro theo thời gian thực
    • Cơ chế kiểm soát rủi ro và dừng lỗ tự động
    • Xử lý khẩn cấp các tình huống bất thường của thị trường

Mã chiến lược (Đã sửa đổi)

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)