Ông Ran, người bạn tốt của tôi, đã quan sát chỉ số này trong một thời gian dài và đề nghị nó cho tôi trước ngày đầu năm mới để thảo luận liệu nó có thể được chuyển thành định lượng hay không. Thật là đáng tiếc khi người trì hoãn đã trì hoãn đến bây giờ để giúp anh ấy thực hiện một mong muốn như vậy. Người ta ước tính rằng một ngày nào đó tôi sẽ viết một phiên dịch cho ngôn ngữ Pine. Mọi thứ đều có thể là Python. Vâng, không có nhiều chuyện vớ vẩn, hãy giới thiệu dòng siêu xu hướng huyền thoại.
Trong thế hệ mới của hệ thống giao dịch thông minh trong CMC Markets, chúng ta có thể chọn
Hãy xem một chút. Nó chủ yếu mô tả kênh nơi HL2 (giá trung bình k-line) cộng với n lần ATR. Nhưng bài viết rất đơn giản. Không có thuật toán chi tiết. Quả thật, nó thực sự ở đó.
Nhìn vào biểu đồ, nó phù hợp với xu hướng.
Mã không quá dài, nên hãy thử dịch nó.!(っ•̀ω•́)っ
Mã pin hoàn chỉnh là như trên.
Ở đây chúng ta tạo ra một chiến lược mới trên FMZ, đặt tên nó là SuperTrend
Tiếp theo, chúng ta sẽ thiết lập hai tham số, Factor và Pd
Để đơn giản hóa tốt hơn các hoạt động mã và tạo điều kiện dễ hiểu, chúng ta cần sử dụng python
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):
M15 = pd.DataFrame(records)
M15.columns = ['time','open','high','low','close','volume','OpenInterest']
#HL2
M15['hl2']=(M15['high']+M15['low'])/2
Sau đó, chúng ta tham khảo hướng dẫn của MyLanguage, và các bước thuật toán của giá trị trung bình của kích thước biến động thực ATR là 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à tối đa của ba sự khác biệt sau:
Trong tính toán Python
M15['prev_close']=M15['close'].shift(1)
Chúng ta cần thiết lập một prev_close để lấy dữ liệu của đóng trong dòng trước đó, đó là, di chuyển gần bên phải bởi một lưới để hình thành một tham số mới
ranges= [M15['high'] - M15['low'],M15['high']-M15['prev_close'],M15['low']-M15['prev_close']]
Tiếp theo, chúng ta xác định một biến trung gian ghi lại một mảng 3 giá trị tương phản cho TR. (HIGH-LOW) (high-prev_close) (low-prev_close)
M15['tr'] = pd.DataFrame(ranges).T.abs().max(axis=1)
Chúng tôi xác định một cột mới trong bộ dữ liệu và đặt tên nó là TR. Giá trị của TR là giá trị tuyệt đối lớn nhất của biến trung gian, 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 toán giá trị của ATR, ATR: RMA (TR, N). N là biến mà chúng ta nhập. tham số mặc định của ATR là 14.
===
Sau đó thuật toán ewm được sử dụng để tính toán ema Quá trình tính toán ATR hoàn chỉnh là 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) Không đơn giản sao?
Đây là phần mã chính của dòng 15-21 từ 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
Điểm chính của đoạn này là thể hiện rằng, Nếu nó ở giai đoạn tăng, (dòng dưới) TrendUp=max (Up, TrendUp [1]) Nếu nó ở giai đoạn giảm, (dòng trên) TrendDown=min (Dn, TrendDown [1]) Điều đó có nghĩa là trong một xu hướng, giá trị ATR đã sử dụng một công nghệ tương tự như chiến lược Bandit Bollinger. Hãy tiếp tục thu hẹp bên kia kênh.
Ở đây, mỗi tính toán của TrendUp và TrendDown đòi hỏi tự lặp. Đó là, mỗi bước nên được tính theo bước trước đó. Do đó, bộ dữ liệu nên được lặp lại trong vòng lặp.
Đầu tiên, chúng ta tạo các trường mới TrendUp, TrendDown, Trend, linecolor cho bộ dữ liệu. Sau đó chúng ta sử dụng fillna ngữ pháp (0) để điền dữ liệu với giá trị không trong kết quả được tính toán trước đó với 0
M15['TrendUp']=0.0
M15['TrendDown']=0.0
M15['Trend']=1
M15['Tsl']=0.0
M15['linecolor']='Homily'
M15 = M15.fillna(0)
Cho phép vòng lặp for Sử dụng Python hoạt động ba trong vòng lặp
for x in range(len(M15)):
Tính toán TrendUp TrendUp = MAX(Up,TrendUp[-1]) nếu gần[-1]>TrendUp[-1] nếu không Up Nó gần như có nghĩa là nếu trước đây đóng>TrendUp trước đó là đúng, giá trị tối đa giữa Up và TrendUp trước đó sẽ được lấy; nếu không, giá trị Up sẽ được lấy và chuyển sang 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ự, tính toán TrendDown TrendDown=min(Dn,TrendDown[-1]) nếu gần[-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]
Sau đây là biểu tượng để tính toán hướng điều khiển. Tôi đơn giản hóa mã giả Xu hướng = 1 nếu (kết thúc > Xu hướngDown[-1]) khác (x) x = -1 nếu (close< TrendUp[-1]) khác Trend[-1]
Điều này có nghĩa là nếu giá đóng> xu hướng trước đó, lấy giá trị của 1 (bullish). Nếu giá đóng cửa thấp hơn so với TrendUp trước đó, lấy giá trị -1 (giảm). Nếu không, lấy xu hướng trước (có nghĩa là không thay đổi) Để dịch thành ngôn ngữ hình ảnh là một sự đột phá của cờ chuyển đổi đường trên cho tăng; và một sự đột phá của cờ chuyển đổi đường dưới cho giảm.
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 nếu (Trend==1) khác TrendDown
Tsl là giá trị được sử dụng để đại diện cho SuperTrend trên hình ảnh. Nó có nghĩa là để đánh dấu theo dõi xuống trên hình ảnh khi chúng ta đang trong tăng, và đánh dấu theo dõi trên hình ảnh khi chúng ta đang trong giảm.
linecolor=
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'
23-30 dòng mã tiếp theo chủ yếu là các bản vẽ phác thảo, không được giải thích ở đây.
Cuối cùng, có 2 dòng mã để điều khiển tín hiệu mua và bán. Trong Tradeview, nó có nghĩa là tín hiệu được đưa ra sau khi đảo ngược cờ Chuyển câu lệnh có điều kiện thành python. Nếu dấu hiệu xu hướng cuối cùng thay đổi từ -1 thành 1, điều đó có nghĩa là ngưỡng kháng cự trên đã được vượt quá và mở vị trí mua. Nếu dấu hiệu xu hướng cuối cùng thay đổi từ 1 sang -1, điều đó có nghĩa là hỗ trợ giảm đã được vượt quá và mở vị trí mua.
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 đủ là 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)
Tôi đã điều chỉnh cấu trúc mã tổng thể. Và tôi hợp nhất các hướng dẫn lệnh liên quan đến đi dài và đi ngắ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);
Địa chỉ chiến lược công cộng:https://www.fmz.com/strategy/200625
Chúng tôi đã chọn dữ liệu của năm ngoái để kiểm tra lại. Chúng tôi sử dụng hợp đồng hàng quý OKEX trong một khoảng thời gian 15 phút. Các thông số được thiết lập là: Nhân tố = 3 Pd=45 Vol=100 (100 hợp đồng cho mỗi đơn đặt hàng) Lợi nhuận hàng năm là khoảng 33%. Nói chung, việc rút tiền không quá nhiều, Sự giảm mạnh của 312 có tác động tương đối lớn đến hệ thống, Nếu không có 312, thì lợi nhuận sẽ tốt hơn.
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à áp dụng chiến lược đột phá kênh ATR (tương tự như kênh Kent) Tuy nhiên, sự thay đổi của nó chủ yếu là do sử dụng chiến lược thu hẹp của Bandit Bollinger, hoặc ngược lại của nguyên tắc Donchian. Trong hoạt động thị trường, các kênh trên và dưới liên tục bị thu hẹp. Để đạt được hoạt động điều khiển xuyên kênh. (Một khi kênh vượt qua, các đường ray trên và dưới sẽ trở lại giá trị ban đầu)
Tôi vẽ lên, dn, TrendUp và TrendDn riêng biệt trên TradeView, Điều này làm cho nó dễ dàng hơn để hiểu rõ hơn chiến lược. Nhìn một cái nhìn rõ ràng:
Ngoài ra, có một phiên bản của js trên github. Tôi không giỏi js, nhưng có vẻ như có một cái gì đó sai với câu lệnh if. Địa chỉ:https://github.com/Dodo33/gekko-supertrend-strategy/blob/master/Supertrend.js
Cuối cùng, tôi đã tìm ra phiên bản gốc. Được xuất bản vào ngày 29 tháng 5 năm 2013 Tác giả là Rajandran R. Mã C ++ đã được xuất bản trên diễn đàn Mt4:https://www.mql5.com/en/code/viewcode/10851/128437/Non_Repainting_SuperTrend.mq4Tôi đã hiểu được ý nghĩa của C++, và tôi sẽ viết lại nó khi có cơ hội.
Tôi hy vọng bạn có thể học được bản chất từ nó. Thật khó!