Công cụ phân tích chiến lược năng động

Tác giả:ChaoZhang, Ngày: 2023-10-13 15:54:35
Tags:

Tổng quan

Ý tưởng chính của chiến lược này là mô phỏng giao dịch thời gian thực, thu thập dữ liệu giao dịch hàng tuần và trình bày thống kê trong một bảng để xem xét trực quan hơn về hiệu suất của chiến lược. Nó có thể giúp chúng ta nhanh chóng đánh giá lợi nhuận và lỗ của chiến lược, xác định các giai đoạn hiệu suất kém và tối ưu hóa chiến lược cho phù hợp.

Chiến lược logic

  1. Đặt thời gian bắt đầu và kết thúc cho thời gian tính toán.

  2. Đặt chính xác số liệu thống kê và số tuần trong mỗi nhóm.

  3. Mô phỏng chiến lược RSI cho các bước vào và ra.

  4. Định nghĩa các biến cho bảng thống kê.

  5. Tính toán kết quả cho giai đoạn hiện tại.

  6. Nếu thay đổi giai đoạn và giao dịch được bật, ghi lại thời gian và kết quả cho giai đoạn này.

  7. Nếu đó là thanh cuối cùng và giao dịch được bật, ghi lại thời gian và kết quả cho giai đoạn hiện tại.

  8. Nếu thay đổi giai đoạn và giao dịch bị vô hiệu hóa, ghi lại thời gian và kết quả cho giai đoạn trước.

  9. Tìm kết quả thời gian cao nhất và thấp nhất.

  10. Đưa bảng thống kê.

  • Đầu tiên tính tổng số thời gian thống kê

  • Iterate thông qua mỗi giai đoạn, hiển thị tiêu đề, thời gian và kết quả

  • Tính tích lũy kết quả cho mỗi nhóm

  • Kết quả dương tính và âm tính mã màu

Phân tích lợi thế

  • Có thể quan sát kết quả hàng tuần trong thời gian thực để đánh giá chiến lược nhanh chóng

  • Việc trình bày trực quan các kết quả để có những hiểu biết rõ ràng

  • Giúp xác định các giai đoạn hoạt động kém để điều chỉnh chiến lược

  • Dễ dàng để theo dõi lợi nhuận tích lũy cho các chiến lược dài hạn

  • Có thể so sánh phong cách giao dịch trong các khoảng thời gian khác nhau

  • Độ chính xác và nhóm có thể tùy chỉnh để đáp ứng các nhu cầu khác nhau

  • Mã đơn giản và rõ ràng, dễ hiểu và mở rộng

Phân tích rủi ro

  • Chiến lược dựa trên RSI, có xu hướng vốn có sau khi hạn chế

  • Chi phí giao dịch có thể ảnh hưởng đáng kể đến kết quả thực tế

  • Dữ liệu backtest có thể không phản ánh điều kiện thị trường thực tế

  • Tiền mặc định trong backtest có thể không phù hợp với kích thước tài khoản thực tế

  • Tránh quá tải bằng cách điều chỉnh mù quáng các thông số dựa trên thống kê

Có thể kết hợp nhiều chỉ số cho xu hướng và tối ưu hóa các mục nhập và lối ra để cải thiện chiến lược cơ bản của RSI. Sử dụng chi phí giao dịch thực tế trong giao dịch trực tiếp. Thêm ngẫu nhiên vào kích thước vốn trong backtest. Duy trì hoài nghi thay vì điều chỉnh quá mức dựa trên thống kê.

Hướng dẫn tối ưu hóa

  • Xem xét thêm stop loss để hạn chế downside

  • Tối ưu hóa các thông số RSI như mức mua quá mức và mức bán quá mức

  • Hãy thử các tần số giao dịch khác nhau như giữ trong ngày so với hàng tháng

  • Bao gồm nhiều chỉ số cho xu hướng và thời gian

  • Thêm lợi nhuận lấy logic

  • Tối ưu hóa cài đặt tham số thống kê

  • Mở rộng để theo dõi nhiều tài sản

Các điểm dừng có thể quản lý tốt hơn rủi ro / phần thưởng. Điều chỉnh RSI cải thiện tỷ lệ thắng. Nhiều chỉ số và tần số làm cho chiến lược mạnh mẽ. Điều chỉnh thống kê làm nổi bật dữ liệu quan trọng. Mở rộng đến nhiều tài sản cung cấp cái nhìn hoàn chỉnh.

Tóm lại

Mục tiêu là thu thập các kết quả định kỳ cho hình ảnh thống kê trực quan để nhanh chóng đánh giá hiệu suất theo thời gian. Điều này cung cấp dữ liệu để tối ưu hóa chiến lược. Điểm mạnh bao gồm kết quả hàng tuần thời gian thực, rõ ràng và khả năng mở rộng. Hãy thận trọng với sự phụ thuộc quá mức và phù hợp đường cong với đầu ra thống kê. Sử dụng hợp lý cùng với chiến lược cốt lõi để hiểu biết, không phải là cơ sở cho những thay đổi. Nhìn chung, cách thuận tiện để đánh giá hiệu suất và rất quan trọng cho tối ưu hóa.


/*backtest
start: 2023-09-12 00:00:00
end: 2023-10-12 00:00:00
period: 3h
basePeriod: 15m
exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}]
*/

//@version=5
// strategy('Strategy weekly results as numbers v1', overlay=true, default_qty_type=strategy.percent_of_equity, default_qty_value=25, commission_type=strategy.commission.percent, commission_value=0.04)

after = input(title='Trade after', defval=timestamp('01 Jan 2019 00:00 UTC'), tooltip="Strategy will be executed after this timestamp. The statistic table will include only periods after this date.")
before = input(title='Trade before', defval=timestamp('31 Dec 2024 23:59 UTC'), tooltip="Strategy will be executes before this timestamp. The statistic table will include only periods before this date.")

statisticPrecision = input.int(title='Statistic precision', group='Statistic visualisation', defval=1, tooltip="Defines how many digits should be rendered in every statistic cell.")
statisticGroupSize = input.int(title='Statistic group size', group='Statistic visualisation', defval=12, tooltip="Defines how many cells should be in one group inside the statistic table.")

// determinet whether the starategy should be traded between the period
isTradeEnabled = true


// *******************************************************************************************
// Core strategy simulation logic
// *******************************************************************************************
// calculate rsi strategy emulation data
rsiEmulationData = ta.rsi(close, 7)
rsiEmulationCrossover = ta.crossover(rsiEmulationData, 70)
rsiEmulationCrossunder = ta.crossunder(rsiEmulationData, 30)

// entry loogic based on the rsi calculations
if (isTradeEnabled and rsiEmulationCrossover)
    strategy.entry('Long', strategy.long)
if (isTradeEnabled and rsiEmulationCrossunder)
    strategy.entry('Short', strategy.short)


// *******************************************************************************************
// Weekly statistics table
// *******************************************************************************************
// define statistic variables
var statisticTable = table(na)
var statisticPeriodTime = array.new_int(0)
var statisticPeriodResult = array.new_float(0)
var statisticIsLatestCalculated = bool(na)
var statisticResultHighest = float(na)
var statisticResultLowest = float(na)
var statisticColorGray = color.new(color.gray, transp = 60)
var statisticColorGreen = color.new(color.green, transp = 60)
var statisticColorRed = color.new(color.red, transp = 60)

// claculate current period result
barResult = not na(strategy.equity[1])
             ? (strategy.equity / strategy.equity[1] - 1) : 0
isPeriodChanged = not na(time[1]) and weekofyear(time) != weekofyear(time[1])
currentPeriodResult = 0.0
currentPeriodResult := not na(currentPeriodResult[1]) and not isPeriodChanged
                       ? ((1 + currentPeriodResult[1]) * (1 + barResult) - 1) : 0.0

// initialise highest and lowest results variables
statisticResultHighest := na(statisticResultHighest) ? currentPeriodResult : statisticResultHighest
statisticResultLowest := na(statisticResultLowest) ? currentPeriodResult : statisticResultLowest

// search for highest and lowest results
statisticResultHighest := currentPeriodResult > statisticResultHighest ? currentPeriodResult : statisticResultHighest
statisticResultLowest := currentPeriodResult < statisticResultLowest ? currentPeriodResult : statisticResultLowest

// new week while trade is active
if isPeriodChanged and isTradeEnabled
    timeCalculated = time - 1000 * 60 * 60 * 24 * 7
    resultCalculated = currentPeriodResult[1]
    statisticIsLatestCalculated := false

    array.push(statisticPeriodTime, timeCalculated)
    array.push(statisticPeriodResult, resultCalculated)

// latest bar while trade is active
if barstate.islast and isTradeEnabled
    timeCalculated = time - 1000 * 60 * 60 * 24 * (dayofweek(time) - 2)
    resultCalculated = currentPeriodResult

    array.push(statisticPeriodTime, timeCalculated)
    array.push(statisticPeriodResult, resultCalculated)

// new week after trade disabled
if isPeriodChanged and not isTradeEnabled and not na(statisticIsLatestCalculated) and not statisticIsLatestCalculated
    timeCalculated = time - 1000 * 60 * 60 * 24 * (dayofweek(time) + 5)
    resultCalculated = currentPeriodResult[1]
    statisticIsLatestCalculated := true

    array.push(statisticPeriodTime, timeCalculated)
    array.push(statisticPeriodResult, resultCalculated)

// render statistics table
if barstate.islast
    statisticLength = array.size(statisticPeriodResult)
    statisticTableSteps = math.floor(statisticLength / statisticGroupSize) + (statisticLength % statisticGroupSize != 0 ? 1 : 0)
    statisticTable := table.new(position.bottom_right, columns = statisticGroupSize + 2, rows = statisticTableSteps + 1, border_width = 1)

    // render headers
    for i = 0 to (statisticGroupSize - 1)
        statisticHeaderContent = str.tostring(i + 1)
        table.cell(statisticTable, 1 + i, 0, statisticHeaderContent, bgcolor = statisticColorGray)

    // render time points
    for i = 0 to (statisticTableSteps - 1)
        statisticPointContent = str.format("{0,date,medium}", array.get(statisticPeriodTime, i * statisticGroupSize))
        table.cell(statisticTable, 0, 1 + i, statisticPointContent, bgcolor = statisticColorGray)

    // render the result
    statisticResultCummulative = 0.0
    for i = 0 to (array.size(statisticPeriodTime) - 1)
        statisticColumn = 1 + i % statisticGroupSize
        statisticRow = 1 + math.floor(i / statisticGroupSize)

        statisticResult = array.get(statisticPeriodResult, i)
        statisticResultCummulative := (i % statisticGroupSize == 0) ? 0.0 : statisticResultCummulative
        statisticResultCummulative := (1 + statisticResultCummulative) * (1 + statisticResult) - 1

        statisticResultColor = statisticResult > 0 ? statisticColorGreen : statisticColorRed
        table.cell(statisticTable, statisticColumn, statisticRow, str.tostring(math.round(statisticResult * 100, statisticPrecision)), bgcolor = statisticResultColor)

        // if it is the last item of the row or data array
        isStatisticLastOfTheRow = ((i + 1) % statisticGroupSize) == 0
        isStatisticLastOfTheData = i == (statisticLength - 1)
        if (isStatisticLastOfTheRow or isStatisticLastOfTheData)
            resultsTableCummulativeCellColor = statisticResultCummulative > 0 ? statisticColorGreen : statisticColorRed
            resultsTableCummulativeCellContent = str.tostring(math.round(statisticResultCummulative * 100, statisticPrecision))
            table.cell(statisticTable, 1 + statisticGroupSize, statisticRow, resultsTableCummulativeCellContent, bgcolor = resultsTableCummulativeCellColor)

Thêm nữa