
Chiến lược này được dựa trên chiến lược nổi tiếng của các nhà giao dịch hải cẩu, chiến lược này đã được chứng minh trong nhiều năm. Nó gửi các tín hiệu dài và trống, tối đa có thể thực hiện 5 lệnh kim tự tháp, có nghĩa là chiến lược này có thể kích hoạt tối đa 5 lệnh theo cùng một hướng.
Cần lưu ý rằng chiến lược này kết hợp hai hệ thống làm việc cùng nhau (S1 và S2).
Kích thước vị trí rất quan trọng đối với các nhà giao dịch biển, để quản lý rủi ro một cách thích hợp. Chiến lược điều chỉnh vị trí này phù hợp với biến động của thị trường và tài khoản (lợi nhuận và tổn thất). Nó dựa trên ATR (trung bình phạm vi thực tế), cũng có thể được gọi là N.
Số đơn vị mua là:
unit = (percentage_to_risk/100)*account/atr*syminfo.pointvalue
Bạn có thể tăng tỷ lệ phần trăm của tài khoản tùy theo sở thích rủi ro của bạn, nhưng các nhà giao dịch hải dương mặc định là 1%. Nếu bạn giao dịch hợp đồng, đơn vị phải lấy số nguyên theo mặc định.
Ngoài ra còn có một quy tắc bổ sung để giảm rủi ro khi giá trị tài khoản thấp hơn vốn đầu tư: Trong trường hợp này, trong công thức đơn vị phải được thay thế bằng phương thức sau:
account := (strategy.equity-strategy.openprofit)*(strategy.equity-strategy.openprofit)/strategy.initial_capital
Có hai hệ thống làm việc cùng nhau: Bước đột phá là một mức cao mới hoặc mức thấp mới. Nếu đó là một mức cao mới, chúng tôi mở một vị trí đầu tư nhiều, ngược lại, nếu đó là một mức thấp mới, chúng tôi đi vào vị trí đầu tư trống.
Chúng tôi thêm một quy tắc nữa: Quy tắc bổ sung này cho phép các nhà giao dịch tham gia vào xu hướng chính nếu có dấu hiệu System 1 bị bỏ qua. Nếu có dấu hiệu của System 1 bị bỏ qua và đường K tiếp theo cũng là một bước đột phá 20 ngày mới, thì S1 sẽ không phát tín hiệu. Chúng ta phải chờ tín hiệu S2 hoặc chờ đợi không tạo ra đường K đột phá mới để kích hoạt lại S1.
Chiến lược Bờ biển cho phép chúng tôi thêm đơn vị vào vị trí khi xu hướng giá thuận lợi cho chúng tôi. Tôi đã cấu hình chiến lược để cho phép thêm tối đa 5 lệnh theo cùng một hướng. Do đó, nếu giá thay đổi từ mua, chúng tôi sẽ thêm đơn vị.
Chúng tôi sẽ đặt đơn đặt hàng đầu tiên là ((multi-headed hoặc empty head)) là đơn đặt hàng lớn nhất. Các đơn đặt hàng kim tự tháp tiếp theo sẽ có ít đơn vị hơn đơn đặt hàng đầu tiên.
Chúng tôi đặt mức dừng tối đa là 10% cho đơn đặt hàng đầu tiên, có nghĩa là bạn sẽ không mất nhiều hơn 10% giá trị đơn đặt hàng đầu tiên. Tuy nhiên, vì dừng sẽ tăng/giảm 0,5*ATR ((20), lệnh kim tự tháp của bạn có thể bị mất nhiều hơn, tại thời điểm này không đảm bảo mất mát không quá 10%. Rủi ro vẫn được quản lý tốt vì các lệnh này có giá trị thấp hơn giá trị của lệnh đầu tiên.
Rủi ro lớn nhất của chiến lược này là giữ quá nhiều vị thế. Do giao dịch được ủy thác sử dụng đơn giá thị trường, nếu có nhiều đơn giá thị trường lớn được đưa ra cùng một lúc, sẽ có tác động lớn đến giá, gây ra sự trượt giá lớn. Điều này có thể gây ra tổn thất tài chính rất lớn.
Một rủi ro khác là việc quản lý tài chính không phù hợp. Nếu điều chỉnh sai hoặc tỷ lệ quá lớn, sẽ dẫn đến tổn thất lớn. Điều này cần phải được điều chỉnh cẩn thận theo sở thích rủi ro của riêng bạn.
Chiến lược này có thể được tối ưu hóa ở một số khía cạnh:
Có thể kiểm tra ảnh hưởng của các tham số khác nhau đối với lợi nhuận và tỷ lệ Sharpe, chẳng hạn như chu kỳ ATR, nhân ATR dừng lỗ, v.v.
Có thể thử nghiệm các quy tắc nhập và xuất khác nhau. Ví dụ: sử dụng hình dạng đường K như một điều kiện lọc bổ sung.
Có thể thử các loại chặn khác, như chặn di chuyển, chặn động. Điều này có thể làm giảm khả năng chặn bị phá vỡ.
Có thể thử nghiệm một số lượng khác nhau các lệnh kim tự tháp. Càng nhiều lệnh, càng có nhiều lợi thế và rủi ro. Tìm điểm cân bằng tốt nhất.
Bạn có thể cố gắng dừng giao dịch trong một khoảng thời gian nhất định (ví dụ như trước khi dữ liệu việc làm phi nông nghiệp của Mỹ được công bố) để tránh tác động của các sự kiện lớn.
Nhìn chung, chiến lược này có sự cân bằng lợi nhuận rủi ro tốt, phù hợp với giao dịch xu hướng đường dài và trung bình. Nó có những lợi thế như hệ thống hóa giao dịch, có thể kiểm soát rủi ro. Bằng cách tối ưu hóa, bạn có thể nâng cao hơn nữa sự ổn định và lợi nhuận của chiến lược.
/*backtest
start: 2023-12-01 00:00:00
end: 2023-12-31 23:59:59
period: 1h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/
// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © gsanson66
//This strategy is based on the famous "Turtle Strategy"
//A well-known strategy which proved its performance during past years
//@version=5
strategy("TURTLE STRATEGY", overlay=true)
//------------------------------TOOL TIPS--------------------------------//
t1 = "Percentage of the account the trader is willing to lose. This percentage is used to define the position size based on previous gains or losses. Turtle traders default to 1%."
t2 = "ATR Length"
t3 = "ATR Multiplier to fix the Stop Loss"
t4 = "Pyramiding : ATR Multiplier to set a profit target to increase position size"
t5 = "System 1 enter long if there is a new high after this selected period of time"
t6 = "System 2 enter long if there is a new high after this selected period of time"
t7 = "Exit Long from system 1 if there is a new low after this selected period of time"
t8 = "Exit Long from system 2 if there is a new low after this selected period of time"
t9 = "System 1 enter short if there is a new low after this selected period of time"
t10 = "System 2 enter short if there is a new low after this selected period of time"
t11 = "Exit short from system 1 if there is a new high after this selected period of time"
t12 = "Exit short from system 2 if there is a new high after this selected period of time"
//----------------------------------------FUNCTIONS---------------------------------------//
//@function Displays text passed to `txt` when called.
debugLabel(txt, color) =>
label.new(bar_index, high, text=txt, color=color, style=label.style_label_lower_right, textcolor=color.black, size=size.small)
//@function which looks if the close date of the current bar falls inside the date range
inBacktestPeriod(start, end) => true
//---------------------------------------USER INPUTS--------------------------------------//
//Risk Management and turtle system input
percentage_to_risk = input.float(1, "Risk % of capital", maxval=100, minval=0, group="Turtle Parameters", tooltip=t1)
atr_period = input.int(20, "ATR period", minval=1, group="Turtle Parameters", tooltip=t2)
stop_N_multiplier = input.float(1.5, "Stop ATR", minval=0.1, group="Turtle Parameters", tooltip=t3)
pyramid_profit = input.float(0.5, "Pyramid Profit", minval=0.01, group="Turtle Parameters", tooltip=t4)
S1_long = input.int(20, "S1 Long", minval=1, group="Turtle Parameters", tooltip=t5)
S2_long = input.int(55, "S2 Long", minval=1, group="Turtle Parameters", tooltip=t6)
S1_long_exit = input.int(10, "S1 Long Exit", minval=1, group="Turtle Parameters", tooltip=t7)
S2_long_exit = input.int(20, "S2 Long Exit", minval=1, group="Turtle Parameters", tooltip=t8)
S1_short = input.int(15, "S1 Short", minval=1, group="Turtle Parameters", tooltip=t9)
S2_short = input.int(55, "S2 Short", minval=1, group="Turtle Parameters", tooltip=t10)
S1_short_exit = input.int(7, "S1 Short Exit", minval=1, group="Turtle Parameters", tooltip=t11)
S2_short_exit = input.int(20, "S2 Short Exit", minval=1, group="Turtle Parameters", tooltip=t12)
//Backtesting period
startDate = input(title="Start Date", defval=timestamp("1 Jan 2020 00:00:00"), group="Backtesting Period")
endDate = input(title="End Date", defval=timestamp("1 July 2034 00:00:00"), group="Backtesting Period")
//----------------------------------VARIABLES INITIALISATION-----------------------------//
//Turtle variables
atr = ta.atr(atr_period)
var float buy_price_long = na
var float buy_price_short = na
var float stop_loss_long = na
var float stop_loss_short = na
float account = na
//Entry variables
day_high_syst1 = ta.highest(high, S1_long)
day_low_syst1 = ta.lowest(low, S1_short)
day_high_syst2 = ta.highest(high, S2_long)
day_low_syst2 = ta.lowest(low, S2_short)
var bool skip = false
var bool unskip_buffer_long = false
var bool unskip_buffer_short = false
//Exit variables
exit_long_syst1 = ta.lowest(low, S1_long_exit)
exit_short_syst1 = ta.highest(high, S1_short_exit)
exit_long_syst2 = ta.lowest(low, S2_long_exit)
exit_short_syst2 = ta.highest(high, S2_short_exit)
float exit_signal = na
//Backtesting period
bool inRange = na
//------------------------------CHECKING SOME CONDITIONS ON EACH SCRIPT EXECUTION-------------------------------//
strategy.initial_capital = 50000
//Checking if the date belong to the range
inRange := inBacktestPeriod(startDate, endDate)
//Checking if the current equity is higher or lower than the initial capital to adjusted position size
if strategy.equity - strategy.openprofit < strategy.initial_capital
account := (strategy.equity-strategy.openprofit)*(strategy.equity-strategy.openprofit)/strategy.initial_capital
else
account := strategy.equity - strategy.openprofit
//Checking if we close all trades in case where we exit the backtesting period
if strategy.position_size!=0 and not inRange
strategy.close_all()
debugLabel("END OF BACKTESTING PERIOD : we close the trade", color=color.rgb(116, 116, 116))
//--------------------------------------SKIP MANAGEMENT------------------------------------//
//Checking if a long signal has been skiped and system2 is not triggered
if skip and high>day_high_syst1[1] and high<day_high_syst2[1]
unskip_buffer_long := true
//Checking if a short signal has been skiped and system2 is not triggered
if skip and low<day_low_syst1[1] and low>day_low_syst2[1]
unskip_buffer_short := true
//Checking if current high is lower than previous 20_day_high after a skiped long signal to set skip to false
if unskip_buffer_long
if high<day_high_syst1[1]
skip := false
unskip_buffer_long := false
//Checking if current low is higher than previous 20_day_low after a skiped short signal to set skip to false
if unskip_buffer_short
if low>day_low_syst1[1]
skip := false
unskip_buffer_short := false
//Checking if we have an open position to reset skip and unskip buffers
if strategy.position_size!=0 and skip
skip := false
unskip_buffer_long := false
unskip_buffer_short := false
//--------------------------------------------ENTRY CONDITIONS--------------------------------------------------//
//We calculate the position size based on turtle calculation
unit = (percentage_to_risk/100)*account/atr*syminfo.pointvalue
//Long order for system 1
if not skip and not (strategy.position_size>0) and inRange
strategy.cancel("Long Syst 2")
//We check that position size doesn't exceed available equity
if unit*day_high_syst1>account
unit := account/day_high_syst1
stop_loss_long := day_high_syst1 - stop_N_multiplier*atr
//We adjust SL if it's greater than 10% of trade value and fix it to 10%
if stop_loss_long < day_high_syst1*0.9
stop_loss_long := day_high_syst1*0.9
strategy.order("Long Syst 1", strategy.long, unit, stop=day_high_syst1)
buy_price_long := day_high_syst1
//Long order for system 2
if skip and not (strategy.position_size>0) and inRange
//We check that position size doesn't exceed available equity
if unit*day_high_syst2>account
unit := account/day_high_syst2
stop_loss_long := day_high_syst2 - stop_N_multiplier*atr
//We adjust SL if it's greater than 10% of trade value and fix it to 10%
if stop_loss_long < day_high_syst2*0.9
stop_loss_long := day_high_syst2*0.9
strategy.order("Long Syst 2", strategy.long, unit, stop=day_high_syst2)
buy_price_long := day_high_syst2
//Short order for system 1
if not skip and not (strategy.position_size<0) and inRange
strategy.cancel("Short Syst 2")
//We check that position size doesn't exceed available equity
if unit*day_low_syst1>account
unit := account/day_low_syst1
stop_loss_short := day_low_syst1 + stop_N_multiplier*atr
//We adjust SL if it's greater than 10% of trade value and fix it to 10%
if stop_loss_short > day_low_syst1*1.1
stop_loss_short := day_low_syst1*1.1
strategy.order("Short Syst 1", strategy.short, unit, stop=day_low_syst1)
buy_price_short := day_low_syst1
//Short order for system 2
if skip and not (strategy.position_size<0) and inRange
//We check that position size doesn't exceed available equity
if unit*day_low_syst2>account
unit := account/day_low_syst2
stop_loss_short := day_low_syst2 + stop_N_multiplier*atr
//We adjust SL if it's greater than 10% of trade value and fix it to 10%
if stop_loss_short > day_low_syst2*1.1
stop_loss_short := day_low_syst2*1.1
strategy.order("Short Syst 2", strategy.short, unit, stop=day_low_syst2)
buy_price_short := day_low_syst2
//-------------------------------PYRAMIDAL------------------------------------//
//Pyramid for long orders
if close > buy_price_long + (pyramid_profit*atr) and strategy.position_size>0
//We calculate the remaining capital
remaining_capital = account - strategy.position_size*strategy.position_avg_price*(1-0.0018)
//We calculate units to add to the long position
units_to_add = (percentage_to_risk/100)*remaining_capital/atr*syminfo.pointvalue
if remaining_capital > units_to_add
//We set the new Stop loss
stop_loss_long := stop_loss_long + pyramid_profit*atr
strategy.entry("Pyramid Long", strategy.long, units_to_add)
buy_price_long := close
//Pyramid for short orders
if close < buy_price_short - (pyramid_profit*atr) and strategy.position_size<0
//We calculate the remaining capital
remaining_capital = account + strategy.position_size*strategy.position_avg_price*(1-0.0018)
//We calculate units to add to the short position
units_to_add = (percentage_to_risk/100)*remaining_capital/atr*syminfo.pointvalue
if remaining_capital > units_to_add
//We set the new Stop loss
stop_loss_short := stop_loss_short - pyramid_profit*atr
strategy.entry("Pyramid Short", strategy.short, units_to_add)
buy_price_short := close
//----------------------------EXIT ORDERS-------------------------------//
//Checking if exit_long_syst1 is higher than stop_loss_long
if strategy.opentrades.entry_id(0)=="Long Syst 1"
if exit_long_syst1[1] > stop_loss_long
exit_signal := exit_long_syst1[1]
else
exit_signal := stop_loss_long
//Checking if exit_long_syst2 is higher than stop_loss_long
if strategy.opentrades.entry_id(0)=="Long Syst 2"
if exit_long_syst2[1] > stop_loss_long
exit_signal := exit_long_syst2[1]
else
exit_signal := stop_loss_long
//Checking if exit_short_syst1 is lower than stop_loss_short
if strategy.opentrades.entry_id(0)=="Short Syst 1"
if exit_short_syst1[1] < stop_loss_short
exit_signal := exit_short_syst1[1]
else
exit_signal := stop_loss_short
//Checking if exit_short_syst2 is lower than stop_loss_short
if strategy.opentrades.entry_id(0)=="Short Syst 2"
if exit_short_syst2[1] < stop_loss_short
exit_signal := exit_short_syst2[1]
else
exit_signal := stop_loss_short
//If the exit order is configured to close the position at a profit, we set 'skip' to true (we substract commission)
if strategy.position_size*exit_signal>strategy.position_size*strategy.position_avg_price*(1-0.0018)
strategy.cancel("Long Syst 1")
strategy.cancel("Short Syst 1")
skip := true
if strategy.position_size*exit_signal<=strategy.position_size*strategy.position_avg_price*(1-0.0018)
skip := false
//We place stop exit orders
if strategy.position_size > 0
strategy.exit("Exit Long", stop=exit_signal)
if strategy.position_size < 0
strategy.exit("Exit Short", stop=exit_signal)
//------------------------------PLOTTING ELEMENTS-------------------------------//
plotchar(atr, "ATR", "", location.top, color.rgb(131, 5, 83))
//Plotting enter threshold
plot(day_high_syst1[1], "20 day high", color.rgb(118, 217, 159))
plot(day_high_syst2[1], "55 day high", color.rgb(4, 92, 53))
plot(day_low_syst1[1], "20 day low", color.rgb(234, 108, 108))
plot(day_low_syst2[1], "55 day low", color.rgb(149, 17, 17))
//Plotting Exit Signal
plot(exit_signal, "Exit Signal", color.blue, style=plot.style_circles)
//Plotting our position
exit_long_syst2_plot = plot(exit_long_syst2[1], color=na)
day_high_syst2_plot = plot(day_high_syst2[1], color=na)
exit_short_syst2_plot = plot(exit_short_syst2[1], color=na)
day_low_syst2_plot = plot(day_low_syst2[1], color=na)
fill(exit_long_syst2_plot, day_high_syst2_plot, color=strategy.position_size>0 ? color.new(color.lime, 90) : na)
fill(exit_short_syst2_plot, day_low_syst2_plot, color=strategy.position_size<0 ? color.new(color.red, 90) : na)