FO SMA CROSS Strategy Templateコード全文
//@version=6
import kabutech/FO_Util/33 as util
strategy(
"FO SMA CROSS Strategy Template",
overlay=true,
initial_capital=10000000,
default_qty_value=1
)
// ====================
// ■ 市場設定
// ====================
marketTypeInput = input.string(
"JP_FUT",
title="市場タイプ",
options=["JP_STOCK","JP_FUT"],
tooltip="市場に応じて発注禁止時間(昼休み・引け前)を自動制御します"
)
// ====================
// ■ インジケータ設定
// ====================
maType = input.string(
"SMA",
title="移動平均タイプ",
options=["SMA", "EMA"],
tooltip="SMA: 単純移動平均\nEMA: 指数平滑移動平均"
)
// SMA
maShortLen = input.int(5, "短期MA期間")
maLongLen = input.int(25, "長期MA期間")
// クロス後猶予
barsAfterCross = input.int(1, "クロス後エントリー許可本数", minval=0, maxval=20)
//====================================================
// ■ VOLUME FILTER(出来高フィルター)
//====================================================
volLength = input.int(20, "出来高フィルター (0:無効)", group="エントリーフィルター設定")
volMultiplier = input.float(1.2, "出来高倍率", step=0.1, inline="vol", tooltip="平均×倍率【以上】の出来高(クライマックス)で許可", group="エントリーフィルター設定")
volLookback = input.int(3, "Lookback", minval=1, inline="vol", group="エントリーフィルター設定")
//====================================================
// ■ WICK FILTER(ヒゲ判定)
//====================================================
wickRatio = input.float(0.0, "Wick Ratio (0:off)", step=0.1, inline="wick", maxval=1.0,
tooltip="ローソク足のレンジに対するヒゲの割合(0.0〜1.0)。\n0で無効化。例)0.5 = レンジの50%以上がヒゲ", group="エントリーフィルター設定")
wickLookback = input.int(3, "Lookback", minval=1, inline="wick",
tooltip="直近何本以内に指定したヒゲが出現したかを判定します。\n1なら現在の足のみ。", group="エントリーフィルター設定")
//====================================================
// ■ ADX FILTER(トレンド強度フィルター)
//====================================================
dmiMode = input.string(
"OFF",
"DMI方向モード",
options=["OFF", "TREND", "REVERSAL"],
inline="dmi_1"
)
dmiAdxLength = input.int(14, "DMI/ADX 共通期間", inline="dmi_1", group="", minval=0)
adxThresh = input.int(25, "ADX 閾値 (0でADX無効)", inline="dmi_2", group="", minval=0)
adxFilterInput = input.string("以下", "ADX 条件", options=["以上", "以下"], inline="dmi_2", group="",
tooltip="以上: ADXが閾値以上の時にエントリー(トレンド追随)\n以下: ADXが閾値以下の時にエントリー(レンジ・保ち合い)")
//====================================================
// ■ CHOPPINESS FILTER(レンジ判定フィルター)
//====================================================
chopLength = input.int(0, "Chop期間 (0で無効)", inline="")
chopThresh = input.float(61.8, "Chop閾値", inline="Chop")
chopFilterInput = input.string("以上", "Chop 条件", options=["以上", "以下"], inline="Chop", group="",
tooltip="以上: Chopが閾値以上の時にエントリー(もみ合い・レンジ)\n以下: Chopが閾値以下の時にエントリー(強いトレンド中)")
//====================================================
// ■ 出口管理(ATR)
//====================================================
atrLength = input.int(14, "ATR期間", group="出口管理")
atrLimitMult = input.float(1.5, "固定利確/追従発動倍率", step=0.1, group="出口管理")
atrStopMult = input.float(2.0, "損切り倍率", step=0.1, group="出口管理")
trailAtrMult = input.float(0.0, "トレール幅 (0で固定利確)", step=0.1, group="出口管理")
maxStopPerc = input.float(2.0, "最大損切り(%)", step=0.1, group="出口管理")
//====================================================
// ■ SESSION管理
//====================================================
useSessionFilter = input.bool(true, "エントリー時間制限", group="SESSION")
startHour = input.int(9, "開始", inline="s", group="SESSION")
startMinute = input.int(0, " ", inline="s", group="SESSION")
endHour = input.int(14, "終了", inline="e", group="SESSION")
endMinute = input.int(30, " ", inline="e", group="SESSION")
useSessionClose = input.bool(true, "引け決済", group="SESSION")
closeHour = input.int(15, "時", inline="c", group="SESSION")
closeMinute = input.int(0, "分", inline="c", group="SESSION")
// ====================
// ■ 指標計算
// ====================
f_ma(src, len, type) =>
type == "EMA" ? ta.ema(src, len) : ta.sma(src, len)
maShort = f_ma(close, maShortLen, maType)
maLong = f_ma(close, maLongLen, maType)
atrValue = ta.atr(atrLength)
safeATR = math.max(atrValue, syminfo.mintick)
// ■ クロス判定
goldenCross = ta.crossover(maShort, maLong)
deathCross = ta.crossunder(maShort, maLong)
barsFromGolden = ta.barssince(goldenCross)
barsFromDeath = ta.barssince(deathCross)
longTrigger = (
barsAfterCross == 0
? goldenCross
: (barsFromGolden >= 0 and barsFromGolden <= barsAfterCross)
) and close > open
shortTrigger = (
barsAfterCross == 0
? deathCross
: (barsFromDeath >= 0 and barsFromDeath <= barsAfterCross)
) and close < open
// ====================
// 各種フィルター
// ====================
// 出来高フィルター
volOK = util.f_volumeFilter(volLength, volMultiplier, volLookback, "above")
// ヒゲフィルター
wickLongOK = util.f_wickFilter(wickRatio, -1, wickLookback)
wickShortOK = util.f_wickFilter(wickRatio, 1, wickLookback)
// エントリー時間制御
allowEntry = util.f_allowEntry(useSessionFilter, startHour, startMinute, endHour, endMinute, marketTypeInput)
// DMI/ADXフィルター
adxFilterMode = (adxFilterInput == "以上") ? "above" : "below"
[dmiLongMode, dmiShortMode, adxOK] = util.f_dmiAdxFilter(dmiAdxLength, dmiMode != "OFF", adxThresh, adxFilterMode)
// DMIモード切り替え
longDmiOK = dmiMode == "REVERSAL" ? dmiShortMode : dmiLongMode
shortDmiOK = dmiMode == "REVERSAL" ? dmiLongMode : dmiShortMode
// CHOPフィルター
chopFilterMode = (chopFilterInput == "以上") ? "above" : "below"
[chopVal, chopOK] = util.f_chopFilter(chopLength, chopThresh, chopFilterMode)
// フィルター統合
allFilters = adxOK and chopOK and volOK and allowEntry
// ====================
// ■ シグナル
// ====================
longSignal = longTrigger and wickLongOK and longDmiOK and allFilters and barstate.isconfirmed
shortSignal = shortTrigger and wickShortOK and shortDmiOK and allFilters and barstate.isconfirmed
// ====================
// ■ エントリー
// ====================
util.f_executeEntry(longSignal, shortSignal)
//====================================================
// EXIT LOGIC(出口設計)
//====================================================
var float highest = na
var float lowest = na
[longStop, shortStop, longLimit, shortLimit, _highest, _lowest] = util.f_calcATRExit(
strategy.position_avg_price,
atrValue,
highest,
lowest,
high[1],
low[1],
trailAtrMult,
atrStopMult,
atrLimitMult,
strategy.position_size > 0,
strategy.position_size < 0,
maxStopPerc
)
highest := _highest
lowest := _lowest
strategy.exit("CLOSE_LONG", from_entry="LONG", stop=longStop, limit=longLimit)
strategy.exit("CLOSE_SHORT", from_entry="SHORT", stop=shortStop, limit=shortLimit)
// ====================
// ■ 引け決済
// ====================
util.f_executeSessionClose(useSessionClose, closeHour, closeMinute, marketTypeInput)
// ====================
// ■ 描画
// ====================
plot(maShort, color=color.blue, title="Short SMA")
plot(maLong, color=color.red, title="Long SMA")
//====================================================
// STATUS DASHBOARD
//====================================================
var table board = table.new(position.bottom_right, 2, 4, bgcolor=color.new(color.black, 70))
// ヘッダー
table.cell(board, 0, 0, "項目", text_color=color.white, bgcolor=color.gray)
table.cell(board, 1, 0, "現在の状態", text_color=color.white, bgcolor=color.gray)
//----------------------------------
// ■ 市場
//----------------------------------
table.cell(board, 0, 1, "市場", text_color=color.white)
table.cell(board, 1, 1, marketTypeInput, text_color=color.yellow)
//----------------------------------
// ■ ポジション
//----------------------------------
posStr = strategy.position_size > 0 ? "LONG" : strategy.position_size < 0 ? "SHORT" : "FLAT"
posCol = strategy.position_size > 0 ? color.lime : strategy.position_size < 0 ? color.red : color.white
table.cell(board, 0, 2, "ポジション", text_color=color.white)
table.cell(board, 1, 2, posStr, text_color=posCol)
//----------------------------------
// ■ 利確・損切り目安
//----------------------------------
longActive = strategy.position_size > 0
shortActive = strategy.position_size < 0
tpStr =
longActive ? str.tostring(longLimit, format.mintick) :
shortActive ? str.tostring(shortLimit, format.mintick) :
"-"
slStr =
longActive ? str.tostring(longStop, format.mintick) :
shortActive ? str.tostring(shortStop, format.mintick) :
"-"
table.cell(board, 0, 3, "出口目安", text_color=color.white)
table.cell(board, 1, 3, "利確: " + tpStr + "\n損切: " + slStr, text_color=color.white)