Tài nguyên đang được tải lên... tải...

Hệ thống backtesting tần số cao dựa trên giao dịch từng giao dịch và các khiếm khuyết của backtesting đường K

Tác giả:FMZ~Lydia, Tạo: 2022-11-30 12:38:50, Cập nhật: 2023-09-11 20:01:01

img

Hệ thống backtesting tần số cao dựa trên giao dịch từng giao dịch và các khiếm khuyết của backtesting đường K

Tôi đã phát hành một công cụ backtesting trong bài viết Nghiên cứu về Chiến lược phòng hộ đa tiền tệ của Binance Futures (https://www.fmz.com/digest-topic/5584) Và báo cáo đầu tiên dựa trên kiểm tra ngược K-line một giờ, xác minh hiệu quả của chiến lược. Tuy nhiên, thực tế, thời gian ngủ của chiến lược công cộng là 1s, đó là một chiến lược tần suất khá cao.https://www.fmz.com/digest-topic/5621Kết quả là, lợi nhuận của backtesting đã được cải thiện rất nhiều, nhưng vẫn không thể xác định các tham số nào nên được sử dụng trong trường hợp cấp độ thứ hai, và sự hiểu biết về toàn bộ chiến lược không rõ ràng.

Các vấn đề dựa trên K-line backtesting

Đầu tiên, K-line lịch sử là gì? Một dữ liệu K-line bao gồm bốn giá: giá cao nhất, giá mở cửa, giá thấp nhất và giá đóng cửa, thời gian bắt đầu, thời gian kết thúc và số lượng giao dịch khoảng thời gian. Hầu hết các nền tảng và khung định lượng được kiểm tra lại dựa trên K-line, và FMZ Quant Platform cũng cung cấp kiểm tra lại cấp độ Tick. Tốc độ kiểm tra lại K-line rất nhanh, và trong hầu hết các trường hợp không có vấn đề, nhưng cũng có những khiếm khuyết rất nghiêm trọng, đặc biệt là chiến lược đa dạng và chiến lược tần số cao của kiểm tra lại, khó có thể đưa ra kết luận chính xác.

Trước hết, đó là vấn đề thời gian. Thời gian của giá cao nhất và thấp nhất của dữ liệu đường K không được đưa ra, vì vậy không cần thiết phải xem xét, nhưng giá mở và đóng quan trọng nhất không phải là thời gian mở và đóng vị trí. Ngay cả khi các loại giao dịch không phổ biến, chúng thường không được giao dịch trong hơn mười giây. Khi chúng ta kiểm tra lại nhiều loại chiến lược, chúng ta thường mặc định rằng giá mở và đóng của chúng giống nhau, đây cũng là cơ sở của kiểm tra lại giá đóng.

Hãy tưởng tượng sử dụng đường phút để kiểm tra lại sự điều chỉnh của hai loại. Sự khác biệt giữa chúng thường là 10 nhân dân tệ. Bây giờ nó được tìm thấy rằng lúc 10:01, giá đóng hợp đồng A là 100 nhân dân tệ, giá đóng hợp đồng B là 112 nhân dân tệ, và sự khác biệt là 12 nhân dân tệ. Vì vậy, chiến lược bắt đầu phòng ngừa rủi ro. Vào một thời điểm nhất định, sự khác biệt trở lại, và chiến lược kiếm được 2 nhân dân tệ lợi nhuận trở lại.

Tuy nhiên, tình huống thực tế có thể xảy ra vào lúc 10:00:45, hợp đồng A tạo ra một giao dịch 100 nhân dân tệ, và sau đó không có giao dịch. Hợp đồng B tạo ra một giao dịch 112 nhân dân tệ vào lúc 10:00:58. Vào lúc 10:01, cả hai giá không tồn tại. Giá mở cửa vào thời điểm này là gì? Và sự khác biệt có thể có được bao nhiêu? Chúng tôi không biết. Một tình huống có thể xảy ra là vào lúc 10:00:58, xu hướng mua một và bán một hợp đồng A là 101.9-102.1, và không có chênh lệch 2 nhân dân tệ, điều này sẽ gây nhầm lẫn cho việc tối ưu hóa chiến lược của chúng tôi.

Thứ hai là kết hợp. Kết hợp thực sự là giá và thời gian đầu tiên. Nếu người mua vượt quá giá bán một, anh / cô ấy thường sẽ kết thúc giao dịch ở mức giá bán một, nếu không, anh / cô ấy sẽ nhập sổ đơn đặt hàng và chờ đợi.

Cuối cùng là tác động của giao dịch của chính chiến lược trên thị trường. Nếu đó là một thử nghiệm ngược quỹ nhỏ, tác động sẽ nhỏ. Tuy nhiên, nếu số lượng giao dịch chiếm một tỷ lệ lớn, nó sẽ có tác động đến thị trường. Không chỉ điểm trượt giá sẽ lớn khi giao dịch được hoàn thành ngay lập tức, mà nếu lệnh mua của bạn được hoàn thành trong thử nghiệm ngược, nó thực sự ngăn chặn giao dịch của các nhà giao dịch ban đầu khác muốn mua, điều này sẽ có tác động hiệu ứng bướm trên thị trường. Tuy nhiên, tác động này không thể được định lượng, và chỉ có thể nói bằng kinh nghiệm rằng giao dịch tần số cao chỉ có thể chứa các quỹ nhỏ.

Kiểm tra ngược dựa trên độ sâu và dấu hiệu thời gian thực

FMZ cung cấp các bot thực cấp backtesting, có thể có được thực sự lịch sử 20-mức độ sâu, thời gian thực thứ hai đánh dấu, giao dịch bằng giao dịch và các dữ liệu khác, và dựa trên điều này nó đã thực hiện thực bot chức năng phát lại (https://www.fmz.com/m/databasePhương pháp kiểm tra ngược hiện tại là nếu lệnh mua lớn hơn lệnh bán, nó sẽ được khớp hoàn toàn ngay lập tức mà không cần nhìn vào số lượng, và nếu lệnh mua nhỏ hơn lệnh bán, nó sẽ đi vào hàng đợi khớp. Cơ chế kiểm tra ngược này giải quyết hai vấn đề đầu tiên của kiểm tra ngược đường K-line, nhưng nó vẫn không thể giải quyết vấn đề cuối cùng. Và vì số lượng dữ liệu quá lớn, tốc độ và thời gian kiểm tra lại bị giới hạn.

img img

Cơ chế kiểm tra ngược dựa trên luồng đơn đặt hàng mỗi giao dịch

Có quá ít thông tin về K-Line, và độ sâu cũng có thể là sai. Tuy nhiên, một loại dữ liệu là ý định giao dịch thực sự của thị trường, phản ánh lịch sử giao dịch thực tế nhất - đó là giao dịch theo giao dịch. Trong bài báo này, tôi sẽ đề xuất một hệ thống backtesting tần số cao dựa trên luồng lệnh, sẽ làm giảm đáng kể số lượng dữ liệu trong backtesting ở mức bot thực tế, và ở một mức độ nhất định, mô phỏng tác động của khối lượng giao dịch trên thị trường.

Tôi đã tải về giao dịch từng giao dịch trong 5 ngày qua Binance XTZ hợp đồng vĩnh cửu (địa chỉ tải về:https://www.fmz.com/upload/asset/1ff487b007e1a848ead.csvn như một loại ít phổ biến hơn, có 213.000 dữ liệu.

[['XTZ', 1590981301905, 2.905, 0.4, 'False\n'],
 ['XTZ', 1590981303044, 2.903, 3.6, 'True\n'],
 ['XTZ', 1590981303309, 2.903, 3.7, 'True\n'],
 ['XTZ', 1590981303738, 2.903, 238.1, 'True\n'],
 ['XTZ', 1590981303892, 2.904, 0.1, 'False\n'],
 ['XTZ', 1590981305250, 2.904, 0.1, 'False\n'],
 ['XTZ', 1590981305643, 2.903, 197.3, 'True\n'],

Dữ liệu là một danh sách hai chiều, được sắp xếp theo thời gian giao dịch. Ý nghĩa cụ thể là: tên loài, giá giao dịch, dấu thời gian giao dịch, số lượng giao dịch và liệu lệnh bán có được thực hiện tích cực hay không. Có cả mua và bán. Mỗi giao dịch bao gồm người mua và người bán. Nếu người mua là người tạo thị trường và người bán là người nhận giao dịch tích cực, dữ liệu cuối cùng sẽ là True.

Trước hết, theo hướng giao dịch, chúng ta có thể suy đoán mua một và bán một trên thị trường chính xác. Nếu đó là một lệnh bán tích cực, giá mua một tại thời điểm này là giá giao dịch. Nếu đó là một lệnh mua tích cực, giá bán một là giá giao dịch. Nếu có một giao dịch mới, chúng ta sẽ cập nhật vị trí mở mới. Nếu không được cập nhật, kết quả cuối cùng sẽ được giữ lại. Thật dễ dàng để khởi động thời điểm cuối cùng của dữ liệu trên. Giá mua một là 2.903 và giá bán một là 2.904.

Theo luồng lệnh, nó có thể được khớp theo cách này: lấy một lệnh mua làm ví dụ, giá là giá, và số lượng lệnh là số lượng. Tại thời điểm này, mua một và bán một trong các vị trí mở được đặt giá và yêu cầu tương ứng. Nếu giá thấp hơn yêu cầu và cao hơn giá thầu, nó sẽ được đánh giá là người tạo đầu tiên, và ưu tiên có thể được đưa ra cho kết hợp. Sau đó tất cả các giao dịch có giá giao dịch thấp hơn hoặc bằng giá trong suốt thời gian hoạt động của lệnh sẽ được khớp với lệnh này (nếu giá thấp hơn hoặc bằng giá thầu, không thể ưu tiên giao dịch, và các lệnh có giá giao dịch thấp hơn giá sẽ được khớp với lệnh này). Giá khớp là giá, và số lượng giao dịch là số lượng giao dịch theo giao dịch, cho đến khi lệnh hoàn toàn đóng hoặc hủy bỏ. Nếu giá chênh lệch cao hơn, nó sẽ được đánh giá là người nhận. Đối với các chiến lược giao dịch này, tất cả các đơn đặt hàng sẽ được khuyến khích khớp với giá cao hơn hoặc không khớp với giá giao dịch.

Nếu lệnh là người nhận, tình hình thực tế là giao dịch có thể được thực hiện ngay lập tức, thay vì chờ một lệnh mới phù hợp với nó. Trước hết, chúng tôi không xem xét số lượng lệnh được liệt kê trên thị trường. Ngay cả khi có dữ liệu, phán quyết trực tiếp của giao dịch đã thay đổi chiều sâu và ảnh hưởng đến thị trường. Việc kết hợp dựa trên các lệnh mới tương đương với việc thay thế các đơn đặt hàng của bạn bằng các đơn đặt hàng thực trong lịch sử, trong trường hợp nào đó sẽ không vượt quá giới hạn số lượng giao dịch của chính thị trường, và lợi nhuận cuối cùng không thể vượt quá lợi nhuận tối đa được tạo ra bởi thị trường. Một số cơ chế kết hợp cũng ảnh hưởng đến số lượng giao dịch của các đơn đặt hàng, do đó ảnh hưởng đến lợi nhuận của chiến lược, phản ánh định lượng chiến lược. Sẽ không có kiểm tra lại truyền thống, nơi số lượng giao dịch tăng gấp đôi nếu quỹ được tăng gấp đôi.

Có một số chi tiết nhỏ. Nếu giá mua của một lệnh bằng với giá mua một, vẫn có một xác suất nhất định rằng lệnh sẽ khớp với giá mua một. Ưu tiên của lệnh và xác suất giao dịch cần được xem xét, phức tạp hơn, và nó sẽ không được xem xét ở đây.

Mã kết hợp

Các đối tượng trao đổi có thể đề cập đến việc giới thiệu ngay từ đầu, về cơ bản không thay đổi. Chỉ có sự khác biệt giữa hoa hồng người tạo và người nhận được thêm vào, và tốc độ kiểm tra lại được tối ưu hóa. Mã kết hợp chủ yếu được giới thiệu dưới đây.

    symbol = 'XTZ'
    loop_time = 0
    intervel = 1000 #The sleep time of the strategy is 1000ms
    init_price = data[0][2] #Initial price
    e = Exchange([symbol],initial_balance=1000000,maker_fee=maker_fee,taker_fee=taker_fee,log='') #Initialize the exchange
    depth = {'ask':data[0][2], 'bid':data[0][2]} #depth
    order = {'buy':{'price':0,'amount':0,'maker':False,'priority':False,'id':0},
             'sell':{'price':0,'amount':0,'maker':False,'priority':False,'id':0}} #Order
    for tick in data:
        price = int(tick[2]/tick_sizes[symbol])*tick_sizes[symbol] #Transaction price
        trade_amount = tick[3] #Number of transactions
        time_stamp = tick[1] #Transaction timestamp
        if tick[4] == 'False\n':
            depth['ask'] = price
        else:
            depth['bid'] = price
        
        if depth['bid'] < order['buy']['price']:
            order['buy']['priority'] = True
        if depth['ask'] > order['sell']['price']:
            order['sell']['priority'] = True
        if price > order['buy']['price']:
            order['buy']['maker'] = True
        if price < order['sell']['price']:
            order['sell']['maker'] = True
        
        #Order network delay can also be used as one of the matching conditions, which is not considered here
        cond1 = order['buy']['priority'] and order['buy']['price'] >= price and order['buy']['amount'] > 0
        cond2 = not order['buy']['priority'] and order['buy']['price'] > price and order['buy']['amount'] > 0
        cond3 = order['sell']['priority'] and order['sell']['price'] <= price and order['sell']['amount'] > 0
        cond4 = not order['sell']['priority'] and order['sell']['price'] < price and order['sell']['amount'] > 0

        if cond1 or cond2:
            buy_price = order['buy']['price'] if order['buy']['maker'] else price
            e.Buy(symbol, buy_price, min(order['buy']['amount'],trade_amount), order['buy']['id'], order['buy']['maker'])
            order['buy']['amount'] -= min(order['buy']['amount'],trade_amount)
            e.Update(time_stamp,[symbol],{symbol:price})
        if cond3 or cond4:
            sell_price = order['sell']['price'] if order['sell']['maker'] else price
            e.Sell(symbol, sell_price, min(order['sell']['amount'],trade_amount), order['sell']['id'], order['sell']['maker'])
            order['sell']['amount'] -= min(order['sell']['amount'],trade_amount)
            e.Update(time_stamp,[symbol],{symbol:price})

        if time_stamp - loop_time > intervel:
            order = get_order(e,depth,order) #Trading logic, not given here
            loop_time += int((time_stamp - loop_time)/intervel)*intervel

Một số chi tiết cần được lưu ý:

-1. Khi có một giao dịch mới, chúng ta nên phù hợp với lệnh đầu tiên, và sau đó đặt lệnh theo giá mới nhất. -2. Mỗi đơn đặt hàng có hai thuộc tính: người tạo cho dù nó là người tạo, và ưu tiên ưu tiên kết hợp. Lấy đơn đặt hàng mua như một ví dụ, khi giá mua thấp hơn giá bán một, nó được đánh dấu là người tạo, và khi giá mua lớn hơn giá mua một, nó được đánh dấu là kết hợp ưu tiên. Ưu tiên quyết định liệu có phù hợp nếu giá bằng giá mua, và người tạo xác định hoa hồng. -3. Người tạo và ưu tiên của lệnh được cập nhật. Ví dụ, có một lệnh mua lớn vượt quá các vị trí mở, khi có giá lớn hơn giá mua, tại thời điểm này, số lượng giao dịch còn lại sẽ là người tạo. -4. khoảng thời gian của chiến lược là cần thiết, có thể đại diện cho sự chậm trễ của thị trường.

Kiểm tra lại các chiến lược lưới điện

Cuối cùng, chúng ta đạt đến giai đoạn kiểm tra ngược thực tế. Ở đây, chúng ta sẽ kiểm tra lại một chiến lược lưới cổ điển nhất để xem liệu nó có đạt được hiệu ứng mong đợi hay không. Nguyên tắc chiến lược là mỗi khi giá tăng 1%, chúng ta sẽ giữ một giá trị nhất định của lệnh vị trí ngắn (nếu không, chúng ta sẽ giữ lệnh vị trí dài), và chúng ta sẽ tính toán lệnh mua và bán và chờ đợi chúng trước. Mã sẽ không được phát hành.Grid ('XTZ ', 100,0.31000, maker_fee=-0.00002, taker_fee=0.0003)Các thông số là: cặp giao dịch, giá trị giữ với độ lệch giá 1%, mật độ lệnh 0,3%, khoảng thời gian ngủ của ms, ủy ban lệnh đang chờ và ủy ban người nhận.

Thị trường XTZ đã bị sốc trong 5 ngày qua, rất phù hợp với chiến lược lưới điện.

img

Chúng ta sẽ kiểm tra tác động của các vị trí khác nhau đối với lợi nhuận đầu tiên.

e1 = Grid('XTZ',100,0.3,1000,maker_fee=-0.00002,taker_fee=0.0003)
print(e1.account['USDT'])
e2 = Grid('XTZ',1000,0.3,1000,maker_fee=-0.00002,taker_fee=0.0003)
print(e2.account['USDT'])
e3 = Grid('XTZ',10000,0.3,1000,maker_fee=-0.00002,taker_fee=0.0003)
print(e3.account['USDT'])
e4 = Grid('XTZ',100000,0.3,1000,maker_fee=-0.00002,taker_fee=0.0003)
print(e4.account['USDT'])

Tổng cộng bốn nhóm đã được kiểm tra lại với các giá trị vị trí 100, 1000, 10000 và 100000, và tổng thời gian kiểm tra lại là 1,3 giây.

{'realised_profit': 28.470993031132966, 'margin': 0.7982662957624465, 'unrealised_profit': 0.0104554474048441, 'total': 10000028.481448, 'leverage': 0.0, 'fee': -0.3430967859046398, 'maker_fee': -0.36980249726699727, 'taker_fee': 0.026705711362357405}
{'realised_profit': 275.63148945320177, 'margin': 14.346335829979132, 'unrealised_profit': 4.4382117331794045e-14, 'total': 10000275.631489, 'leverage': 0.0, 'fee': -3.3102045933457784, 'maker_fee': -3.5800688964477048, 'taker_fee': 0.2698643031019274}
{'realised_profit': 2693.8701498889504, 'margin': 67.70120400534114, 'unrealised_profit': 0.5735269329348516, 'total': 10002694.443677, 'leverage': 0.0001, 'fee': -33.984021415250744, 'maker_fee': -34.879233866850974, 'taker_fee': 0.8952124516001403}
{'realised_profit': 22610.231198585603, 'margin': 983.3853688758861, 'unrealised_profit': -20.529965947304365, 'total': 10022589.701233, 'leverage': 0.002, 'fee': -200.87094000385412, 'maker_fee': -261.5849078470078, 'taker_fee': 60.71396784315319}

Có thể thấy rằng lợi nhuận thực hiện cuối cùng lần lượt là 28,4%, 27,5%, 26,9% và 22,6% của giá trị vị trí. Điều này cũng phù hợp với tình hình thực tế. Giá trị của vị trí càng lớn, giá trị của lệnh càng lớn và các giao dịch một phần càng có khả năng xảy ra. Lợi nhuận thực hiện cuối cùng sẽ nhỏ hơn so với số tiền đặt hàng. Hình dưới đây cho thấy so sánh lợi nhuận tương đối với giá trị vị trí lần lượt là 100 và 10000:

img

Chúng ta cũng có thể kiểm tra lại tác động của các tham số khác nhau đối với kết quả kiểm tra lại, chẳng hạn như mật độ đơn đặt hàng đang chờ, thời gian ngủ và hoa hồng. Lấy thời gian ngủ làm ví dụ, thay đổi nó thành 100ms, so sánh với thời gian ngủ 1000ms và quan sát kết quả. Kết quả kiểm tra lại như sau:

{'realised_profit': 29.079440803790423, 'margin': 0.7982662957624695, 'unrealised_profit': 0.0104554474048441, 'total': 10000029.089896, 'leverage': 0.0, 'fee': -0.3703702128662524, 'maker_fee': -0.37938946377435134, 'taker_fee': 0.009019250908098965}

Lợi nhuận đã tăng lên một chút. Điều này là do chỉ có một nhóm đơn đặt hàng đang chờ cho chiến lược, và một số đơn đặt hàng không thể nhận được giá dao động vì họ không có thời gian để thay đổi. Thời gian ngủ giảm cải thiện vấn đề này. Điều này cũng cho thấy tầm quan trọng của các đơn đặt hàng đa nhóm đang chờ trong chiến lược lưới điện.

Tóm lại

Bài báo này đề xuất một hệ thống backtesting mới dựa trên dòng lệnh sáng tạo, có thể mô phỏng một phần tình huống khớp như lệnh đang chờ, nhận lệnh, giao dịch một phần và trì hoãn, một phần phản ánh tác động của khối lượng quỹ chiến lược đối với lợi nhuận, và nó có giá trị tham chiếu quan trọng cho các chiến lược tần số cao và các chiến lược phòng ngừa rủi ro.


Có liên quan

Thêm nữa