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

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

Thông tin chi tiết

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

Nguyên tắc chiến lược

  1. Thiết lập thời gian bắt đầu và kết thúc chu kỳ tính toán.

  2. Thiết lập độ chính xác của kết quả thống kê và số tuần trong mỗi nhóm.

  3. Các chiến lược mua bán bắt chước RSI.

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

  5. Tính toán kết quả của chu kỳ hiện tại.

  6. Nếu chu kỳ thay đổi và cho phép giao dịch, ghi lại thời gian và kết quả của chu kỳ này.

  7. Nếu là dòng K cuối cùng và cho phép giao dịch, ghi lại thời gian và kết quả của chu kỳ hiện tại.

  8. Nếu chu kỳ thay đổi và không cho phép giao dịch, ghi lại thời gian và kết quả của chu kỳ trước.

  9. Tìm kết quả chu kỳ cao nhất và thấp nhất.

  10. Những con số này có thể được sử dụng trong các hình ảnh.

  • Đầu tiên tính tổng số chu kỳ thống kê

  • Đi qua mỗi chu kỳ, biểu diễn các trang, thời gian và kết quả

  • Kết quả của mỗi nhóm chu kỳ được tích lũy

  • Kết quả dương tính được đánh dấu bằng màu sắc

Phân tích ưu thế

  • Có thể xem kết quả giao dịch hàng tuần trong thời gian thực và đánh giá nhanh hiệu suất chiến lược

  • Những kết quả hiển thị trực quan, ngay lập tức, giúp bạn tìm ra các chu kỳ chiến lược hoạt động kém.

  • Có thể điều chỉnh và tối ưu hóa các tham số chiến lược theo mức lợi nhuận và thua lỗ trong khoảng thời gian

  • Có thể dễ dàng theo dõi lợi nhuận tích lũy hàng tuần từ chiến lược nắm giữ dài hạn

  • Có thể phân tích các phong cách giao dịch khác nhau trong thời gian

  • Tính chính xác thống kê tùy chỉnh và số tuần phân nhóm để đáp ứng nhu cầu khác nhau

  • Mã thực hiện đơn giản, rõ ràng, dễ hiểu và phát triển thứ hai

Phân tích rủi ro

  • Chiến lược này dựa trên RSI để kinh doanh giả lập, và chiến lược RSI có những nhược điểm của nó không theo xu hướng đủ mạnh.

  • Trong thực tế, chi phí giao dịch có ảnh hưởng lớn đến kết quả.

  • Dữ liệu lịch sử được sử dụng để đánh giá lại không nhất thiết phản ánh môi trường giao dịch thực tế

  • Kết quả thống kê phụ thuộc vào số tiền trong tài khoản thực, số tiền mặc định trong đánh giá lại không nhất thiết chính xác

  • Cần chú ý để ngăn ngừa quá phù hợp, thay đổi một cách mù quáng các tham số chính sách theo kết quả kiểm tra lại

Có thể tăng cường chiến lược RSI bằng cách kết hợp nhiều chỉ số hơn để xác định xu hướng, tối ưu hóa các điểm vào và ra. Khi giao dịch trên thực tế, hãy chú ý đến việc thiết lập phí thủ tục theo các tham số thực sự. Tăng sự biến động của số tiền trong giai đoạn kiểm tra lại, làm cho nó gần với thực tế hơn, v.v.

Định hướng tối ưu

  • Bạn có thể xem xét sử dụng logic dừng lỗ để kiểm soát lỗ đơn lẻ.

  • Có thể tối ưu hóa các thông số chiến lược như điều chỉnh ngưỡng tăng hoặc giảm của RSI

  • Có thể thử các tần số giao dịch khác nhau, chẳng hạn như giao dịch trong ngày hoặc giữ hàng tháng

  • Có thể thêm nhiều chỉ số để xác định xu hướng thị trường và thời điểm tham gia

  • Bạn có thể xem xét thêm logic ngăn chặn.

  • Bạn có thể tối ưu hóa cài đặt các thông số thống kê

  • Có thể xem xét thực hiện thống kê về nhiều loại tài sản

Bằng cách thêm stop-loss, bạn có thể kiểm soát tốt hơn tỷ lệ rủi ro và lợi nhuận. Tối ưu hóa các thông số RSI có thể cải thiện tỷ lệ thắng. Sử dụng nhiều thông số hơn và tần suất giao dịch khác nhau có thể làm cho chiến lược ổn định hơn. Điều chỉnh các thông số thống kê có thể làm cho kết quả nổi bật hơn.

Tóm lại

Mục đích của chiến lược là thu thập kết quả giao dịch theo chu kỳ, hiển thị trực quan dưới dạng bảng thống kê, để có thể nhanh chóng xác định tình trạng thua lỗ của chiến lược trong các khoảng thời gian khác nhau. Điều này cung cấp hỗ trợ dữ liệu cho tối ưu hóa chiến lược. Ưu điểm là có thể xem kết quả hàng tuần trong thời gian thực, trực quan rõ ràng và dễ phát triển thứ hai.


/*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)

Nhiều hơn nữa