Chiến lược tạo ra kết quả tốt không thực tế bằng cách nhìn vào tương lai

Một trong những mục tiêu chính của chúng tôi khi phát triển ngôn ngữ Pine là cung cấp cho người dùng nhiều công cụ hữu ích nhất có thể. Các công cụ này có thể có nhiều cách sử dụng khác nhau và với một số thao tác nhất định, một số chỉ báo và loại biểu đồ cho phép bạn trích xuất dữ liệu từ các thanh hoặc giao dịch trong tương lai (liên quan đến thanh hiện đang được xử lý). Vì một nhà giao dịch không thể nhận được dữ liệu này trong giao dịch thực, các chiến lược được xây dựng xung quanh nó có thể tạo ra kết quả sinh lời không thực tế khi phản đối, trong khi trong giao dịch thời gian thực, các giao dịch này sẽ thua lỗ. Sai lầm khi sử dụng thông tin từ tương lai trong các chiến lược còn được gọi là thiên vị nhìn trước.

Một số người dùng TradingView, vì thiếu hiểu biết hoặc có mục đích xấu, có xu hướng tạo ra các ý tưởng và các ấn phẩm kịch bản khai thác tính năng này. TradingView không thể tự xóa tính năng này vì nó có thể hữu ích trong một số trường hợp, nhưng đồng thời, chúng tôi cam kết cảnh báo người dùng về hành vi này.

Chiến lược sử dụng nến kiểu Nhật

Một lý do rất phổ biến cho hành vi này là chiến lược phản đối trên các biểu đồ kiểu Nhật Bản (Renko, Kagi, v.v.). Vấn đề nảy sinh từ thực tế là Strategy Backtesting Engine coi mỗi thanh là 4 giao dịch, với các mức giá mở, cao, thấp và đóng (như trường hợp của biểu đồ hình nến thông thường). Do đó, trên biểu đồ Renko, Strategy Backtesting Engine có thể nhập / thoát một vị trí ở mức giá không tồn tại trong thực tế. Ngoài ra, nếu bạn đặt giá trị Kích thước hộp nhỏ hơn giá trị tùy chọn, bạn có thể kiểm tra xem giá tiếp theo sẽ cao hơn hay thấp hơn giá hiện tại và nhập / thoát vị trí trước, trước khi Backtesting Engine xử lý giá thực.

//@version=4
strategy("My Strategy", overlay=true)
if close < close[1]
    strategy.entry("ShortEntryId", strategy.short)
strategy.close("ShortEntryId", when = close > close[1])

if close > close[1]
    strategy.entry("LongEntryId", strategy.long)
strategy.close("LongEntryId", when = close < close[1])

Như bạn có thể thấy trên ảnh chụp màn hình, chiến lược đơn giản này có thể thực hiện các giao dịch ở mức giá rất gần với mức giá tối đa / tối thiểu.

Các chiến lược sử dụng tham số calc_on_order_fills = true

Khi tham số calc_on_order_fills = true được chỉ định trong hàm chiến lược, Backtesting Engine thực hiện một phép tính bổ sung bên trong thanh sau khi lệnh được thực hiện (trái ngược với tình huống thông thường khi chiến lược chỉ được tính ở cuối thanh). Đồng thời, trong quá trình tính toán, chiến lược có quyền truy cập vào nhiều tham số thanh bổ sung, ví dụ: giá trị cao và thấp. Điều này cho phép bạn viết một chiến lược sẽ cho thấy hiệu suất tuyệt vời trong khi phản hồi:

//@version=4
strategy("CalcOnOrderFillsStrategy", overlay=true, calc_on_order_fills=true)

// a variable is used to prevent double entry on the same bar
var lastTimeEntry = 0

longCondition = close > sma(close, 14)  and lastTimeEntry != time
if longCondition
    strategy.entry("LongEntryId", strategy.long)

strategy.exit("exitId", "LongEntryId", limit=high)
lastTimeEntry := time

Trên ảnh chụp màn hình, bạn có thể thấy rằng mục nhập ở mức giá mở của một thanh và việc thoát xảy ra ở mức cao của cùng một thanh. Tức là, trong quá trình tính toán, sau khi lệnh được thực hiện, chúng tôi đặt giá giới hạn chiến lược bằng với mức cao của thanh hiện tại, điều mà chúng tôi không thể thực hiện trong giao dịch thực.

Tham số lookahead = barmerge.lookahead_on trong bảo mật và bất kỳ bảo mật nào trước Pine v3

Chức năng bảo mật trong Pine cho phép bạn yêu cầu dữ liệu từ các ký hiệu và / hoặc khung thời gian khác. Tùy thuộc vào việc triển khai, điều này có thể cho phép chiến lược nhận dữ liệu từ tương lai: ví dụ: nếu một người yêu cầu mức đóng hoặc mức cao của thanh hàng ngày, trong khi phản hồi chiến lược có thể biết các giá trị này ngay vào đầu ngày .

Trước phiên bản 3, chức năng bảo mật sẽ trả về giá trị từ khung thời gian cao hơn ngay cả trước khi nó đáng lẽ có thể truy cập được. Trong phiên bản 3, hành vi này đã được khắc phục, nhưng để tương thích, tham số lookahead đã được thêm vào chức năng bảo mật. Nó là false theo mặc định (tức là tầm nhìn trong tương lai bị tắt), nhưng bạn có thể bật nó bằng cách đặt giá trị của lookahead tham số thành barmerge.lookahead_on).

Ví dụ về chiến lược sinh lời được xây dựng bằng tính năng này:

//@version=4
strategy("My Strategy", overlay=true)
dayStart = security(syminfo.tickerid, "1D", time, lookahead=barmerge.lookahead_on)
dayHigh = security(syminfo.tickerid, "1D", high, lookahead=barmerge.lookahead_on)
dayLow = security(syminfo.tickerid, "1D", low, lookahead=barmerge.lookahead_on)

// entry at first bar of a day
if time == dayStart
    // distance to daily high is further, so we can earn more
    if abs(open - dayHigh) > abs(open - dayLow)
        strategy.entry("LongEntryId", strategy.long)
        strategy.exit("exitLongId", "LongEntryId", limit=dayHigh)
    else
        strategy.entry("ShortEntryId", strategy.short)
        strategy.exit("exitShortId", "ShortEntryId", limit=dayLow)
        
plot(dayHigh)
plot(dayLow)

Trên thanh đầu tiên, chúng tôi phân tích xem giá sẽ tăng lên hay xuống nhiều hơn so với giá mở cửa và dựa trên điều này, chúng tôi nhập vị thế mua hay bán, sau đó thoát ra ở mức giá tối đa hoặc tối thiểu trong ngày, tương ứng.

Lưu ý rằng không phải tất cả các trường hợp mà security () có đối số barmerge.lookahead_on đều hướng tới tương lai: ví dụ: nếu chúng ta thay đổi mã ở trên bằng cách thay thế time / high / low inside security () thành time [1] / high [ 1] / low [1] tương ứng, chúng tôi sẽ nhận được giá trị cho các thanh đã đóng. Điều này thường được sử dụng bởi các lập trình viên có kinh nghiệm để lấy dữ liệu từ bảo mật () mà không có bất kỳ nguy cơ tìm kiếm nào.

Hiện tại, đây đều là những cách được biết đến cho một chiến lược nhìn về tương lai. Chúng tôi hy vọng rằng mô tả này sẽ cho phép bạn tạo ra các chiến lược không có những thiếu sót này, cũng như tránh các chiến lược đã xuất bản mà tác giả khai thác những đặc điểm này trong ý tưởng của họ.