この戦略は,現在のトレンド方向を決定するために移動平均システムを使用し,トレンドに応じてロングまたはショートポジションを作成します.移動平均が上昇すると,ロングへの信頼性が高くなります.移動平均が低下すると,ショートへの信頼性が高くなります.この戦略は主に移動平均システムを利用して,トレンドの傾向方向を決定します.
定期間の移動平均指標として,重度の移動平均 vwma を計算する (デフォルト 400 期).
移動平均値vwmaが上昇しているかどうかを決定し,上昇している場合は長信号上昇傾向を設定し,低下している場合は短信号下落傾向を設定します.
上昇傾向が本当なら,ロングに; 下降傾向が本当なら,ロングを閉じてショートに.
戦略を計算します return bar_pnl と buy & hold return bar_bh 各バーに対して
四半期および年次タイムスタンプに基づいて,四半期戦略リターン (quarter_pnl),年次リターン (year_pnl) と対応するbuy&holdリターン (quarter_bh, year_bh) を計算します.
四半期戦略のリターンを表で表示します.
この戦略の主な利点は以下の通りです.
操作が簡単 移動平均で市場動向を判断し 分かりやすい
引き上げを制御する能力は 傾向を踏むことで 傾向のない市場での損失を減らす
調整可能なパラメータは少ない.主に移動平均周期を調整し,テストし最適化しやすい.
結果を明確に示す直感的な返信表です
比較用の表にbuy&hold return を追加すると,余剰収益を示します.
柔軟なテーブルポジション,他の戦略と簡単に統合.
リスクもあります:
長期的な牛市での低パフォーマンス バイ&ホールと比較して 移動平均期を最適化できます
市場での高リスクは 取引を減らすために フィルター条件を追加します
移動平均は曲線適合能力が悪く,トレンドターニングポイントを見逃す可能性があります.異なる種類の移動平均をテストできます.
ストップ・ロスのメカニズムがないため 巨額の引き下げのリスクがあり ダイナミックなストップ・ロスの設定や ポジションのサイズもできます
シェープ比率や最大引き上げなど リスク指標を追加できます
戦略は以下の側面で最適化できます.
移動平均のパラメータを最適化し 市場体制に基づいて期間を調整します
フィルターを追加して前回の高値を 打ち破るようにします
WMA,DEMAなどなどです.
ストップ・ロスのメカニズムを追加します ダイナミック・ストップやポジション・サイジングなど
シャープ比率や最大抽出量といった メトリックを追加します
MACD,ボリンジャー帯などの他の指標と組み合わせて 傾向を決定します
ポジションのサイズを最適化し 市場の状況に基づいて ポジションを動的に調整します
異なる製品でテストして 最適な応用範囲を見つけます
移動平均取引戦略は,比較的シンプルで直接的なものです. 移動平均を使用してトレンドを決定することによってトレンドをフォローし,トレンドをフォローするトレーダーに適しています. 移動平均システム,ストップロスのメカニズム,ポジションサイジングなど,複雑な市場環境に適応できるように最適化するための大きな余地があります. テーブルデザインは,戦略の返済を購入&保持に比較し,過剰な返済を直感的に示しています. この戦略の枠組みとテーブルデザインは定量トレーダーにいくつかの良い参照を提供することができます.
/*backtest start: 2022-10-23 00:00:00 end: 2023-10-29 00:00:00 period: 1d basePeriod: 1h exchanges: [{"eid":"Futures_Binance","currency":"BTC_USDT"}] */ // This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/ // © Dannnnnnny //@version=4 strategy(title="Quarterly Returns in Strategies vs Buy & Hold", initial_capital= 1000, overlay=true,default_qty_type = strategy.percent_of_equity, default_qty_value = 100, commission_type = strategy.commission.percent, commission_value = 0.1) maLength= input(400) wma= vwma(hl2,maLength) uptrend= rising(wma, 5) downtrend= falling(wma,5) plot(wma) if uptrend strategy.entry("Buy", strategy.long) else strategy.close("Buy")// /////////////////// // QUARTERLY TABLE // enableQuarterlyTable = input(title="Enable Quarterly Return table", type=input.bool, defval=false) enableCompareWithMarket = input(title="Compare with Market Benchmark", type=input.bool, defval=false) table_position = input(title="Table Position", type=input.string, defval='bottom_right', options=['bottom_right','bottom_left','top_right', 'top_left']) precision = 2 new_quarter = ceil(month(time)/3) != ceil(month(time[1])/3) new_year = year(time) != year(time[1]) eq = strategy.equity bar_pnl = eq / eq[1] - 1 bar_bh = (close-close[1])/close[1] cur_quarter_pnl = 0.0 cur_year_pnl = 0.0 cur_quarter_bh = 0.0 cur_year_bh = 0.0 // Current Quarterly P&L cur_quarter_pnl := new_quarter ? 0.0 : (1 + cur_quarter_pnl[1]) * (1 + bar_pnl) - 1 cur_quarter_bh := new_quarter ? 0.0 : (1 + cur_quarter_bh[1]) * (1 + bar_bh) - 1 // Current Yearly P&L cur_year_pnl := new_year ? 0.0 : (1 + cur_year_pnl[1]) * (1 + bar_pnl) - 1 cur_year_bh := new_year ? 0.0 : (1 + cur_year_bh[1]) * (1 + bar_bh) - 1 // Arrays to store Yearly and Quarterly P&Ls var quarter_pnl = array.new_float(0) var quarter_time = array.new_int(0) var quarter_bh = array.new_float(0) var year_pnl = array.new_float(0) var year_time = array.new_int(0) var year_bh = array.new_float(0) end_time = false end_time:= time_close + (time_close - time_close[1]) > timenow or barstate.islastconfirmedhistory if (not na(cur_quarter_pnl[1]) and (new_quarter or end_time)) if (end_time[1]) array.pop(quarter_pnl) array.pop(quarter_time) array.push(quarter_pnl , cur_quarter_pnl[1]) array.push(quarter_time, time[1]) array.push(quarter_bh , cur_quarter_bh[1]) if (not na(cur_year_pnl[1]) and (new_year or end_time)) if (end_time[1]) array.pop(year_pnl) array.pop(year_time) array.push(year_pnl , cur_year_pnl[1]) array.push(year_time, time[1]) array.push(year_bh , cur_year_bh[1]) // Quarterly P&L Table var quarterly_table = table(na) getCellColor(pnl, bh) => if pnl > 0 if bh < 0 or pnl > 2 * bh color.new(color.green, transp = 20) else if pnl > bh color.new(color.green, transp = 50) else color.new(color.green, transp = 80) else if bh > 0 or pnl < 2 * bh color.new(color.red, transp = 20) else if pnl < bh color.new(color.red, transp = 50) else color.new(color.red, transp = 80) if (end_time and enableQuarterlyTable) quarterly_table := table.new(table_position, columns = 14, rows = array.size(year_pnl) + 1, border_width = 1) table.cell(quarterly_table, 0, 0, "", bgcolor = #cccccc) table.cell(quarterly_table, 1, 0, "Q1", bgcolor = #cccccc) table.cell(quarterly_table, 2, 0, "Q2", bgcolor = #cccccc) table.cell(quarterly_table, 3, 0, "Q3", bgcolor = #cccccc) table.cell(quarterly_table, 4, 0, "Q4", bgcolor = #cccccc) table.cell(quarterly_table, 5, 0, "Year", bgcolor = #999999) for yi = 0 to array.size(year_pnl) - 1 table.cell(quarterly_table, 0, yi + 1, tostring(year(array.get(year_time, yi))), bgcolor = #cccccc) y_color = getCellColor(array.get(year_pnl, yi), array.get(year_bh, yi)) table.cell(quarterly_table, 5, yi + 1, enableCompareWithMarket ? tostring(round(array.get(year_pnl, yi) * 100, precision)) + " (" + tostring(round(array.get(year_bh, yi) * 100, precision)) + ")" : tostring(round(array.get(year_pnl, yi) * 100, precision)), bgcolor = y_color, text_color=#bfbfbf) for mi = 0 to array.size(quarter_time) - 1 m_row = year(array.get(quarter_time, mi)) - year(array.get(year_time, 0)) + 1 m_col = ceil(month(array.get(quarter_time, mi)) / 3) m_color = getCellColor(array.get(quarter_pnl, mi), array.get(quarter_bh, mi)) table.cell(quarterly_table, m_col, m_row, enableCompareWithMarket ? tostring(round(array.get(quarter_pnl, mi) * 100, precision)) + " (" + tostring(round(array.get(quarter_bh, mi) * 100,precision)) +")" : tostring(round(array.get(quarter_pnl, mi) * 100, precision)), bgcolor = m_color, text_color=#bfbfbf)