이 전략은 트렌드 방향을 결정하기 위해 서로 다른 기간에 두 개의 간단한 이동 평균의 교차를 사용하여 트렌드가 나타나면 거래를 입력합니다. 동시에 전략은 다른 시간 스케일에 전략의 예상 수익을 계산하고 표시하기 위해 예상 가치 패널을 도입하여 사용자가 전략의 성능을 더 잘 평가 할 수 있습니다. 예상 가치 패널은 전략의 승률, 평균 이익 및 역사적 기간 동안 평균 손실과 같은 주요 지표를 고려하고 다양한 시장 조건 하에서 전략의 성과를 직관적으로 제시합니다.
이 전략의 핵심은 시장 추세를 결정하기 위해 서로 다른 기간 (14 일과 28 일 이 예제) 의 두 가지 간단한 이동 평균의 교차를 사용하는 것입니다. 단기 평균이 아래에서 장기 평균을 넘어서면 시장이 상승 추세에 들어갔다고 간주되며 전략은 긴 지위를 개척합니다. 반대로 단기 평균이 상위에서 장기 평균을 넘어서면 시장이 하락 추세에 들어갔다고 간주되며 전략은 짧은 지위를 개척합니다. 이러한 방식으로 전략은 다른 시장 추세에 적응하고 트렌드가 트렌드에 의해 가져온 이윤을 포착하는 것처럼 보일 때 적시에 위치를 설정 할 수 있습니다.
기본 트렌드 결정 및 거래 논리 외에도 전략은 다른 시간 스케일 (월별 및 연간) 에서 전략의 예상 수익을 계산하고 표시 할 수있는 예상 가치 패널을 도입합니다. 예상 가치의 계산은 다음과 같은 역사적 기간 동안 전략의 주요 통계 지표에 기초합니다.
이 지표들을 이용하면 그 기간에 전략의 예상 가치를 계산할 수 있습니다. 예상 가치 = 승률 × 평균 이익 - (1 - 승률) × 평균 손실
그래프에 열지도의 형태로 다른 기간의 예상 값을 표시함으로써 사용자는 다른 시장 조건에서 전략의 예상 성과를 한 눈에 볼 수 있으며, 따라서 전략의 적용성과 위험을 더 잘 파악 할 수 있습니다.
트렌드에 대한 높은 적응력: 트렌드를 결정하기 위해 이동 평균 크로스오버를 사용하여 전략은 시장 변화에 적응하기 위해 다른 시장 트렌드에 따라 포지션을 적시에 조정할 수 있습니다. 이것은 전략이 트렌딩 시장에서 좋은 수익을 얻을 수있게합니다.
직관적인 성능 평가: 내장된 예상 가치 패널은 히트맵 형태로 전략의 예상 수익을 다양한 시간대에 표시하여 사용자가 다른 시장 조건 하에서 전략의 성능을 한 눈에 평가 할 수 있습니다. 이 시각화된 성능 프레젠테이션은 사용자에게 더 많은 의사 결정 참조를 제공합니다.
주요 통계 지표의 고려: 예상 가치의 계산은 전략의 승률뿐만 아니라 평균 이익과 평균 손실의 영향을 통합합니다.이 계산 방법은 전략의 실제 성과를 보다 포괄적이고 정확하게 반영하여 사용자에게 더 신뢰할 수있는 참조를 제공합니다.
유연한 매개 변수 설정: 사용자는 자신의 필요에 따라 예상 값 패널과 투명성을 표시할지 여부를 유연하게 설정할 수 있습니다. 이것은 사용자가 자신의 선호도에 따라 차트의 표시 효과를 조정하여 사용자 경험을 향상시킬 수 있습니다.
범위에 묶인 시장에서 낮은 성과: 전략은 주로 수익을 창출하기 위해 추세에 의존하기 때문에 범위에 묶인 또는 추세에 대한 불분명한 시장 조건에서 빈번하게 거래하면 전략의 전반적인 성과에 영향을 미치는 상당한 미끄러짐 및 거래 비용이 발생할 수 있습니다.
예상 가치 계산의 한계: 예상 가치 패널은 전략 성과를 평가하는 직관적인 방법을 제공하지만 여전히 계산을 위해 역사적 데이터에 기반합니다. 시장에서 중요한 변화가 발생하거나 극단적인 상황이 발생하면 역사적 데이터가 전략의 실제 성과를 잘 반영하지 않을 수 있으며 예상 가치의 기준 값이 감소 할 수 있습니다.
매개 변수 선택의 큰 영향: 전략의 성능은 이동 평균 기간의 선택에 크게 달려 있습니다. 다른 기간 조합은 완전히 다른 거래 결과를 가져올 수 있습니다. 선택한 매개 변수가 시장 특성에 잘 적응할 수 없다면 전략의 실제 성능은 예상 가치에서 크게 벗어날 수 있습니다.
더 많은 기술 지표를 도입: 기존 이동 평균을 바탕으로 MACD와 RSI와 같은 다른 기술 지표를 고려하여 트렌드의 강도와 지속 가능성을 더 잘 결정하여 전략 입출시기를 개선할 수 있습니다.
포지션 관리를 최적화: 현재 전략은 거래 신호가 나타날 때 고정 포지션 접근 방식을 채택합니다. 시장 변동성 및 트렌드 강도와 같은 요인에 따라 포지션을 동적으로 조정하여 위험을 더 잘 제어하고 수익을 높이는 것을 고려할 수 있습니다.
스톱-프로프트 및 스톱-러스 메커니즘을 추가: 전략에 합리적인 스톱-프로프트 및 스톱-러스 메커니즘을 추가하면 전략이 잠재적 인 손실을 제한하면서 기존 수익을 적시에 잠금 할 수 있습니다. 이것은 전략의 위험-상금 비율을 개선하고 다양한 시장 환경에서 비교적 안정적인 성과를 유지하는 데 도움이됩니다.
예상 가치 계산을 최적화: 예상 가치 계산 방법은 거래 비용을 고려하고 예상 가치 지표의 효과와 실용성을 향상시키기 위해 움직이는 창을 도입하는 것과 같이 추가로 최적화 될 수 있습니다. 또한 다른 전략 성과 평가 지표는 사용자에게 더 포괄적인 참조를 제공하기 위해 탐구 할 수 있습니다.
이 전략은 이동 평균 크로스오버를 사용하여 시장 트렌드를 결정하고 트렌드가 트렌드에 의한 이익을 포착하는 것처럼 보일 때 적시에 포지션을 설정합니다. 동시에, 전략은 또한 전략의 예상 수익을 다른 시간 스케일에서 표시하기 위해 직관적인 예상 가치 패널을 도입하여 사용자에게 더 많은 의사 결정 참조를 제공합니다. 전략이 범위 제한 시장에서 성능이 좋지 않고 예상 가치 계산이 특정 한계를 가지고 있지만, 더 많은 기술적 지표, 포지션 관리 최적화, 스톱-이익 및 스톱-손실 메커니즘 추가 및 기타 조치를 통해 전략의 위험-이익 비율을 더 향상시킬 수 있으며 변화하는 시장 환경에 더 잘 적응 할 수 있습니다.
/*backtest start: 2023-06-11 00:00:00 end: 2024-06-16 00:00:00 period: 1d basePeriod: 1h 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/ // © ir0nantc2 //@version=5 strategy("Expected Value Panel", overlay=true) // ロングエントリー条件 / Long entry condition longCondition = ta.crossover(ta.sma(close, 14), ta.sma(close, 28)) if (longCondition) strategy.entry("My Long Entry Id", strategy.long) // ショートエントリー条件 / Short entry condition shortCondition = ta.crossunder(ta.sma(close, 14), ta.sma(close, 28)) if (shortCondition) strategy.entry("My Short Entry Id", strategy.short) // ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ // Please copy the code below and paste it into the strategy where you want to display the expected value. // 以下のコードをコピーして期待値を表示させたいストラテジーに貼り付けて下さい。 // ■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■ // 表示選択 / Display selection show_performance = input.bool(true, '期待値ON/OFF (Show Expected Value)', group='Expected Value / ©ir0nantc2') transparency = input.int(50, '透過度 (Transparency)', minval=0, maxval=100, group='Expected Value / ©ir0nantc2') prec = 2 // 背景色 / Background color bg_color(value) => na(value) ? color.new(color.gray, transparency) : value > 0.0 ? color.new(color.green, transparency) : value < 0.0 ? color.new(color.red, transparency) :color.new(color.gray, transparency) // 利益と損失の追跡 / Track profits and losses var float total_monthly_profit = 0.0 var float total_yearly_profit = 0.0 if show_performance new_month = month(time) != month(time[1]) new_year = year(time) != year(time[1]) cur_month_pnl = 0.0, cur_year_pnl = 0.0 eq = strategy.equity bar_pnl = eq / eq[1] - 1 // 月次・年次 期待値 / Monthly & Yearly Expected Value cur_month_pnl := new_month ? 0.0 : (1 + cur_month_pnl[1]) * (1 + bar_pnl) - 1 cur_year_pnl := new_year ? 0.0 : (1 + cur_year_pnl[1]) * (1 + bar_pnl) - 1 // 年次および月次期待値を格納 / Store monthly and yearly expected values var month_pnl = array.new_float(), var month_time = array.new_int() var year_pnl = array.new_float(), var year_time = array.new_int() // 期待値計算の変数 / Variables for expected value calculation var month_wins = array.new_int(), var month_losses = array.new_int() var month_avg_win = array.new_float(), var month_avg_loss = array.new_float() var year_wins = array.new_int(), var year_losses = array.new_int() var year_avg_win = array.new_float(), var year_avg_loss = array.new_float() // 月次および年次期待値の配列更新 / Update arrays for monthly and yearly expected values bool last_computed = false if (not na(cur_month_pnl[1]) and (new_month or barstate.islastconfirmedhistory)) if (last_computed and array.size(month_pnl) > 0) array.pop(month_pnl), array.pop(month_time) array.pop(month_wins), array.pop(month_losses) array.pop(month_avg_win), array.pop(month_avg_loss) array.push(month_pnl, cur_month_pnl[1]), array.push(month_time, time[1]) array.push(month_wins, 0), array.push(month_losses, 0) array.push(month_avg_win, 0.0), array.push(month_avg_loss, 0.0) if (not na(cur_year_pnl[1]) and (new_year or barstate.islastconfirmedhistory)) if (last_computed and array.size(year_pnl) > 0) array.pop(year_pnl), array.pop(year_time) array.pop(year_wins), array.pop(year_losses) array.pop(year_avg_win), array.pop(year_avg_loss) array.push(year_pnl, cur_year_pnl[1]), array.push(year_time, time[1]) array.push(year_wins, 0), array.push(year_losses, 0) array.push(year_avg_win, 0.0), array.push(year_avg_loss, 0.0) last_computed := barstate.islastconfirmedhistory ? true : last_computed // 勝ち取引と負け取引を追跡 / Track winning and losing trades if (strategy.closedtrades > 0 and na(strategy.closedtrades[1]) == false) closed_profit = strategy.netprofit - strategy.netprofit[1] if closed_profit > 0 if array.size(month_wins) > 0 wins = array.get(month_wins, array.size(month_wins) - 1) + 1 avg_win = (array.get(month_avg_win, array.size(month_avg_win) - 1) * (wins - 1) + closed_profit) / wins array.set(month_wins, array.size(month_wins) - 1, wins) array.set(month_avg_win, array.size(month_avg_win) - 1, avg_win) if array.size(year_wins) > 0 wins = array.get(year_wins, array.size(year_wins) - 1) + 1 avg_win = (array.get(year_avg_win, array.size(year_avg_win) - 1) * (wins - 1) + closed_profit) / wins array.set(year_wins, array.size(year_wins) - 1, wins) array.set(year_avg_win, array.size(year_avg_win) - 1, avg_win) else if array.size(month_losses) > 0 losses = array.get(month_losses, array.size(month_losses) - 1) + 1 avg_loss = (array.get(month_avg_loss, array.size(month_avg_loss) - 1) * (losses - 1) + closed_profit) / losses array.set(month_losses, array.size(month_losses) - 1, losses) array.set(month_avg_loss, array.size(month_avg_loss) - 1, avg_loss) if array.size(year_losses) > 0 losses = array.get(year_losses, array.size(year_losses) - 1) + 1 avg_loss = (array.get(year_avg_loss, array.size(year_avg_loss) - 1) * (losses - 1) + closed_profit) / losses array.set(year_losses, array.size(year_losses) - 1, losses) array.set(year_avg_loss, array.size(year_avg_loss) - 1, avg_loss) // 月次テーブル / Monthly table var monthly_table = table(na) if (barstate.islastconfirmedhistory) monthly_table := table.new(position.bottom_right, columns = 14, rows = array.size(year_time) + 1, border_width = 1) table.cell(monthly_table, 0, 0, "", bgcolor = #bbbbbb00) table.cell(monthly_table, 1, 0, "Jan", bgcolor = #bbbbbb) table.cell(monthly_table, 2, 0, "Feb", bgcolor = #bbbbbb) table.cell(monthly_table, 3, 0, "Mar", bgcolor = #bbbbbb) table.cell(monthly_table, 4, 0, "Apr", bgcolor = #bbbbbb) table.cell(monthly_table, 5, 0, "May", bgcolor = #bbbbbb) table.cell(monthly_table, 6, 0, "Jun", bgcolor = #bbbbbb) table.cell(monthly_table, 7, 0, "Jul", bgcolor = #bbbbbb) table.cell(monthly_table, 8, 0, "Aug", bgcolor = #bbbbbb) table.cell(monthly_table, 9, 0, "Sep", bgcolor = #bbbbbb) table.cell(monthly_table, 10, 0, "Oct", bgcolor = #bbbbbb) table.cell(monthly_table, 11, 0, "Nov", bgcolor = #bbbbbb) table.cell(monthly_table, 12, 0, "Dec", bgcolor = #bbbbbb) table.cell(monthly_table, 13, 0, "Year", bgcolor = #bbbbbb) // 年次データの集計 / Collecting yearly data var year_total_pnl = array.new_float() var year_exp_val = array.new_float() for yt = 0 to array.size(year_time) - 1 total_year_wins = 0, total_year_losses = 0 total_year_avg_win = 0.0, total_year_avg_loss = 0.0 total_year_pnl = 0.0 for mt = 1 to 12 idx = -1 for j = 0 to array.size(month_time) - 1 if year(array.get(month_time, j)) == year(array.get(year_time, yt)) and month(array.get(month_time, j)) == mt idx := j break if idx != -1 total_year_pnl := total_year_pnl + array.get(month_pnl, idx) total_year_wins := total_year_wins + array.get(month_wins, idx) total_year_losses := total_year_losses + array.get(month_losses, idx) total_year_avg_win := total_year_avg_win + (array.get(month_avg_win, idx) * array.get(month_wins, idx)) total_year_avg_loss := total_year_avg_loss + (array.get(month_avg_loss, idx) * array.get(month_losses, idx)) total_year_avg_win := total_year_wins > 0 ? total_year_avg_win / total_year_wins : 0.0 total_year_avg_loss := total_year_losses > 0 ? total_year_avg_loss / total_year_losses : 0.0 win_rate = total_year_wins + total_year_losses > 0 ? total_year_wins / (total_year_wins + total_year_losses) : na exp_val = win_rate ? (win_rate * total_year_avg_win) - ((1 - win_rate) * math.abs(total_year_avg_loss)) : na array.push(year_total_pnl, total_year_pnl) array.push(year_exp_val, exp_val) for yt = 0 to array.size(year_time) - 1 table.cell(monthly_table, 0, yt + 1, str.tostring(year(array.get(year_time, yt))), bgcolor = #bbbbbb) y_color = bg_color(array.get(year_exp_val, yt)) value_to_display = na(array.get(year_exp_val, yt)) ? "" : str.tostring(math.round(array.get(year_exp_val, yt) * 100, prec)) table.cell(monthly_table, 13, yt + 1, value_to_display, bgcolor = y_color, text_color=color.new(color.white, 0)) for mt = 0 to array.size(month_time) - 1 m_row = year(array.get(month_time, mt)) - year(array.get(year_time, 0)) + 1 m_col = month(array.get(month_time, mt)) if array.size(month_wins) > mt and array.size(month_losses) > mt and array.size(month_avg_win) > mt and array.size(month_avg_loss) > mt win_rate = array.get(month_wins, mt) / (array.get(month_wins, mt) + array.get(month_losses, mt)) exp_val = (win_rate * array.get(month_avg_win, mt)) - ((1 - win_rate) * math.abs(array.get(month_avg_loss, mt))) m_color = bg_color(exp_val) value_to_display = na(exp_val) ? "" : str.tostring(math.round(exp_val * 100, prec)) table.cell(monthly_table, m_col, m_row, value_to_display, bgcolor = m_color, text_color=color.new(color.white, 0)) else table.cell(monthly_table, m_col, m_row, "", bgcolor = color.new(color.gray, transparency), text_color=color.new(color.white, 0)) // [EOF]