
相対価策とは,取引量異常と価格変動に基づく量化取引策である.この策は,現在の取引量と歴史的な平均取引量との関係を比較して,取引量が異常であるかどうかを判断し,平均実波幅の範囲と組み合わせて,価格が比較的安定した範囲にあるかどうかを判断する.取引量が異常に増加し,価格は比較的安定しているときは,入場信号とみなされる.
相対量策の核心論理は,2つの指標に基づいて判断する.一つは相対量取引,もう一つは価格変動区間である.
まず,過去20サイクルにおける取引量の単純移動平均を計算し,歴史平均取引量とする. そして,倍数パラメータを設定する (例えば1.5倍). 現在の取引量が平均取引量の1.5倍以上である場合,取引量は異常であり,相対量である.
次に,価格変動の指標として,最近14サイクル間の平均真波幅 ((ATR) を計算する.また,平均真波幅の標準差を計算する.現在の真波幅が平均値の正と負の標準差の間にある場合,価格変動は比較的平らな範囲にあると考えます.
上記の2つの条件が同時に満たされると,つまり多行シグナルを発信し,多行を展開する. ポジションの維持過程で,最大低点で減倍ATRをストップポイントとして,最大高点で減倍ATRをストップポイントとして.
相対価策の最大の利点は,異常取引量による価格トレンドを捕捉することです.取引量が激増すると,市場参加者の態度の変化を代表し,これはしばしば価格の突破と新しいトレンドの形成を予兆します.戦略は,取引量と歴史的平均値との関係を比較することによって,取引量の異常のタイミングを効果的に判断できます.
一方,戦略は価格の変動率も考慮し,価格が比較的平穏な時にシグナルが発生させる.これは,激しい変動時に追上した大きな損失のリスクを回避する.また,トレンドは通常相対的に平穏な後に突破を開始するので,利益を得る機会も増加する.
この戦略の最大のリスクは,取引量指標が新しいトレンドを100%決定できないこと,取引量の急増が偽の突破であり,価格がすぐに逆転する可能性があることにある.この場合,戦略は大きな損失を被る.
損失を減らすために,相対量のパラメータを適切に調整し,取引量の異常を判断するより厳格な基準を設定する.または,取引量の増加が取引金額に匹敵するかどうかを判断する取引量分析を増加させるなど,他の判断指標を追加する.
この戦略は以下の点で最適化できます.
取引量異常の信号をより信頼性のあるものにするために,他の指標の判断,例えば,上昇・下降,取引量などを追加します.
ATRパラメータは,異なる株に対して最適化され,価格安定区間をより正確に判断することができる.
機械学習のアルゴリズムを加え,取引量の異常を単純に歴史平均と比較するのではなく,積極的に判断する.
価格変動の予測は,ATRの歴史のみに基づいて判断するのではなく,ディープ・ラーニング・モデルを用いて判断します.
相対量策は,取引量異常を特徴的な信号として捉え,価格安定判断と組み合わせて取引信号を発する.戦略はシンプルで実用的で,株式の異常取引量を追跡する際に有効である.しかし,ある程度の偽信号のリスクもあるため,判断力を高めるために指標をさらに最適化する必要がある.
/*backtest
start: 2022-12-21 00:00:00
end: 2023-12-27 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/
// © DojiEmoji (kevinhhl)
//@version=4
strategy("[KL] Relative Volume + ATR Strategy",overlay=true,pyramiding=1)
ENUM_LONG = "Long"
// Timeframe {
backtest_timeframe_start = input(defval = timestamp("01 Apr 2016 13:30 +0000"), title = "Backtest Start Time", type = input.time)
USE_ENDTIME = input(false,title="Define backtest end-time (If false, will test up to most recent candle)")
backtest_timeframe_end = input(defval = timestamp("01 May 2021 19:30 +0000"), title = "Backtest End Time (if checked above)", type = input.time)
within_timeframe = true
// }
len_volat = input(14,title="Length of ATR to determine volatility")
ATR_volat = atr(len_volat)
avg_ATR_volat = sma(ATR_volat, len_volat)
std_ATR_volat = stdev(ATR_volat, len_volat)
// }
// Trailing stop loss {
ATR_X2_TSL = atr(input(14,title="Length of ATR for trailing stop loss")) * input(2.0,title="ATR Multiplier for trailing stop loss",type=input.float)
TSL_source = low
var stop_loss_price = float(0)
TSL_line_color = color.green, TSL_transp = 100
if strategy.position_size == 0 or not within_timeframe
TSL_line_color := color.black
stop_loss_price := TSL_source - ATR_X2_TSL
else if strategy.position_size > 0
stop_loss_price := max(stop_loss_price, TSL_source - ATR_X2_TSL)
TSL_transp := 0
plot(stop_loss_price, color=color.new(TSL_line_color, TSL_transp))
// }
// Signals for entry {
_avg_vol = sma(volume,input(20, title="SMA(volume) length (for relative comparison)"))
_relative_vol = _avg_vol * input(1.5,title="Multiple of avg vol to consider relative volume as being high",type=input.float)
__lowerOfOpenClose = min(open,close)
_wickRatio_lower = (__lowerOfOpenClose - low) / (high - low)
entry_signal1 = volume > _relative_vol
entry_signal2 = ATR_volat < avg_ATR_volat + std_ATR_volat and ATR_volat > avg_ATR_volat - std_ATR_volat
// }
alert_per_bar(msg)=>
prefix = "[" + syminfo.root + "] "
suffix = "(P=" + tostring(close) + "; atr=" + tostring(ATR_volat) + ")"
alert(tostring(prefix) + tostring(msg) + tostring(suffix), alert.freq_once_per_bar)
// MAIN:
if within_timeframe
if strategy.position_size > 0 and strategy.position_size[1] > 0 and (stop_loss_price/stop_loss_price[1]-1) > 0.005
alert_per_bar("TSL raised to " + tostring(stop_loss_price))
// EXIT :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: // placed before entry, will re-enter if stopped out
exit_msg = close <= strategy.position_avg_price ? "stop loss" : "take profit"
if strategy.position_size > 0 and TSL_source <= stop_loss_price
strategy.close(ENUM_LONG, comment=exit_msg)
// ENTRY :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
if entry_signal1 and entry_signal2// and entry_signal3
entry_msg = strategy.position_size > 0 ? "adding" : "initial"
strategy.entry(ENUM_LONG, strategy.long, comment=entry_msg)
// CLEAN UP:
if strategy.position_size == 0
stop_loss_price := float(0)