yuya_takahashi_

Pine講座㊾ バックテスト|Moving Average Cross and/or Bbands bot の解説

Edukasi
FX:USDJPY   Dollar A.S. / Yen Jepang
今回はCryptoRoxさんの
Moving Average Cross and/or Bbands bot を題材に解説しています。

このストラテジーはアイデアが満載で、
(儲かるかは別として)非常に良いコードだと思います。

利確損切り幅をチャート上に表示する方法など、
個人的にも勉強になる点がいくつかありました。

このストラテジーには以下のような機能があります。

・MAロジックのON/OFF
・BBロジックのON/OFF
(組み合わせることもできる)
・平均足のON/OFF
・検証期間の調整
・ピラミッティングの回数の調整
・取引対象によって取引量を変更
・利益確定幅の指定
・ロスカット幅の指定
・トレーリングストップの指定
(利確、損切り、トレーリングストップがない場合は途転売買)

ただし、注文は成行しか使っていないですね。
Pineスクリプトのストラテジーでは指値、逆指値を使うこともできます。

・どういう動きになるか
・どういう設定をしたら良いのか

あたりを、次回以降、
何回かに分けて解説してみようと思います。

※ 解説はコードの中で

※ コピペする場合は以下の変更を行ってください
[](全角の角括弧)→(半角の角括弧)
(全角スペース)→(半角スペース)

=====
//@version=3
strategy("Moving Average Cross and/or Bbands bot by CryptoRox の解説", overlay=true, pyramiding=1000)

//
// 取引量の設定
////

qty = 1

isALT = input(false, "Altcoin")
if isALT
 qty:= 100000000

isForex = input(false, "Forex")
if isForex
 qty:= 10000


//
// 検証期間の設定
////

testStartYear = input(1, "Backtest Start Year")
testStartMonth = input(8, "Backtest Start Month")
testStartDay = input(25, "Backtest Start Day")
testPeriodStart = timestamp(testStartYear,testStartMonth,testStartDay,0,0)

testStopYear = input(999999, "Backtest Stop Year")
testStopMonth = input(9, "Backtest Stop Month")
testStopDay = input(26, "Backtest Stop Day")
testPeriodStop = timestamp(testStopYear,testStopMonth,testStopDay,0,0)

testPeriod() =>
 time >= testPeriodStart and time <= testPeriodStop ? true : false


//
// ローソク足と平均足を切り替える
////

isHA = false

data = isHA ? heikinashi(tickerid) : tickerid

o = security(data, period, open)
h = security(data, period, high)
l = security(data, period, low)
c = security(data, period, close)

// ローソク足を描画
col = c > o ? green : red
plotcandle(o, h, l, c, "Heiken Ashi", col, black)


//
// エントリーの判断
////

// 買いシグナルと売りシグナルを入れる変数
long = na
short = na

// MAだけのロジック(設定ONのとき)
////

// ON/OFF と 計算用の数値の設定
useMA = input(true, "Use Moving Average Cross")
ma1Input = input(50, "Moving Average 1")
ma2Input = input(200, "Moving Average 2")

// MAの算出
ma1 = sma(c, ma1Input)
ma2 = sma(c, ma2Input)

// 描画用の計算値の入れ物
ma1Plot = na
ma2Plot = na

// MAロジックの根拠(買いシグナル、売りシグナル)
maLong = c > ma1 and ma1 > ma2
maShort = c < ma1 and ma1 < ma2

// MAロジックON → データの格納とシグナルの判断
if useMA
 ma1Plot := ma1
 ma2Plot := ma2
 long := maLong
 short := maShort

// 描画(MAロジックOFFのときは描画されない)
plot(ma1Plot, "ma1", blue)
plot(ma2Plot, "ma2", orange)

// ボリンジャーバンドロジック
////

// ON/OFF と 計算用の数値の設定
useBbands = input(false, "Use Bollinger Bands")
bblength = input(20, minval=1)
mult = input(2.0, minval=0.001, maxval=50)

// テクニカルの算出
basis = sma(c, bblength)
dev = mult * stdev(c, bblength)
upper = basis + dev
lower = basis - dev

// 描画用の計算値の入れ物
basisPlot = na
p1Plot = na
p2Plot = na

// BBロジックON → データの格納とシグナルの判断
if useBbands
 long := c < lower
 short := c > upper
 basisPlot := basis
 p1Plot := upper
 p2Plot := lower

// BBロジックとMAロジックがON → シグナルの判断(上書く)
if useBbands and useMA
 long := c < lower and maLong
 short := c > upper and maShort

// 描画(BBロジックがOFFのときは描画されない)
plot(basisPlot, color=red)
p1 = plot(p1Plot, color=blue)
p2 = plot(p2Plot, color=blue)
fill(p1, p2)


//
// 売買のロジック
////

// エントリーシグナルの数をカウントする
sectionLongs = 0
sectionLongs := nz(sectionLongs[1])
sectionShorts = 0
sectionShorts := nz(sectionShorts[1])

if long
 sectionLongs := sectionLongs + 1
 sectionShorts := 0

if short
 sectionLongs := 0
 sectionShorts := sectionShorts + 1

// ピラミッティングの設定値
pyrl = input(1, "Pyramiding less than") // If your count is less than this number
pyre = input(0, "Pyramiding equal to") // If your count is equal to this number
pyrg = input(1000000, "Pyramiding greater than") // If your count is greater than this number

// シグナルとピラミッティングの制限を確認
longCondition = long and sectionLongs <= pyrl or long and sectionLongs >= pyrg or long and sectionLongs == pyre
shortCondition = short and sectionShorts <= pyrl or short and sectionShorts >= pyrg or short and sectionShorts == pyre

// エントリーの価格を記録する
last_open_longCondition = na
last_open_shortCondition = na
last_open_longCondition := longCondition ? close : nz(last_open_longCondition[1])
last_open_shortCondition := shortCondition ? close : nz(last_open_shortCondition[1])

// ピラミッティングの制限を含めたエントリーのシグナルを数える
sectionLongConditions = 0
sectionLongConditions := nz(sectionLongConditions[1])
sectionShortConditions = 0
sectionShortConditions := nz(sectionShortConditions[1])

if longCondition
 sectionLongConditions := sectionLongConditions + 1
 sectionShortConditions := 0

if shortCondition
 sectionLongConditions := 0
 sectionShortConditions := sectionShortConditions + 1

// 最後のエントリーの時間を記録
last_longCondition = na
last_shortCondition = na
last_longCondition := longCondition ? time : nz(last_longCondition[1])
last_shortCondition := shortCondition ? time : nz(last_shortCondition[1])

in_longCondition = last_longCondition > last_shortCondition
in_shortCondition = last_shortCondition > last_longCondition

// エントリー後の最高値、最安値などの記録
last_high = na
last_low = na
last_high_short = na
last_low_short = na
last_high := not in_longCondition ? na : in_longCondition and (na(last_high[1]) or high > nz(last_high[1])) ? high : nz(last_high[1])
last_high_short := not in_shortCondition ? na : in_shortCondition and (na(last_high[1]) or high > nz(last_high[1])) ? high : nz(last_high[1])
last_low := not in_shortCondition ? na : in_shortCondition and (na(last_low[1]) or low < nz(last_low[1])) ? low : nz(last_low[1])
last_low_short := not in_longCondition ? na : in_longCondition and (na(last_low[1]) or low < nz(last_low[1])) ? low : nz(last_low[1])

// トレーリングストップの設定
////

// 設定
isTS = input(false, "Trailing Stop")
tsi = input(0, "Activate Trailing Stop Price") / qty
ts = input(0, "Trailing Stop") / qty
// 判断
long_ts = isTS and not na(last_high) and crossunder(low, last_high - ts) and longCondition == 0 and high >= (last_open_longCondition + tsi)
short_ts = isTS and not na(last_low) and crossover(high, last_low + ts) and shortCondition == 0 and low <= (last_open_shortCondition - tsi)
// 描画
tsColor = isTS and in_longCondition and last_high >= (last_open_longCondition + tsi) ? blue : isTS and in_shortCondition and last_low <= (last_open_shortCondition - tsi) ? blue : white
tsiColor = isTS and in_longCondition and last_high >= (last_open_longCondition + tsi) ? white : isTS and in_shortCondition and last_low <= (last_open_shortCondition - tsi) ? white : blue
plot(isTS and in_longCondition ? last_open_longCondition + tsi : na, "Long Trailing", tsiColor, style=3, linewidth=2)
plot(isTS and in_shortCondition ? last_open_shortCondition - tsi : na, "Short Trailing", tsiColor, style=3, linewidth=2)
plot(isTS and in_longCondition and last_high >= (last_open_longCondition + tsi) ? last_high - ts : na, "Long Trailing", tsColor, style=2, linewidth=2)
plot(isTS and in_shortCondition and last_low <= (last_open_shortCondition - tsi) ? last_low + ts : na, "Short Trailing", tsColor, style=2, linewidth=2)

// 利益確定の設定
////

// 設定
isTP = input(false, "Take Profit")
tp = input(0, "Take Profit") / qty
// シグナル
long_tp = isTP and crossover(high, last_open_longCondition + tp) and longCondition == 0
short_tp = isTP and crossunder(low, last_open_shortCondition - tp) and shortCondition == 0
// 描画
tpColor = isTP and in_longCondition ? purple : isTP and in_shortCondition ? purple : white
plot(isTP and in_longCondition and last_high < last_open_longCondition + tp ? last_open_longCondition + tp : na, "Long TP", tpColor, style=3, linewidth=2)
plot(isTP and in_shortCondition and last_low > last_open_shortCondition - tp ? last_open_shortCondition - tp : na, "Short TP", tpColor, style=3, linewidth=2)

// ロスカットの設定
////

// 設定
isSL = input(false, "Stop Loss")
sl = input(0, "Stop Loss") / qty
// 判断
long_sl = isSL and crossunder(low, last_open_longCondition - sl) and longCondition == 0
short_sl = isSL and crossover(high, last_open_shortCondition + sl) and shortCondition == 0
// 描画
slColor = isSL and in_longCondition and last_low_short > last_open_longCondition - sl ? red : isSL and in_shortCondition and last_high_short < last_open_shortCondition + sl ? red : white
plot(isSL and in_longCondition ? last_open_longCondition - sl : na, "Long SL", slColor, style=3, linewidth=2)
plot(isSL and in_shortCondition ? last_open_shortCondition + sl : na, "Short SL", slColor, style=3, linewidth=2)

// 仮想マージンコール
////

isMargin = input(false, "Margin Call")
leverage = input(1, "Leverage")
long_call = last_open_longCondition - (0.8 + 0.2 * (1/leverage)) / leverage * last_open_longCondition
short_call = last_open_shortCondition + (0.78 + 0.2 * (1/leverage)) / leverage * last_open_shortCondition
long_call_signal = isMargin and crossunder(low, long_call)
short_call_signal = isMargin and crossunder(high, short_call)
marginColor = isMargin and in_longCondition and last_low_short > long_call ? black : isMargin and in_shortCondition and last_high_short < short_call ? black : white
plot(isMargin and in_longCondition ? long_call : na, "Long Margin", marginColor, style=3, linewidth=2)
plot(isMargin and in_shortCondition ? short_call : na, "Short Margin", marginColor, style=3, linewidth=2)

// ポジションの平均価格の算出
////

totalLongs = 0.0
totalLongs := nz(totalLongs[1])
totalShorts = 0.0
totalShorts := nz(totalShorts[1])
averageLongs = 0.0
averageLongs := nz(averageLongs[1])
averageShorts = 0.0
averageShorts := nz(averageShorts[1])

if longCondition
 totalLongs := totalLongs + last_open_longCondition
 totalShorts := 0.0

if shortCondition
 totalLongs := 0.0
 totalShorts := totalShorts + last_open_shortCondition

averageLongs := totalLongs / sectionLongConditions
averageShorts := totalShorts / sectionShortConditions

// 利益・損失幅の描画
longProfit = averageLongs > 0 and close >= averageLongs ? green : red
shortProfit = averageShorts > 0 and close <= averageShorts ? green : red
plot1 = plot(averageLongs > 0 ? averageLongs : na, color=white)
plot2 = plot(close, color=white)
plot3 = plot(averageShorts > 0 ? averageShorts : na, color=white)
fill(plot1, plot2, color=longProfit, transp=50)
fill(plot2, plot3, color=shortProfit, transp=50)




//Enable this to double your order size every time your pyramid on top of an existing position. (Martingale strategy)
// useMartin = input(true, "Martingale")

// longMartin = 0
// longMartin := nz(longMartin[1])
// shortMartin = 0
// shortMartin := nz(shortMartin[1])

// // Check to see if this is our first order, set the order qty to 1
// if longCondition and sectionLongConditions == 1
//  longMartin := longMartin + 1
//  shortMartin := 0
// if shortCondition and sectionShortConditions == 1
//  longMartin := 0
//  shortMartin := shortMartin + 1

// confirm that this order is being added to an existing order
// if longCondition and sectionLongConditions > 1
//  longMartin := longMartin * 2
// if shortCondition and sectionShortConditions > 1
//  shortMartin := shortMartin * 2

// 決済シグナルの判断(利確 or 損切り or トレーリングストップ or 途転)
////

long_close = long_tp or long_sl or long_ts or long_call_signal ? 1 : 0
short_close = short_tp or short_sl or short_ts or short_call_signal ? 1 : 0

// 決済時間の記録
last_long_close = na
last_short_close = na
last_long_close := long_close ? time : nz(last_long_close[1])
last_short_close := short_close ? time : nz(last_short_close[1])

// エントリーと決済の時間を確認
if long_close and last_long_close[1] > last_longCondition
 long_close := 0
if short_close and last_short_close[1] > last_shortCondition
 short_close := 0

// 検証期間内ならトレード
if testPeriod()
 strategy.entry("Long", strategy.long, qty=qty, when=longCondition)
 strategy.entry("Short", strategy.short, qty=qty, when=shortCondition)

 strategy.close("Long", when=long_close)
 strategy.close("Short", when=short_close)
=====
Komentar:
次の講座

小次郎講師公式インジケーターのお申込
bit.ly/2vdSV4Q

小次郎講師のLINE@
bit.ly/2VZQFu3

小次郎講師のチャート情報局
bit.ly/2GvLAEp
Pernyataan Penyangkalan

Informasi dan publikasi tidak dimaksudkan untuk menjadi, dan bukan merupakan saran keuangan, investasi, perdagangan, atau rekomendasi lainnya yang diberikan atau didukung oleh TradingView. Baca selengkapnya di Persyaratan Penggunaan.