見出し画像

移動平均乖離率エンベロープV0.91本体

//@version=5

//Moving Average Envelope - MA-E- V0.9  終値の移動平均線と上値、下値の乖離率 @issei_tamrua0008 2024-03-28

strategy('Moving Average Envelope - MA-E- V0.91', shorttitle='Moving Average Envelope V0.91',overlay =true) //, format=format.price, precision=2, timeframe="", timeframe_gaps=true

IptPeriod = input.timeframe(defval="",title="マルチタイムフレーム(MT)",

  tooltip = '乖離率 マルチタイム')// マルチタイムフレームのデータを取得



// ▼ ▼ ▼ Smoothed Rate of Change

//input

str_upper = input.string("最高値", options=["最高値","上髭中心","終値"], inline="101")

upper_view = input.bool(true, inline="101")

str_lower = input.string("最安値", options=["最安値","下髭中心","終値"], inline="102")

lower_view = input.bool(true, inline="102")

maPeriod = input(25, title='偏差取得平均線',group=" -  移動平均線乖離率 - -Moving Average Deviation Ratio-")


// 集計用

aggreg = input(100, title='集計回数',group="集計用")

maentropy = input(25, title='緑範囲集計')

rms = input.int(defval=200,minval=0, step=10,title="閾値",tooltip = "2乗累積平方根 又は 絶対値平均足数、最大値を求めるときの閾値とする、雑音除去の精度")

ave_rms = input.string(defval="2乗累積平方根",options=["2乗累積平方根","絶対値平均"],title="閾値の方法",tooltip = "レンジ確認用閾値" + "\n" + "本来2乗累積平方根だけど、最大値を求めすぎて、INができないかも。の緊急措置用")

center_view = input.bool(true, "",inline="104")

sma_center = input.int(25 , inline="104")

center_color = input.color(defval=color.new(color.blue, 0),  title = "" , inline="104",tooltip = "中心位置確認用、利確などに。 計算には使用していない")

long_view = input.bool(true, "",inline="105")

sma_long = input.int(100, inline="105")

long_color = input.color(defval=color.new(color.purple, 0), title = "" , inline="105",tooltip = "トレンド確認用、計算には使用していない")

short_view = input.bool(true, "",inline="106")

sma_short = input.int(3, inline="106")

short_color = input.color(defval=color.new(color.gray, 0), title = "" , inline="106",tooltip = "利確予定ライン" + "\n" + "センターラインとのクロスオーバーでロング、アンダーオーバーでショート利確かも")


Dev0 = input.float(defval=2.0,minval=0.0,maxval=5.0, step=0.1,title="IN用  標準偏差", inline="200",tooltip = "閾値内の偏差") //標準偏差

color_div0 = input.color(defval=color.new(color.green, 0), inline="200")

Dev1 = input.float(defval=2.0,minval=0.0,maxval=5.0, step=0.1,title="偏差内最大  標準偏差", inline="201",tooltip = "閾値外の偏差" + "\n" +

  "0で2乗累積平方根 又は 絶対値平均") //標準偏差

color_div1 = input.color(defval=color.new(color.orange, 0), inline="201")

Dev2 = input.float(defval=4.0,minval=0.0,maxval=5.0, step=0.5,title="損切用 標準偏差", inline="202",tooltip = "0で非表示") //標準偏差

color_div2 = input.color(defval=color.new(color.yellow, 0), inline="202")


rms_bai = input.float(defval=1.0,minval=0.0,maxval=100, step=0.01,title="閾値倍率",tooltip = "閾値の倍率 閾値を使わない場合は100くらいにすればいいかも" + "\n" + "この閾値は描画時の閾値、集計時の閾値とは違う" )

value_view = input.bool(true, "価格表示 取引:白 レンジ外:灰")

value_stay = input.int(10, "価格位置",minval=0,maxval=20, step=1)


threshold_00 = input.bool(true, "閾値を使う",inline="303",group="レンジの確認方法")

threshold_03 = input.bool(true, "閾値 長期線",inline="304",group="レンジの確認方法")

threshold_01 = input.bool(true, "閾値 乖離率平均",inline="304",group="レンジの確認方法")

threshold_02 = input.bool(true, "閾値 偏差",inline="304",group="レンジの確認方法" , tooltip = "レンジの定義で使用する要素" + "\n" +

  "長期の移動平均が第1ライン内にある場合" + "\n" +  

  "乖離率の移動平均が2乗累積平方根内にある場合" + "\n" +

  "乖離率のボリンジャーバンドが2乗累積平方根内にある場合" )


alart = input.bool(true, "アラート",inline="302")

strategy = input.bool(false, "ストラテジー",inline="302")

strategy_son = input.bool(true, "第2ラインで損切",inline="302")

date_s = input.time(timestamp("05 Mar 2024"), "ストラテジー 開始", confirm=true)

date_e = input.time(timestamp("29 Mar 2024"), "ストラテジー 終了", confirm=true)



high_time = request.security(syminfo.tickerid, IptPeriod, high,barmerge.gaps_on,barmerge.lookahead_on)

low_time = request.security(syminfo.tickerid, IptPeriod, low,barmerge.gaps_on,barmerge.lookahead_on)

close_time = request.security(syminfo.tickerid, IptPeriod, close,barmerge.gaps_on,barmerge.lookahead_on)

open_time = request.security(syminfo.tickerid, IptPeriod, open,barmerge.gaps_on,barmerge.lookahead_on)

time_close_time = request.security(syminfo.tickerid, IptPeriod, time_close,barmerge.gaps_on,barmerge.lookahead_on)

bar_index_time = request.security(syminfo.tickerid, IptPeriod, bar_index,barmerge.gaps_on,barmerge.lookahead_on)


float upper = str_upper == "最高値" ? high_time : str_upper == "上髭中心" ?  (high_time + math.max(close_time,open_time)) * 0.5 : close_time

float lower = str_lower == "下髭中心" ?  (low_time + math.min(close_time,open_time)) * 0.5 : close_time


var float[] array_inside_up = array.new_float(maentropy,0.0)

var float[] array_inside_down = array.new_float(maentropy,0.0)

var float[] array_inside_up_count = array.new_float()

var float[] array_inside_down_count = array.new_float()


var float[] array_over_up = array.new_float(aggreg,0.0)

var float[] array_over_down = array.new_float(aggreg,0.0)

var float[] array_over_up_count = array.new_float()

var float[] array_over_down_count = array.new_float()


//deviation rate

sma_up = ta.sma(upper, maPeriod)

sma_low = ta.sma(lower, maPeriod)

rate_upper = upper / sma_up * 100 - 100

rate_lower = lower / sma_low * 100 - 100



ave_upper = ta.sma(math.abs(rate_upper),rms)

ave_lower = ta.sma(-math.abs(rate_lower),rms)

rms_upper = math.sqrt(ta.sma(math.pow(rate_upper, 2),rms))

rms_lower = -math.sqrt(ta.sma(math.pow(rate_lower, 2),rms))


rms_upper := ave_rms == "2乗累積平方根" ?  rms_upper : ave_upper

rms_lower := ave_rms == "2乗累積平方根" ?  rms_lower : ave_lower


// レンジ内用 偏差ラインの内側範囲の最大値

if ta.sma(rate_upper,maentropy) > 0 and rate_upper > 0

    array.insert(array_inside_up_count,0,rate_upper)


if ta.sma(rate_upper,maentropy)[1] > 0 and ta.sma(rate_upper,maentropy) <= 0

    if array.max(array_inside_up_count) < rms_upper and array.max(array_inside_up_count) > 0

        array.insert(array_inside_up,0,array.max(array_inside_up_count))

        array.remove(array_inside_up,array.size(array_inside_up)-1)

        array.clear(array_inside_up_count)

    else

        array.clear(array_inside_up_count)



//レンジ内用 偏差ラインの内側範囲の最小値

if ta.sma(rate_lower,maentropy) < 0 and rate_lower < 0

    array.insert(array_inside_down_count,0,rate_lower)


if ta.sma(rate_lower,maentropy)[1] < 0 and ta.sma(rate_lower,maentropy) >= 0

    if array.min(array_inside_down_count) > rms_lower and array.min(array_inside_down_count) < 0

        array.insert(array_inside_down,0,array.min(array_inside_down_count))

        array.remove(array_inside_down,array.size(array_inside_down)-1)

        array.clear(array_inside_down_count)

    else

        array.clear(array_inside_down_count)


float std_inside_up_ave = 0.0

float std_inside_up_std = 0.0

float std_inside_up_plus0  = 0.0

float std_inside_down_ave = 0.0

float std_inside_down_std = 0.0

float std_inside_down_minu0 = 0.0


// 最大値偏差

if array.get(array_inside_up,maPeriod - 1 ) > 0

    std_inside_up_ave := array.avg(array_inside_up)

    std_inside_up_std := array.stdev(array_inside_up)

    std_inside_up_plus0 := std_inside_up_ave + std_inside_up_std * Dev0


// 最小値偏差

if array.get(array_inside_down,maPeriod - 1 ) < 0

    std_inside_down_ave := array.avg(array_inside_down)

    std_inside_down_std := array.stdev(array_inside_down)

    std_inside_down_minu0 := std_inside_down_ave - std_inside_down_std * Dev0



rms_inside_up_plus0 = math.sqrt(ta.sma(math.pow(std_inside_up_plus0, 2),maPeriod))

rms_inside_down_minu0 = -math.sqrt(ta.sma(math.pow(std_inside_down_minu0, 2),maPeriod))



// 集計用 偏差ラインのオーバーラップ範囲の最大値

if rate_upper > rms_upper

    array.insert(array_over_up_count,0,rate_upper)


if rate_upper[1] > rms_upper[1] and rate_upper <= rms_upper

    array.insert(array_over_up,0,array.max(array_over_up_count))

    array.remove(array_over_up,array.size(array_over_up)-1)

    array.clear(array_over_up_count)


//集計用 偏差ラインのオーバーラップ範囲の最小値 マイナスの値なので絶対値に

if rate_lower < rms_lower

    array.insert(array_over_down_count,0,-rate_lower)


if rate_lower[1] < rms_lower[1] and rate_lower >= rms_lower

    array.insert(array_over_down,0,array.max(array_over_down_count))

    array.remove(array_over_down,array.size(array_over_down)-1)

    array.clear(array_over_down_count)


float std_over_up_ave = 0.0

float std_over_up_std = 0.0

float std_over_up_plus0  = 0.0

float std_over_up_plus1 = 0.0

float std_over_down_ave = 0.0

float std_over_down_std = 0.0

float std_over_down_minu0 = 0.0

float std_over_down_minu1 = 0.0


// 最大値偏差

if array.get(array_over_up,aggreg - 1 ) > 0

    std_over_up_ave := array.avg(array_over_up)

    std_over_up_std := array.stdev(array_over_up)

    std_over_up_plus0 := std_over_up_ave + std_over_up_std * Dev1

    std_over_up_plus1 := std_over_up_ave + std_over_up_std * Dev2


// 最小値偏差

if array.get(array_over_down,aggreg - 1 ) > 0

    std_over_down_ave := -array.avg(array_over_down)

    std_over_down_std := -array.stdev(array_over_down)

    std_over_down_minu0 := std_over_down_ave + std_over_down_std * Dev1

    std_over_down_minu1 := std_over_down_ave + std_over_down_std * Dev2




plot( center_view ? ta.sma((high_time+low_time)*0.5,sma_center) : na,title="Center", color=center_color)

plot( long_view ? ta.sma((high_time+low_time)*0.5,sma_long) : na,title="L_sma", color=long_color)

plot( short_view ? ta.sma((high_time+low_time)*0.5,sma_short) : na,title="S_sma", color=short_color)


bool threshold_1 = true

bool threshold_2 = true

bool threshold_3 = true



// 以下、アラート用閾値

ave_upper := ta.sma(rate_upper,aggreg)

ave_lower := ta.sma(rate_lower,aggreg)


up_plusDev = ave_upper + ta.stdev(rate_upper,aggreg) * 2 // 乖離率の標準偏差 2σ

low_plusDev = ave_lower - ta.stdev(rate_lower,aggreg) * 2 // 乖離率の標準偏差 2σ


rms_up_plusDev = math.sqrt(ta.sma(math.pow(up_plusDev, 2),rms))

rms_low_plusDev = -math.sqrt(ta.sma(math.pow(low_plusDev, 2),rms))


 

// 閾値 長期線がトレンド内に収まっている時をレンジと仮定

if threshold_00 and threshold_03

    if sma_up * (1+std_over_up_plus0/100) < ta.sma((high_time+low_time)*0.5,sma_long) // 上の第一ライン > 長期線

        threshold_3 := false

    if sma_low * (1+std_over_down_minu0/100) > ta.sma((high_time+low_time)*0.5,sma_long) // 下の第一ライン > 長期線

        threshold_3 := false


// 閾値 乖離率平均線 乖離率が平均以上になった時にトレンドと仮定

if threshold_00 and threshold_01

    if ave_upper > rms_upper

        threshold_1 := false

    if ave_lower < rms_lower

        threshold_1 := false


 

// 閾値 乖離率のボリンジャーバンド 株価が大きく動くときに、存在確率も大きく開くので、開く大きさが許容値内かでレンジを判断

if threshold_00 and threshold_02

    if up_plusDev > rms_up_plusDev

        threshold_2 := false

    if low_plusDev < rms_low_plusDev

        threshold_2 := false



// アラート

alertcondition((threshold_3 and threshold_1 and threshold_2) and (high_time > sma_up * (1+std_over_up_plus0/100)) , title="Upper Line Over", message="Upper Line Over" + "\n" + "{{ticker}} {{interval}}分足/ {{time}} " + "\n" + "終値:{{close}} , 出来高:{{volume}} ")

alertcondition((threshold_3 and threshold_1 and threshold_2) and (low_time < sma_low * (1+std_over_down_minu0/100)),  title="Lower Line Over", message="{{ticker}} {{interval}}分足/ {{time}} " + "\n" + "終値:{{close}} , 出来高:{{volume}} ")


if (alart and threshold_3 and threshold_1 and threshold_2) and (high_time > sma_up * (1+std_over_up_plus0/100))

    alert("Upper Line Over" + "\n" + "{{ticker}} {{interval}}分足/ {{time}} " + "\n" + "終値:{{close}} , 出来高:{{volume}} ")

if (alart and threshold_3 and threshold_1 and threshold_2) and (low_time < sma_low * (1+std_over_down_minu0/100))

    alert("Lower Line Over" + "\n" + "{{ticker}} {{interval}}分足/ {{time}} " + "\n" + "終値:{{close}} , 出来高:{{volume}} ")


// ▲▲▲▲ アラート



// ▽▽▽▽ トレンド転換 EXIT ストラテジー

if strategy.position_size > 0 and time_close_time > date_s and time_close_time <= date_e and ta.crossunder(ta.sma((high_time+low_time)*0.5,sma_short),ta.sma((high_time+low_time)*0.5,sma_center))

    strategy.cancel_all()

    strategy.close( id = "str_L" , comment = "close_Long",alert_message="ロング 決済")


if strategy.position_size < 0 and time_close_time > date_s and time_close_time <= date_e  and ta.crossover(ta.sma((high_time+low_time)*0.5,sma_short),ta.sma((high_time+low_time)*0.5,sma_center))

    strategy.cancel_all()

    strategy.close( id = "str_S" , comment = "close_short",alert_message="ショート 決済")


// ▽▽▽▽ トレンド転換 エントリー ストラテジー

strategy.entry("str_L", strategy.long, when=strategy and time_close_time > date_s and time_close_time <= date_e  and (threshold_3 and threshold_1 and threshold_2) and (low_time < sma_low * (1+std_over_down_minu0/100))  and (low_time > sma_low * (1+std_over_down_minu1/100)) ,

   alert_message="Lower Line Over" + "\n" + "{{ticker}} {{interval}}分足/ {{time}} " + "\n" + "終値:{{close}} , 出来高:{{volume}} ")

strategy.entry("str_S", strategy.short, when=strategy and  time_close_time > date_s and time_close_time <= date_e and (threshold_3 and threshold_1 and threshold_2) and (high_time > sma_up * (1+std_over_up_plus0/100)) and (high_time < sma_up * (1+std_over_up_plus1/100)),

   alert_message="トレンド転換 売りENT")

strategy.exit("str_L",  when=strategy_son  and time_close_time > date_s and time_close_time <= date_e  and (close_time <  sma_low * (1 + std_over_down_minu1/100)) ,stop =  sma_low * (1 + std_over_down_minu1/100) )

strategy.exit("str_S",  when=strategy_son  and time_close_time > date_s and time_close_time <= date_e  and (close_time >  sma_up * (1 + std_over_up_plus1/100))  ,stop =  sma_up * (1 + std_over_up_plus1/100) )



// labelを宣言

label label_h2 = na

label label_h1 = na

label label_h0 = na

label label_l0 = na

label label_l1 = na

label label_l2 = na


// 古いものは削除

label.delete( label_h2[1] )

label.delete( label_h1[1] )

label.delete( label_h0[1] )

label.delete( label_l0[1] )

label.delete( label_l1[1] )

label.delete( label_l2[1] )


// labelを描画

label_h2 := label.new( bar_index_time + value_stay ,sma_up * (1 + std_over_up_plus1/100) , style=label.style_none , textcolor= threshold_3 and threshold_1 and threshold_2 ? color_div2 :color.new(color.white, 40),

   text = value_view ? str.tostring(sma_up * (1 + std_over_up_plus1/100) , "#,###.##") : na )

label_h1 := label.new( bar_index_time + value_stay ,sma_up * (1+std_over_up_plus0/100) , style=label.style_none , textcolor= threshold_3 and threshold_1 and threshold_2 ? color_div1 :color.new(color.white, 50),

   text = value_view ? str.tostring(sma_up * (1 + std_over_up_plus0/100) , "#,###.##") : na )

label_h0 := label.new( bar_index_time + value_stay ,sma_up * (1+rms_inside_up_plus0/100) , style=label.style_none , textcolor= threshold_3 and threshold_1 and threshold_2 ? color_div0 :color.new(color.white, 60),

   text = value_view ? str.tostring(sma_up * (1+rms_inside_up_plus0/100) , "#,###.##") : na )

label_l0 := label.new( bar_index_time + value_stay ,sma_low * (1+rms_inside_down_minu0/100) , style=label.style_none , textcolor= threshold_3 and threshold_1 and threshold_2 ? color_div0 :color.new(color.white, 60),

   text = value_view ? str.tostring(sma_low * (1+rms_inside_down_minu0/100) , "#,###.##") : na )

label_l1 := label.new( bar_index_time + value_stay ,sma_low * (1+std_over_down_minu0/100) , style=label.style_none , textcolor= threshold_3 and threshold_1 and threshold_2 ? color_div1 :color.new(color.white, 50),

   text = value_view ? str.tostring(sma_low * (1+std_over_down_minu0/100) , "#,###.##") : na )

label_l2 := label.new( bar_index_time + value_stay ,sma_low * (1 + std_over_down_minu1/100) , style=label.style_none , textcolor= threshold_3 and threshold_1 and threshold_2 ? color_div2 :color.new(color.white, 40),

   text = value_view ? str.tostring(sma_low * (1 + std_over_down_minu1/100) , "#,###.##") : na )




plus0 = plot( Dev0 > 0 ? sma_up * (1+rms_inside_up_plus0/100) : na ,color = threshold_3 and threshold_1 and threshold_2 ? color_div0 : color.new(color.white, 40))

minu0 = plot( Dev0 > 0 ? sma_low * (1+rms_inside_down_minu0/100) : na ,color =threshold_3 and threshold_1 and threshold_2 ? color_div0 : color.new(color.white, 40))

plus1 = plot( Dev1 > 0 ? sma_up * (1+std_over_up_plus0/100) : Dev1 == 0 ? sma_up * (1 + rms_upper/100 * rms_bai) : na,title="Upper", color= threshold_3 and threshold_1 and threshold_2 ? color_div1 : color.new(color.white, 40))

plus2 = plot( Dev2 > 0 ? sma_up * (1+std_over_up_plus1/100)  : na,title="Up_over", color= threshold_3 and threshold_1 and threshold_2 ? color_div2 : color.new(color.white, 40))

minu1 = plot( Dev1 > 0 ? sma_low * (1+std_over_down_minu0/100) : Dev1 == 0 ? sma_up * (1 + rms_lower/100 * rms_bai) :  na,title="Lower", color= threshold_3 and threshold_1 and threshold_2 ? color_div1 : color.new(color.white, 40))

minu2 = plot( Dev2 > 0 ? sma_low * (1+std_over_down_minu1/100)  : na,title="Low_over", color= threshold_3 and threshold_1 and threshold_2 ? color_div2 : color.new(color.white, 40))

// plot( upper_view and ( Dev1 > 0 or Dev2 > 0 ) ? sma_up   : na,title="high", color=color.blue)

// plot( lower_view and ( Dev1 > 0 or Dev2 > 0 ) ? sma_low   : na,title="low", color=color.blue)


fill(plus1, plus2, color = threshold_3 and threshold_1 and threshold_2 ? close_time > sma_up * (1+std_over_up_plus1/100) ? color.new(color.red,0) :  

  high_time > sma_up * (1+std_over_up_plus0/100) ? color.new(color.yellow,20) : na : na, title="upColor")

fill(minu1, minu2, color = threshold_3 and threshold_1 and threshold_2 ? close_time < sma_low * (1+std_over_down_minu1/100) ? color.new(color.red,0) :

  low_time < sma_low * (1+std_over_down_minu0/100) ? color.new(color.yellow,20) : na:na, title="upColor")

この記事が気に入ったらサポートをしてみませんか?