Esta estratégia usa o cruzamento de duas médias móveis simples com períodos diferentes para determinar a direção da tendência e entra em negociações quando uma tendência aparece. Ao mesmo tempo, a estratégia também introduz um painel de valor esperado para calcular e exibir os retornos esperados da estratégia em diferentes escalas de tempo, permitindo que os usuários avaliem melhor o desempenho da estratégia. O painel de valor esperado leva em conta indicadores-chave como a taxa de ganho da estratégia, o lucro médio e a perda média durante períodos históricos e apresenta o desempenho da estratégia sob diferentes condições de mercado de forma intuitiva.
O núcleo desta estratégia é usar o cruzamento de duas médias móveis simples com períodos diferentes (14 dias e 28 dias neste exemplo) para determinar as tendências do mercado. Quando a média de curto prazo cruza acima da média de longo prazo de baixo, considera-se que o mercado entrou em uma tendência ascendente, e a estratégia abre uma posição longa. Por outro lado, quando a média de curto prazo cruza abaixo da média de longo prazo de cima, considera-se que o mercado entrou em uma tendência descendente, e a estratégia abre uma posição curta. Desta forma, a estratégia pode se adaptar a diferentes tendências do mercado e estabelecer posições em tempo útil quando as tendências parecem capturar os lucros trazidos pelas tendências.
Além da determinação básica da tendência e da lógica de negociação, a estratégia também introduz um painel de valor esperado para calcular e exibir os retornos esperados da estratégia em diferentes escalas de tempo (mensuais e anuais).
Com base nestes indicadores, pode calcular-se o valor esperado da estratégia nesse período de tempo: Valor esperado = Taxa de ganho × Lucro médio - (1 - Taxa de ganho) × Perda média
Ao exibir os valores esperados de diferentes períodos de tempo sob a forma de um mapa de calor no gráfico, os utilizadores podem ver de uma só vez o desempenho esperado da estratégia em diferentes condições de mercado, compreendendo assim melhor a aplicabilidade e o risco da estratégia.
Forte adaptabilidade às tendências: Ao utilizar cruzamento de médias móveis para determinar tendências, a estratégia pode ajustar as posições em tempo útil sob diferentes tendências de mercado para se adaptar às mudanças do mercado.
Avaliação intuitiva do desempenho: O painel de valor esperado embutido exibe os retornos esperados da estratégia em diferentes períodos de tempo na forma de um mapa de calor, permitindo que os usuários avaliem o desempenho da estratégia sob diferentes condições de mercado de uma só vez.
Consideração dos principais indicadores estatísticos: o cálculo do valor esperado não considera apenas a taxa de ganho da estratégia, mas também integra o impacto do lucro médio e da perda média.
Configurações de parâmetros flexíveis: Os usuários podem definir flexivelmente se desejam exibir o painel de valor esperado e sua transparência de acordo com suas necessidades. Isso permite aos usuários ajustar o efeito de exibição do gráfico de acordo com suas preferências, melhorando a experiência do usuário.
Prejuízo de desempenho nos mercados de intervalo: uma vez que a estratégia depende principalmente das tendências para gerar lucros, a negociação frequente em condições de mercado de intervalo ou de tendência pouco claras pode conduzir a deslizamentos e custos de transação significativos, afetando o desempenho geral da estratégia.
Limitações do cálculo do valor esperado: Embora o painel de valor esperado forneça uma maneira intuitiva de avaliar o desempenho da estratégia, ele ainda se baseia em dados históricos para o cálculo.
Grande impacto da seleção de parâmetros: O desempenho da estratégia depende em grande parte da seleção de períodos de média móvel. Combinações de períodos diferentes podem trazer resultados comerciais completamente diferentes. Se os parâmetros selecionados não puderem se adaptar bem às características do mercado, o desempenho real da estratégia pode desviar significativamente do valor esperado.
Introduzir mais indicadores técnicos: com base nas médias móveis existentes, podem ser considerados outros indicadores técnicos como o MACD e o RSI para determinar melhor a força e a sustentabilidade das tendências, melhorando assim o calendário das entradas e saídas da estratégia.
Otimizar o gerenciamento de posições: atualmente, a estratégia adota uma abordagem de posição fixa quando os sinais de negociação aparecem. Pode ser considerado ajustar dinamicamente as posições com base em fatores como a volatilidade do mercado e a força da tendência para controlar melhor os riscos e aumentar os retornos.
Adicionar mecanismos de stop-profit e stop-loss: Adicionar mecanismos razoáveis de stop-profit e stop-loss à estratégia pode ajudar a estratégia a bloquear os lucros existentes em tempo hábil, limitando as perdas potenciais. Isso ajuda a melhorar a relação risco-recompensa da estratégia e manter um desempenho relativamente constante em vários ambientes de mercado.
Otimizar o cálculo do valor esperado: O método de cálculo do valor esperado pode ser otimizado ainda mais, como considerar os custos de transação e introduzir janelas móveis para melhorar a eficácia e praticidade do indicador de valor esperado.
Esta estratégia determina as tendências do mercado usando crossovers de média móvel e estabelece posições em tempo hábil quando as tendências parecem capturar os lucros trazidos pelas tendências. Ao mesmo tempo, a estratégia também introduz um painel de valor esperado intuitivo para exibir os retornos esperados da estratégia em diferentes escalas de tempo, fornecendo aos usuários mais referências de tomada de decisão. Embora a estratégia possa ter um desempenho ruim em mercados de faixa e o cálculo do valor esperado tenha certas limitações, introduzindo mais indicadores técnicos, otimizando o gerenciamento de posição, adicionando mecanismos de stop-profit e stop-loss e outras medidas, a relação risco-recompensa da estratégia pode ser melhorada, permitindo que ela se adapte melhor aos ambientes de mercado em mudança.
/*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]