0
tập trung vào
48
Người theo dõi

SuperTrend V.1--Hệ thống đường xu hướng siêu cấp

Được tạo ra trong: 2020-04-20 22:10:36, cập nhật trên: 2024-12-12 21:03:30
comments   28
hits   11392

SuperTrend V.1–Hệ thống đường xu hướng siêu cấp

1. Nguồn gốc của câu chuyện

Người bạn tốt của tôi là Ran đã quan sát chỉ số này trong một thời gian dài và đã giới thiệu nó với tôi trước ngày đầu năm mới để thảo luận xem liệu nó có thể được chuyển đổi thành dạng định lượng hay không. Thật không may, tôi đã mắc chứng trì hoãn và chưa giúp anh ấy thực hiện được mong muốn của mình cho đến tận bây giờ. Trên thực tế, sự hiểu biết của tôi về thuật toán đã có tiến triển lớn gần đây. Tôi dự định một ngày nào đó sẽ viết một chương trình dịch ngôn ngữ thông. Mọi thứ đều có thể là python. . Được rồi, không cần phải nói thêm nữa, chúng tôi xin giới thiệu dòng siêu xu hướng huyền thoại này. .

2. Giới thiệu hệ thống

Hệ thống giao dịch thông minh thế hệ mới của CMC Markets - Supertrend Sau đây là bài viết giới thiệu hệ thống này. SuperTrend V.1–Hệ thống đường xu hướng siêu cấp

Trong hệ thống giao dịch thông minh thế hệ mới tại CMC Markets, hãy chọn “Super Trend Line” trong các chỉ báo kỹ thuật để mở nó. Như thể hiện trong hình, bạn có thể điều chỉnh “màu sắc và độ dày” của tín hiệu tăng và giảm theo sở thích của mình. Vậy chỉ báo siêu xu hướng là gì? Trước khi hiểu công thức chỉ báo siêu xu hướng, cần phải hiểu ATR vì siêu xu hướng sử dụng giá trị ATR để tính toán giá trị chỉ báo.

Ngoài ra còn có một hình ảnh bên dưới để giới thiệu thuật toán chính SuperTrend V.1–Hệ thống đường xu hướng siêu cấp

Nhìn sơ qua, mô tả chính là kênh HL2 (giá trung bình của đường K) nhân với n lần ATR. Tạo ra sự đột phá về xu hướng. Nhưng bài viết khá ngắn gọn. Không có thuật toán chi tiết. Sau đó tôi nghĩ đến nền tảng cộng đồng tốt nhất là Tradingview. Không có gì ngạc nhiên. Quả nhiên là có. SuperTrend V.1–Hệ thống đường xu hướng siêu cấp

Xét theo biểu đồ, điều này khá phù hợp với xu hướng. Nhưng thật không may, đó chỉ là tín hiệu cảnh báo.

3. Nghiên cứu mã nguồn

Mã này trông không quá dài, chúng ta hãy dịch nó và thử xem. ! (っ•̀ω•́)っ✎⁾⁾! SuperTrend V.1–Hệ thống đường xu hướng siêu cấp Mã thông báo đầy đủ như trên. .

4. Chuyển đổi mã

Ở đây chúng tôi tạo ra một chiến lược mới trong FMZ và đặt tên là SuperTrade SuperTrend V.1–Hệ thống đường xu hướng siêu cấp

Tiếp theo, chúng ta thiết lập hai tham số Factor và Pd SuperTrend V.1–Hệ thống đường xu hướng siêu cấp

Để đơn giản hóa hoạt động của mã và giúp dễ hiểu hơn, chúng ta cần sử dụng gói mở rộng dữ liệu nâng cao của Pythonpandas

Trong giờ ăn trưa, tôi hỏi cô Mengmeng xem FMZ có hỗ trợ thư viện này không. Tôi đã kiểm tra vào buổi chiều và nó thực sự hoạt động. Cô giáo Mạnh Mạnh thật tuyệt vời.

1. Chúng ta cần nhập thư viện pandas thư viện thời gian 2. Thiết lập hợp đồng quý trong chức năng chính (chủ yếu là chạy OKEX) 3. Đặt vòng lặp doTicker() để kiểm tra sau mỗi 15 phút. Chạy mã theo chu kỳ 15 phút Tiếp theo chúng ta viết chiến lược chính trong doTicker().

import pandas as pd
import time

def main():
    exchange.SetContractType("quarter")
    preTime = 0
    Log(exchange.GetAccount())
    while True:
        records = exchange.GetRecords(PERIOD_M15)
        if records and records[-2].Time > preTime:
            preTime = records[-2].Time
            doTicker(records[:-1])
        Sleep(1000 *60)
        

4. Chúng ta cần lấy OHCLV của dòng K, vì vậy hãy sử dụng GetRecords() 5. Chúng tôi nhập dữ liệu đã lấy được vào pandas M15 = pd.DataFrame(records) 6. Chúng ta cần sửa đổi thẻ tiêu đề bảng. M15.cột =[‘time’,‘open’,‘high’,‘low’,‘close’,‘volume’,‘OpenInterest’] Trên thực tế, nó chỉ thay đổi các chữ cái đầu tiên của ‘open’, ‘high’, ‘low’ và ‘close’ thành chữ thường để dễ viết mã hơn sau này mà không cần xen kẽ giữa chữ hoa và chữ thường.

def doTicker(records):
    M15 = pd.DataFrame(records)
    M15.columns = ['time','open','high','low','close','volume','OpenInterest']  

7. Thêm một cột hl2 vào tập dữ liệu hl2=(high+low)/2

#HL2
M15['hl2']=(M15['high']+M15['low'])/2

8. Tiếp theo, hãy tính ATR Bởi vì tính toán ATR đòi hỏi phải nhập một chiều dài biến đổi, giá trị của nó là Pd

Sau đó, chúng ta tham khảo hướng dẫn sử dụng ngôn ngữ Mai và các bước thuật toán của ATR true volatility average như sau: TR : MAX(MAX((HIGH-LOW),ABS(REF(CLOSE,1)-HIGH)),ABS(REF(CLOSE,1)-LOW)); ATR : RMA(TR,N)

Giá trị TR là giá trị lớn nhất trong ba giá trị khác biệt sau. 1. Biến động giữa giá cao nhất và giá thấp nhất của ngày giao dịch hiện tại CAO-THẤP 2. Biến động giữa giá đóng cửa của ngày giao dịch trước đó và giá cao nhất của ngày giao dịch hiện tại (REF(CLOSE,1)-HIGH) 3. Biến động giữa giá đóng cửa của ngày giao dịch trước đó và giá thấp nhất của ngày giao dịch hiện tại (REF(CLOSE,1)-LOW) Vì vậy TR : MAX(MAX((HIGH-LOW),ABS(REF(CLOSE,1)-HIGH)),ABS(REF(CLOSE,1)-LOW));

Trong phép tính Python

M15['prev_close']=M15['close'].shift(1)

Đầu tiên, thiết lập prev_close để lấy dữ liệu close ở hàng trước, tức là di chuyển close sang phải 1 lưới để tạo thành tham số mới

ranges= [M15['high'] - M15['low'],M15['high']-M15['prev_close'],M15['low']-M15['prev_close']]

Tiếp theo, định nghĩa một biến trung gian để ghi lại mảng ba giá trị so sánh của TR. (CAO-THẤP)(cao-trước_đóng)(thấp-trước_đóng)

M15['tr'] = pd.DataFrame(ranges).T.abs().max(axis=1)

Chúng tôi định nghĩa một cột mới có tên TR trong tập dữ liệu. Giá trị của TR là giá trị tuyệt đối lớn nhất của biến trung gian. Chúng tôi sử dụng các hàm abs() và max().

    alpha = (1.0 / length) if length > 0 else 0.5
    M15['atr']=M15['tr'].ewm(alpha=alpha, min_periods=length).mean()

Cuối cùng, chúng ta cần tính giá trị của ATR, ATR: RMA (TR, N). Người ta thấy rằng thuật toán RMA thực chất là một biến thể giá trị cố định của thuật toán EMA. N là biến chúng ta đã nhập, trong đó tham số mặc định cho ATR là 14. Ở đây chúng ta nhập alpha = nghịch đảo của chiều dài.

===

Sau đó sử dụng thuật toán EWM để tính toán EMA Quá trình tính toán ATR hoàn chỉnh như sau

    #ATR(PD)
    length=Pd
    M15['prev_close']=M15['close'].shift(1)
    ranges= [M15['high'] - M15['low'],M15['high']-M15['prev_close'],M15['low']-M15['prev_close']]
    M15['tr'] = pd.DataFrame(ranges).T.abs().max(axis=1)
    alpha = (1.0 / length) if length > 0 else 0.5
    M15['atr']=M15['tr'].ewm(alpha=alpha, min_periods=length).mean()

9 Bắt đầu tính Up và Dn

    M15['Up']=M15['hl2']-(Factor*M15['atr'])
    M15['Dn']=M15['hl2']+(Factor*M15['atr'])

Up=hl2 -(Factor * atr) Dn=hl2 +(Factor * atr) Có phải đơn giản không?

Sau đây là đoạn mã cốt lõi của các dòng 15-21 trong TV

TrendUp=close[1]>TrendUp[1]? max(Up,TrendUp[1]) : Up
TrendDown=close[1]<TrendDown[1]? min(Dn,TrendDown[1]) : Dn

Trend = close > TrendDown[1] ? 1: close< TrendUp[1]? -1: nz(Trend[1],1)
Tsl = Trend==1? TrendUp: TrendDown

linecolor = Trend == 1 ? green : red

Mục đích chính của đoạn văn này là để diễn đạt, Nếu trong giai đoạn tăng giá, (đường dưới) TrendUp = max(Up,TrendUp[1]) Nếu đang trong giai đoạn giảm, (dòng trên) TrendDown=min(Dn,TrendDown[1]) Có nghĩa là, trong một xu hướng, giá trị ATR đã sử dụng một kỹ thuật tương tự như chiến lược Bandit Bollinger. Tiếp tục thu hẹp phía bên kia của kênh

Ở đây, mỗi phép tính TrendUp và TrendDown cần phải được tự lặp lại. Nghĩa là mỗi bước phải được tính toán dựa trên bước trước đó. Vì vậy, chúng ta cần lặp qua tập dữ liệu.

Ở đây, trước tiên chúng ta cần tạo các trường mới TrendUp, TrendDown, Trend và linecolor cho tập dữ liệu. Và cung cấp cho họ một giá trị ban đầu Sau đó sử dụng cú pháp fillna(0) để điền dữ liệu với giá trị null vào kết quả đã tính toán trước đó bằng 0

    M15['TrendUp']=0.0
    M15['TrendDown']=0.0
    M15['Trend']=1
    M15['Tsl']=0.0
    M15['linecolor']='Homily'
    M15 = M15.fillna(0)

Bắt đầu một vòng lặp for Sử dụng các phép toán ba ngôi của Python trong các vòng lặp

    for x in range(len(M15)):

Tính toán TrendUp TrendUp = MAX(Up,TrendUp[-1]) if close[-1]>TrendUp[-1] else Up Ý nghĩa chung là nếu giá đóng cửa trước đó > giá TrendUp trước đó, nếu đúng, lấy giá trị Up lớn nhất và giá TrendUp trước đó, nếu không đúng, lấy giá trị Up và truyền cho giá TrendUp hiện tại.

        M15['TrendUp'].values[x] = max(M15['Up'].values[x],M15['TrendUp'].values[x-1]) if (M15['close'].values[x-1]>M15['TrendUp'].values[x-1]) else M15['Up'].values[x]

Tương tự như vậy, hãy tính TrendDown TrendDown=min(Dn,TrendDown[-1]) if close[-1]

        M15['TrendDown'].values[x] = min(M15['Dn'].values[x],M15['TrendDown'].values[x-1]) if (M15['close'].values[x-1]<M15['TrendDown'].values[x-1]) else M15['Dn'].values[x]

Dưới đây là cờ để tính toán hướng điều khiển. Tôi đã đơn giản hóa mã giả Trend= 1 if (close > TrendDown[-1]) else (x) x = -1 if (close< TrendUp[-1]) else Trend[-1]

Nghĩa là nếu giá đóng cửa > TrendDown trước đó thì lấy 1 (tăng giá) nếu không thì lấy x Nếu giá đóng cửa thấp hơn TrendUp trước đó, hãy lấy -1 (bán khống). Nếu không, hãy lấy Trend trước đó (có nghĩa là nó vẫn không thay đổi). Dịch sang ngôn ngữ đồ họa, điều này có nghĩa là phá vỡ đường ray phía trên để chuyển cờ sang xu hướng tăng giá, phá vỡ đường ray phía dưới để chuyển cờ sang xu hướng giảm giá và những lần khác không thay đổi.

        M15['Tsl'].values[x] = M15['TrendUp'].values[x] if  (M15['Trend'].values[x]==1) else M15['TrendDown'].values[x]

Tính toán Tsl và Linecolor Tsl= rendUp if (Trend==1) else TrendDown Tsl được sử dụng để biểu diễn giá trị của SuperTrend trên biểu đồ. Điều này có nghĩa là khi bạn tăng giá, hãy đánh dấu đường dưới cùng trên biểu đồ và khi bạn giảm giá, hãy đánh dấu đường trên cùng trên biểu đồ. linecolor= ‘green’ if (Trend==1) else ‘red’ Ý nghĩa của linecolor là nếu bạn lạc quan, hãy đánh dấu đường màu xanh lá cây, nếu bạn bi quan, hãy đánh dấu màu trống (chủ yếu được sử dụng để hiển thị Tradingview)

        M15['Tsl'].values[x] = M15['TrendUp'].values[x] if  (M15['Trend'].values[x]==1) else M15['TrendDown'].values[x]
        M15['linecolor'].values[x]= 'green' if ( M15['Trend'].values[x]==1) else  'red'

Các dòng 23-30 sau đây chủ yếu dùng để vẽ đồ thị, sẽ không được giải thích chi tiết ở đây.

Cuối cùng, có 2 dòng mã để mua và bán tín hiệu điều khiển Trong Tradingview, điều này có nghĩa là đưa ra tín hiệu sau khi đảo ngược cờ. Chuyển đổi các câu lệnh điều kiện sang Python. Nếu cờ xu hướng trước đó thay đổi từ -1 thành 1, điều đó có nghĩa là mức kháng cự trên đã bị phá vỡ. Mở lệnh mua dài hạn Nếu cờ xu hướng trước đó thay đổi từ 1 thành -1, điều đó có nghĩa là hỗ trợ hướng xuống đã bị phá vỡ. Mở một vị thế bán khống.

    if(M15['Trend'].values[-1] == 1 and M15['Trend'].values[-2] == -1):
        Log('SuperTrend V.1 Alert Long',"Create Order Buy)
    if(M15['Trend'].values[-1] == -1 and M15['Trend'].values[-2] == 1):
        Log('SuperTrend V.1 Alert Long',"Create Order Sell)

Mã đầy đủ cho phần này như sau:

    M15['TrendUp']=0.0
    M15['TrendDown']=0.0
    M15['Trend']=1
    M15['Tsl']=0.0
    M15['linecolor']='Homily'
    M15 = M15.fillna(0)
    
    for x in range(len(M15)):
        M15['TrendUp'].values[x] = max(M15['Up'].values[x],M15['TrendUp'].values[x-1]) if (M15['close'].values[x-1]>M15['TrendUp'].values[x-1]) else M15['Up'].values[x]
        M15['TrendDown'].values[x] = min(M15['Dn'].values[x],M15['TrendDown'].values[x-1]) if (M15['close'].values[x-1]<M15['TrendDown'].values[x-1]) else M15['Dn'].values[x]
        M15['Trend'].values[x] = 1 if (M15['close'].values[x] > M15['TrendDown'].values[x-1]) else ( -1 if (M15['close'].values[x]< M15['TrendUp'].values[x-1])else M15['Trend'].values[x-1] )
        M15['Tsl'].values[x] = M15['TrendUp'].values[x] if  (M15['Trend'].values[x]==1) else M15['TrendDown'].values[x]
        M15['linecolor'].values[x]= 'green' if ( M15['Trend'].values[x]==1) else  'red'
        
    if(M15['Trend'].values[-1] == 1 and M15['Trend'].values[-2] == -1):
        Log('SuperTrend V.1 Alert Long',"Create Order Buy)
        Log('Tsl=',Tsl)
    if(M15['Trend'].values[-1] == -1 and M15['Trend'].values[-2] == 1):
        Log('SuperTrend V.1 Alert Long',"Create Order Sell)
        Log('Tsl=',Tsl)

SuperTrend V.1–Hệ thống đường xu hướng siêu cấp

SuperTrend V.1–Hệ thống đường xu hướng siêu cấp

5. Tất cả các mã

Tôi đã điều chỉnh cấu trúc mã tổng thể. Và kết hợp các lệnh liên quan dài hạn và ngắn hạn vào chiến lược. Đây là mã đầy đủ

'''backtest
start: 2019-05-01 00:00:00
end: 2020-04-21 00:00:00
period: 15m
exchanges: [{"eid":"Futures_OKCoin","currency":"BTC_USD"}]
'''

import pandas as pd
import time

def main():
    exchange.SetContractType("quarter")
    preTime = 0
    Log(exchange.GetAccount())
    while True:
        records = exchange.GetRecords(PERIOD_M15)
        if records and records[-2].Time > preTime:
            preTime = records[-2].Time
            doTicker(records[:-1])
        Sleep(1000 *60)

       
def doTicker(records):
    #Log('onTick',exchange.GetTicker())
    M15 = pd.DataFrame(records)

    #Factor=3
    #Pd=7
    
    M15.columns = ['time','open','high','low','close','volume','OpenInterest']  
    
    #HL2
    M15['hl2']=(M15['high']+M15['low'])/2

    #ATR(PD)
    length=Pd
    M15['prev_close']=M15['close'].shift(1)
    ranges= [M15['high'] - M15['low'],M15['high']-M15['prev_close'],M15['low']-M15['prev_close']]
    M15['tr'] = pd.DataFrame(ranges).T.abs().max(axis=1)
    alpha = (1.0 / length) if length > 0 else 0.5
    M15['atr']=M15['tr'].ewm(alpha=alpha, min_periods=length).mean()


    M15['Up']=M15['hl2']-(Factor*M15['atr'])
    M15['Dn']=M15['hl2']+(Factor*M15['atr'])
    
    M15['TrendUp']=0.0
    M15['TrendDown']=0.0
    M15['Trend']=1
    M15['Tsl']=0.0
    M15['linecolor']='Homily'
    M15 = M15.fillna(0)

    for x in range(len(M15)):
        M15['TrendUp'].values[x] = max(M15['Up'].values[x],M15['TrendUp'].values[x-1]) if (M15['close'].values[x-1]>M15['TrendUp'].values[x-1]) else M15['Up'].values[x]
        M15['TrendDown'].values[x] = min(M15['Dn'].values[x],M15['TrendDown'].values[x-1]) if (M15['close'].values[x-1]<M15['TrendDown'].values[x-1]) else M15['Dn'].values[x]
        M15['Trend'].values[x] = 1 if (M15['close'].values[x] > M15['TrendDown'].values[x-1]) else ( -1 if (M15['close'].values[x]< M15['TrendUp'].values[x-1])else M15['Trend'].values[x-1] )
        M15['Tsl'].values[x] = M15['TrendUp'].values[x] if  (M15['Trend'].values[x]==1) else M15['TrendDown'].values[x]
        M15['linecolor'].values[x]= 'Long' if ( M15['Trend'].values[x]==1) else  'Short'
 

    linecolor=M15['linecolor'].values[-2]
    close=M15['close'].values[-2]
    Tsl=M15['Tsl'].values[-2] 


    if(M15['Trend'].values[-1] == 1 and M15['Trend'].values[-2] == -1):

        Log('SuperTrend V.1 Alert Long','Create Order Buy')
        Log('Tsl=',Tsl)
        position = exchange.GetPosition()
        if len(position) > 0:
            Amount=position[0]["Amount"]
            exchange.SetDirection("closesell")
            exchange.Buy(_C(exchange.GetTicker).Sell*1.01, Amount);
        
        exchange.SetDirection("buy")
        exchange.Buy(_C(exchange.GetTicker).Sell*1.01, vol);

    if(M15['Trend'].values[-1] == -1 and M15['Trend'].values[-2] == 1):
        Log('SuperTrend V.1 Alert Long','Create Order Sell')
        Log('Tsl=',Tsl)
        position = exchange.GetPosition()
        if len(position) > 0:
            Amount=position[0]["Amount"]
            exchange.SetDirection("closebuy")
            exchange.Sell(_C(exchange.GetTicker).Buy*0.99,Amount);
        exchange.SetDirection("sell")
        exchange.Sell(_C(exchange.GetTicker).Buy*0.99, vol*2);

Liên kết chiến lược công khai: https://www.fmz.com/strategy/200625

6. Kiểm tra ngược và tóm tắt

Chúng tôi đã chọn dữ liệu từ năm ngoái để kiểm tra ngược. Sử dụng hợp đồng quý của OKEX với chu kỳ 15 phút. Các tham số được thiết lập là, Factor=3 Pd=45 vol=100 (100 vé cho mỗi đơn hàng) Lợi nhuận hàng năm là khoảng 33%. Nhìn chung, mức thoái lui không lớn lắm. Nguyên nhân chính dẫn đến điều này là sự cố 312 đã ảnh hưởng đáng kể đến hệ thống. Nếu không có 312 thì lợi nhuận sẽ tốt hơn.

SuperTrend V.1–Hệ thống đường xu hướng siêu cấp

6. Suy nghĩ cuối cùng

SuperTrend là một hệ thống giao dịch rất tốt

Nguyên tắc chính của hệ thống SuperTrend là sử dụng chiến lược đột phá kênh ATR (tương tự như kênh Kent) Nhưng thay đổi chính nằm ở việc sử dụng chiến lược thu hẹp Bandit Bollinger hoặc nguyên tắc Donchian ngược lại. Các kênh trên và dưới liên tục thu hẹp trong quá trình hoạt động của thị trường. Để đạt được hoạt động đột phá và chuyển hướng kênh. (Khi kênh bị phá vỡ, thanh ray trên và dưới sẽ trở về giá trị ban đầu)

Tôi đã vẽ đồ thị TrendUp TrendDn riêng biệt trên TradingView Điều này sẽ giúp bạn hiểu rõ hơn về chiến lược này Rõ ràng trong nháy mắt SuperTrend V.1–Hệ thống đường xu hướng siêu cấp

Ngoài ra còn có phiên bản js trên github. Tôi không hiểu rõ về js lắm, nhưng xét theo câu lệnh if thì có vẻ như có vấn đề gì đó. Địa chỉ làhttps://github.com/Dodo33/gekko-supertrend-strategy/blob/master/Supertrend.js

Cuối cùng tôi đã tìm ra được phiên bản gốc. Nó được xuất bản vào ngày 2013.05.29 Được viết bởi Rajandran R Mã C++ được công bố trên diễn đàn Mt4https://www.mql5.com/en/code/viewcode/10851/128437/Non_Repainting_SuperTrend.mq4 Tôi hiểu sơ qua ý nghĩa của C++ và sẽ viết lại khi có cơ hội.

Tôi hy vọng mọi người có thể học được bản chất từ ​​nó. Thật khó. ~!