Ý 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.
Đặt thời gian bắt đầu và kết thúc cho thời gian tính toán.
Đặt chính xác số liệu thống kê và số tuần trong mỗi nhóm.
Mô phỏng chiến lược RSI cho các bước vào và ra.
Định nghĩa các biến cho bảng thống kê.
Tính toán kết quả cho giai đoạn hiện tại.
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.
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.
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.
Tìm kết quả thời gian cao nhất và thấp nhất.
Đư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
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
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ê.
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.
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)