3
tập trung vào
1444
Người theo dõi

Hệ thống kiểm tra ngược tần suất cao dựa trên từng giao dịch và các khiếm khuyết của kiểm tra ngược K-line

Được tạo ra trong: 2020-06-04 16:48:02, cập nhật trên: 2024-12-10 20:32:01
comments   7
hits   5112

Hệ thống kiểm tra ngược tần suất cao dựa trên từng giao dịch và các khiếm khuyết của kiểm tra ngược K-line

Tôi ở đâyChiến lược phòng ngừa rủi ro đa tiền tệ của Binance short over-rising long overslumpingCùng lúc đó, một công cụ kiểm tra ngược cũng được phát hành. Báo cáo đầu tiên đã xác minh tính hiệu quả của chiến lược dựa trên thử nghiệm ngược dòng K trong một giờ. Tuy nhiên, thời gian ngủ đông thực tế của chiến lược công khai là 1 giây, đây là chiến lược có tần suất rất cao. Rõ ràng là không thể có được kết quả chính xác bằng cách kiểm tra ngược với K-line hàng giờ. Sau đó thêm vàoKiểm tra ngược dòng phútKết quả là, lợi nhuận kiểm thử ngược đã tăng lên rất nhiều, nhưng vẫn không thể xác định được nên sử dụng thông số nào trong tình huống cấp độ thứ hai và việc hiểu toàn bộ chiến lược cũng không thực sự rõ ràng. Lý do chính là nhược điểm quan trọng của phương pháp kiểm tra ngược dựa trên K-line.

Các vấn đề với kiểm tra ngược dòng K

Trước hết, K-line lịch sử là gì? Dữ liệu của đường K bao gồm bốn mức giá: giá mở cửa cao và giá đóng cửa thấp, hai thời điểm bắt đầu và khối lượng giao dịch trong phạm vi. Hầu hết các nền tảng và khuôn khổ định lượng đều dựa trên kiểm thử ngược K-line và nền tảng định lượng FMZ cũng cung cấp kiểm thử ngược ở cấp độ tick. Kiểm thử ngược K-line rất nhanh và hầu hết không có vấn đề gì, nhưng nó cũng có những sai sót rất nghiêm trọng, đặc biệt là khi kiểm thử ngược các chiến lược đa dạng và chiến lược tần suất cao, gần như không thể đưa ra kết luận chính xác.

Đầu tiên là vấn đề thời gian. Thời gian giá cao nhất và thấp nhất của dữ liệu K-line không được đưa ra, vì vậy không cần phải xem xét. Nhưng giá mở cửa và đóng cửa quan trọng nhất không bắt đầu từ giá mở cửa và giờ đóng cửa. Ngay cả đối với các sản phẩm giao dịch ít phổ biến hơn, thường không có giao dịch nào kéo dài hơn mười giây. Khi chúng tôi kiểm tra ngược các chiến lược đa sản phẩm, chúng tôi thường cho rằng giá mở cửa và giá đóng cửa của chúng là đồng thời. Đây cũng là cơ sở để kiểm tra ngược giá đóng cửa.

Hãy tưởng tượng sử dụng đường phút để kiểm tra ngược lại chênh lệch giá của hai loại. Chênh lệch giá của chúng thường là 10 nhân dân tệ. Bây giờ thấy rằng vào lúc 10:01, giá đóng cửa của hợp đồng A là 100 và của hợp đồng B là 112. Chênh lệch giá 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 thời điểm này, chênh lệch giá đã quay trở lại và chiến lược đã kiếm được lợi nhuận hoàn vốn là 2 nhân dân tệ.

Tình hình thực tế có thể là vào lúc 10:00:45, hợp đồng A tạo ra giao dịch 100 nhân dân tệ và sau đó không có giao dịch nào nữa. Vào lúc 10:00:58, hợp đồng B tạo ra giao dịch 112 nhân dân tệ. Vào lúc 10:01, cả hai mức giá đều không tồn tại, giá thị trường tại thời điểm này là bao nhiêu và có thể đạt được mức chênh lệch giá bao nhiêu bằng cách phòng ngừa rủi ro? Không có cách nào để biết được. Một kịch bản có thể xảy ra là: tại thời điểm 10:00:58, giá mua-bán của hợp đồng A là 101,9-102,1 và không có chênh lệch giá 2 nhân dân tệ nào cả. Điều này sẽ làm sai lệch đáng kể chiến lược tối ưu hóa của chúng ta.

Vấn đề thứ hai là sự phù hợp. Sự phù hợp thực sự ưu tiên giá cả và thời gian. Nếu người mua vượt quá giá chào bán, giao dịch thường sẽ được hoàn tất trực tiếp theo giá chào bán. Nếu không, nó sẽ vào sổ lệnh và chờ. Rõ ràng là dữ liệu dòng K không có giá mua và giá bán và không thể mô phỏng việc khớp lệnh ở cấp độ chi tiết.

Cuối cùng, có tác động của chính chiến lược lên thị trường. Nếu đó là một backtest vốn nhỏ, tác động sẽ không đáng kể. Nhưng nếu khối lượng giao dịch chiếm tỷ trọng lớn thì sẽ có tác động tới thị trường. Không chỉ giá sẽ trượt lớn khi giao dịch được thực hiện ngay lập tức mà nếu lệnh mua của bạn được thực hiện thông qua kiểm tra ngược, nó sẽ thực sự ngăn chặn các giao dịch của những nhà giao dịch khác ban đầu muốn mua và hiệu ứng cánh bướm sẽ có tác động đến chợ. Tác động này không thể định lượng được và chúng ta chỉ có thể nói dựa trên kinh nghiệm rằng giao dịch tần suất cao chỉ phù hợp với các khoản tiền nhỏ.

Kiểm tra ngược dựa trên độ sâu và tích tắc thời gian thực

FMZ cung cấp tính năng kiểm tra ngược thời gian thực, có thể thu được dữ liệu lịch sử thực tế về độ sâu 20 cấp độ, dữ liệu tích tắc cấp độ thứ hai theo thời gian thực, dữ liệu từng giao dịch và dựa trên dữ liệu này,Chức năng phát lại thời gian thực. Lượng dữ liệu kiểm thử ngược cực kỳ lớn và tốc độ rất chậm, thường chỉ mất hai ngày. Đối với các chiến lược có tần suất tương đối cao hoặc các chiến lược đòi hỏi phải phán đoán thời gian chặt chẽ thì việc kiểm tra ngược theo thời gian thực là cần thiết. Các cặp giao dịch và khoảng thời gian được FMZ thu thập không dài, nhưng có hơn 70 tỷ dữ liệu lịch sử. Cơ chế khớp lệnh hiện tại là nếu lệnh mua lớn hơn lệnh bán, lệnh đó sẽ được khớp hoàn toàn ngay lập tức bất kể khối lượng; nếu lệnh mua nhỏ hơn lệnh bán, lệnh sẽ được đưa vào hàng đợi khớp lệnh. Cơ chế kiểm tra ngược như vậy giải quyết được hai vấn đề đầu tiên của kiểm tra ngược dòng K, nhưng vẫn không giải quyết được vấn đề cuối cùng. Và vì lượng dữ liệu quá lớn nên tốc độ và phạm vi thời gian kiểm tra ngược bị hạn chế.

Hệ thống kiểm tra ngược tần suất cao dựa trên từng giao dịch và các khiếm khuyết của kiểm tra ngược K-line

Cơ chế kiểm tra ngược dựa trên luồng lệnh giao dịch

Có quá ít thông tin về đường K và độ sâu có thể sai, nhưng có một loại dữ liệu phản ánh ý định giao dịch thực sự của thị trường và phản ánh lịch sử giao dịch chân thực nhất - đó là từng giao dịch một. Bài viết này sẽ đề xuất một hệ thống kiểm tra ngược tần suất cao dựa trên luồng lệnh, giúp giảm đáng kể lượng dữ liệu kiểm tra ngược thời gian thực và mô phỏng tác động của khối lượng giao dịch lên thị trường ở một mức độ nhất định.

Tôi đã tải xuống hồ sơ giao dịch của hợp đồng vĩnh viễn Binance XTZ trong 5 ngày qua (địa chỉ tải xuống: https://www.fmz.com/upload/asset/1ff487b007e1a848ead.csv). Là một sản phẩm không phổ biến lắm, có 213.000 giao dịch trong tổng số. Dữ liệu, trước tiên chúng ta hãy xem xét thành phần của 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à 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 sản phẩm, giá giao dịch, dấu thời gian giao dịch, số lượng giao dịch và liệu đó có phải là giao dịch lệnh bán đang hoạt động hay không. Có người mua và người bán, và 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 lập thị trường và người bán là người mua, dữ liệu cuối cùng là Đúng.

Đầu tiên, dựa trên hướng giao dịch, giá mua và giá bán trên thị trường có thể được suy ra khá chính xác. Nếu là lệnh bán đang hoạt động, giá mua tại thời điểm này là giá giao dịch. Nếu là lệnh mua đang hoạt động, Giá bán là giá giao dịch. Nếu có giao dịch mới, báo giá mới sẽ được cập nhật. Nếu không cập nhật, kết quả trước đó sẽ được giữ nguyên. Có thể dễ dàng suy ra rằng tại thời điểm cuối cùng của dữ liệu trên, giá mua là 2,903 và giá bán là 2,904.

Theo luồng lệnh, việc khớp lệnh có thể được thực hiện như sau: lấy lệnh mua làm ví dụ, giá là giá, số lượng đặt hàng là số tiền, lệnh mua và lệnh bán tương ứng là giá thầu và giá chào bán. Nếu giá thấp hơn giá chào bán và cao hơn giá chào mua, trước tiên nó được xác định là một nhà sản xuất và có thể được khớp lệnh trước. Sau đó, trong thời gian tồn tại của lệnh, tất cả các giao dịch có giá giao dịch thấp hơn hoặc bằng giá sẽ được khớp với lệnh này (nếu giá thấp hơn giá chào bán, lệnh sẽ được khớp với giá chào mua). Nếu giá chào mua bằng hoặc cao hơn giá chào mua, lệnh không thể được giao dịch trước . Tất cả các lệnh có giá giao dịch thấp hơn giá thầu sẽ được khớp với lệnh này. Giá khớp là giá thầu, và khối lượng giao dịch là khối lượng giao dịch của mỗi giao dịch cho đến khi lệnh được thực hiện hoàn toàn hoặc bị hủy. Nếu giá cao hơn giá chào bán thì được coi là lệnh mua. Sau đó, tất cả các giao dịch có giá giao dịch thấp hơn hoặc bằng giá trong thời gian tồn tại của lệnh sẽ được khớp với lệnh này và giá khớp sẽ là giá giao dịch của giao dịch. Sự khác biệt giữa maker và taker là vì các sàn giao dịch về cơ bản khuyến khích đặt lệnh và cung cấp phí giao dịch ưu đãi. Đối với các chiến lược tần suất cao, sự khác biệt này phải được tính đến.

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

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

Mã phù hợp

Đối tượng trao đổi có thể tham khảo phần giới thiệu ở phần đầu, về cơ bản là không thay đổi. Chỉ thêm vào sự khác biệt giữa phí của người tạo và người nhận, tốc độ kiểm tra ngược được tối ưu hóa. Phần sau đây chủ yếu giới thiệu mã phù hợp.

    symbol = 'XTZ'
    loop_time = 0
    intervel = 1000 #策略的休眠时间为1000ms
    init_price = data[0][2] #初始价格
    e = Exchange([symbol],initial_balance=1000000,maker_fee=maker_fee,taker_fee=taker_fee,log='') #初始化交易所
    depth = {'ask':data[0][2], 'bid':data[0][2]} #深度
    order = {'buy':{'price':0,'amount':0,'maker':False,'priority':False,'id':0},
             'sell':{'price':0,'amount':0,'maker':False,'priority':False,'id':0}} #订单
    for tick in data:
        price = int(tick[2]/tick_sizes[symbol])*tick_sizes[symbol] #成交价格
        trade_amount = tick[3] #成交数量
        time_stamp = tick[1] #成交时间戳
        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
        
        #订单网络延时也可以作为撮合条件之一,这里没考虑
        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) #交易逻辑,这里未给出
            loop_time += int((time_stamp - loop_time)/intervel)*intervel

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

  • 1. Khi có giao dịch mới, trước tiên bạn phải khớp lệnh, sau đó mới đặt lệnh dựa trên giá mới nhất.
  • 2. Mỗi lệnh có hai thuộc tính: maker - có phải là maker không, priority - mức độ ưu tiên phù hợp. Lấy lệnh mua làm ví dụ, khi giá mua thấp hơn giá chào bán, lệnh này được đánh dấu là maker, và khi giá mua lớn hơn giá mua, được đánh dấu là lệnh mua. Khớp lệnh ưu tiên, mức độ ưu tiên quyết định giá có bằng giá thầu hay không và người tạo lệnh quyết định phí xử lý.
  • 3. Người tạo lệnh và mức độ ưu tiên của lệnh được cập nhật. Ví dụ, nếu một lệnh mua lớn được đặt vượt quá giá thị trường, khi giá cao hơn giá chào mua xuất hiện, khối lượng giao dịch còn lại sẽ là người tạo lệnh.
  • 4. Khoảng thời gian của chiến lược là cần thiết, có thể thể hiện sự chậm trễ của thị trường.

Backtesting Grid Strategies

Cuối cùng, chúng ta đã đến giai đoạn kiểm tra ngược thực tế. Chúng ta sẽ kiểm tra ngược một trong những chiến lược lưới cổ điển nhất để xem liệu nó có đạt được kết quả mong đợi hay không. Nguyên tắc của chiến lược này là mỗi khi giá tăng 1%, chúng ta sẽ giữ một lệnh bán khống có giá trị nhất định (hoặc ngược lại, giữ một lệnh mua), tính toán các lệnh mua và bán rồi đặt lệnh trước. Mã không được phát hành. Đóng gói tất cả mã vàoGrid('XTZ',100,0.3,1000,maker_fee=-0.00002,taker_fee=0.0003)Trong hàm, các tham số là: cặp giao dịch, độ lệch giá 1% giá trị nắm giữ, mật độ lệnh 0,3%, khoảng thời gian ngủ tính bằng ms, phí tạo lệnh và phí tiếp nhận lệnh.

Trong năm ngày qua, thị trường XTZ đang trong giai đoạn biến động, rất phù hợp với lưới điện. /tải lên/tài sản/1e235fa08ed9dce82a3.png

Đầu tiên, chúng tôi kiểm tra ngược tác động của các quy mô vị thế khác nhau lên lợi nhuận. Lợi nhuận được đo bằng cơ chế kiểm tra ngược truyền thống chắc chắn sẽ tăng theo tỷ lệ với sự gia tăng của các vị thế.

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 có bốn nhóm được kiểm tra ngược, với các giá trị giữ lần lượt là 100, 1000, 10000 và 100000 và tổng thời gian kiểm tra ngược là 1,3 giây. Kết quả như sau:

{'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% giá trị vị thế. Điều này cũng phù hợp với tình hình thực tế. Giá trị của vị thế càng lớn, giá trị của lệnh chờ càng lớn, khả năng xảy ra giao dịch một phần càng cao và lợi nhuận thực tế cuối cùng sẽ nhỏ hơn so với khối lượng lệnh đang chờ xử lý. Hình dưới đây so sánh lợi nhuận tương đối của các khoản nắm giữ có giá trị lần lượt là 100 và 10.000: Hệ thống kiểm tra ngược tần suất cao dựa trên từng giao dịch và các khiếm khuyết của kiểm tra ngược K-line

Chúng tôi cũng có thể kiểm tra ngược tác động của các tham số khác nhau lên lợi nhuận kiểm tra ngược, chẳng hạn như mật độ lệnh, thời gian không hoạt động, phí xử lý, v.v. Lấy thời gian ngủ làm ví dụ, hãy thay đổi thành 100ms và so sánh với thời gian ngủ là 1000ms để thấy được lợi ích. Kết quả kiểm tra ngược 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 nhẹ. Điều này là do chiến lược chỉ đặt một bộ lệnh. Một số lệnh không thể hưởng lợi từ giá biến động vì chúng không thể thay đổi kịp thời. Việc giảm thời gian ngủ đông đã cải thiện vấn đề này. Điều này cũng minh họa tầm quan trọng của việc đặt nhiều nhóm lệnh trong chiến lược lưới.

Tóm tắt

Bài báo này đề xuất một cách sáng tạo một hệ thống kiểm tra ngược mới dựa trên luồng lệnh, có thể mô phỏng một phần các điều kiện khớp lệnh đang chờ xử lý, lệnh đang nhận, giao dịch một phần, sự chậm trễ, v.v. và phản ánh một phần tác động của quỹ chiến lược lên lợi nhuận. Nó có tài liệu tham khảo quan trọng giá trị cho các chiến lược phòng ngừa rủi ro và kiểm tra ngược có độ chính xác cao chỉ ra hướng để tối ưu hóa các tham số chiến lược. Điều này cũng đã được xác minh thông qua giao dịch thực tế dài hạn. Nó cũng kiểm soát tốt hơn lượng dữ liệu cần thiết cho việc kiểm tra ngược và tốc độ kiểm tra ngược cũng rất nhanh.