GitHub で見る
AIS5トレードマシン
概要
AIS5 Trade Machine は、MetaTrader 4 エキスパート アドバイザー AIS5TM.mq4 を StockSharp のハイレベル戦略 API に移植します。オリジナル
このプログラムは、2 つの時間枠で市場プロファイルのヒストグラムを構築し、半自動実行コンソールを提供することに重点を置いています。の
StockSharp バージョンは、ティックボリュームの集計から強い価格ゾーンと弱い価格ゾーンを強調表示するというアイデアを維持し、それを
平均トゥルーレンジ (ATR) に基づく適応型リスク制御を備えた自動ブレイクアウト システム。
この戦略は 2 つのローソク足ストリームをサブスクライブします。
- プロファイルの時間枠 (デフォルトは 15 分) で、強いゾーンと弱いゾーンを検出するためにボリュームを蓄積します。
- これらのゾーンから離れた出来高が確認されたブレイクアウトを探す 取引時間枠 (デフォルトは 1 分)。
ポジションは、ATR 比例ストップとスケーラブルなターゲットによって保護されます。体積収縮は早期終了を引き起こし、
MT4 コードにある監視規律。
戦略ロジック
ボリューム ゾーンの検出 (プロファイルの時間枠)
- 終了した各上位タイムフレーム ローソク足は、ティック量の 2 つの単純移動平均 (SMA) を更新します。
- ローソクの出来高が設定可能な乗数 (
Strong Volume Mult) の平均を超えた場合、ローソクは 強いゾーン とラベル付けされます。
ローソク足の終値が直近の強い水準となります。
- ローソクの出来高が設定された分割器で割られた平均を下回る場合、ローソクは 弱いゾーン というラベルが付けられます。
(
Weak Volume Divider)。そのローソク足の終値が直近の弱い水準となります。
- 完成したキャンドルのみが参加します。この戦略では、プロファイル SMA が完全に形成されるまで、ゾーンが無視されます。これは時期尚早を避けるためです。
ウォームアップ期間中の信号。
ブレイクアウトエントリー(取引時間枠)
- 下のタイムフレームは、ボリューム SMA と ATR インジケーターの両方の形成が完了するのを待ちます。
- 長いセットアップでは、ゾーンベースポイントとゾーンベースポイント**の合計により、終値が最新の強いレベルを超える必要があります。
ゾーン ステップ ポイント バッファー (商品の価格ステップを介して変換)。キャンドルはまた、相対的にボリュームスパイクを提供する必要があります
日中平均まで。
- 短いセットアップでは、最新の弱いレベル周辺のロジックが反映され、結合されたバッファを超えたブレークダウンが必要となり、確認が必要になります。
ボリュームの拡大。
- オリジナルの MT4 エキスパートでは、手動コマンドと多次グリッドが許可されていました。 StockSharp ポートは単一位置モデルを保持するため、
ブレイクアウトは、現在のネット ポジションがフラットの場合にのみ実行されます。
出口管理
- エントリー時に、戦略は約定価格を保存し、ATR ベースの保護ストップを計算します (ATR に
ATR Multiplier を乗算し、
ベース ゾーン バッファーによってクランプされます)、停止距離に弱いボリューム ディバイダーを乗算した値としてターゲットを設定します。これにより、
リスクと報酬をボリューム構造に合わせて調整します。
- ポジションがオープンしている間、戦略は終了した各取引ローソク足を監視します。
- 価格が利益目標または保護ストップに達すると、ポジションは直ちにフラット化されます。
- いずれかのレベルに達する前にティックボリュームが弱いボリュームしきい値を下回った場合、取引は回避するために早期に終了します。
非アクティブゾーンに留まります。
- ネットポジションがゼロに戻ると内部状態がリセットされ、次のブレークアウトを最初から評価できるようになります。
パラメーター
- プロファイル キャンドル – ボリューム プロファイルをフィードするキャンドル タイプ (デフォルト: 15 分キャンドル)。
- トレーディングローソク足 – ブレイクアウトとエグジットに使用される下限の時間枠 (デフォルト: 1 分ローソク足)。
- 出来高ルックバック – 出来高SMAとATR期間の両方のローソク足の数。
- Strong Volume Mult – 強いゾーンをマークする平均ボリュームを超える乗数 (MQL の
Parameter.1 にマッピングされます)。
- 弱いボリュームディバイダー – 弱いゾーンをマークし、利益目標のサイズを決定する、平均ボリュームの下のディバイダー(
Parameter.2)。
- ATR 乗数 – 適応停止距離を計算するときに ATR に適用されるスケール係数 (
Parameter.3 にマップ)。
- ゾーン ベース ポイント – ブレークアウトをチェックする前にゾーン レベルに追加されるポイントの最小バッファー (
ZoneBasePoints にマップ)。
- ゾーン ステップ ポイント – エントリーが開始される前にゾーンからの距離を広げるポイント単位の追加のブレイクアウト バッファー
トリガーされます (
ZoneStepPoints にマッピングされます)。
- ボリューム – 基本の
Strategy クラスから継承されます。市場エントリーの注文サイズを定義します。
追加の注意事項
- 証券で指定されていない場合、戦略は自動的にデフォルトの価格ステップ
0.0001 に戻ります。これにより、
ほとんどの FX シンボルと互換性のあるポイントベースのパラメーター。
- すべてのインジケーターの計算は、完全に閉じたバーで機能する MT4 実装と一致する完成したローソク足に依存します。
- オリジナルの EA とは異なり、手動のコントロール パネルやファイルベースのプロファイル ローダーはありません。ゾーンはライブから純粋に再構築されます
ポートを自己完結型に保つためのキャンドル データ。
- StockSharp バージョンには Python 翻訳が含まれていません。
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// AIS5 Trade Machine: EMA breakout with RSI filter and ATR stops.
/// </summary>
public class Ais5TradeMachineStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _emaLength;
private readonly StrategyParam<int> _rsiLength;
private readonly StrategyParam<int> _atrLength;
private decimal _prevClose;
private decimal _entryPrice;
public Ais5TradeMachineStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(8).TimeFrame())
.SetDisplay("Candle Type", "Timeframe.", "General");
_emaLength = Param(nameof(EmaLength), 20)
.SetDisplay("EMA Length", "Trend filter.", "Indicators");
_rsiLength = Param(nameof(RsiLength), 14)
.SetDisplay("RSI Length", "RSI period.", "Indicators");
_atrLength = Param(nameof(AtrLength), 14)
.SetDisplay("ATR Length", "ATR period.", "Indicators");
}
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int EmaLength
{
get => _emaLength.Value;
set => _emaLength.Value = value;
}
public int RsiLength
{
get => _rsiLength.Value;
set => _rsiLength.Value = value;
}
public int AtrLength
{
get => _atrLength.Value;
set => _atrLength.Value = value;
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevClose = 0;
_entryPrice = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevClose = 0;
_entryPrice = 0;
var ema = new ExponentialMovingAverage { Length = EmaLength };
var rsi = new RelativeStrengthIndex { Length = RsiLength };
var atr = new AverageTrueRange { Length = AtrLength };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ema, rsi, atr, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, ema);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal emaVal, decimal rsiVal, decimal atrVal)
{
if (candle.State != CandleStates.Finished)
return;
var close = candle.ClosePrice;
if (_prevClose == 0 || atrVal <= 0)
{
_prevClose = close;
return;
}
if (Position > 0)
{
if (close >= _entryPrice + atrVal * 2.5m || close <= _entryPrice - atrVal * 1.5m || rsiVal > 75)
{
SellMarket();
_entryPrice = 0;
}
}
else if (Position < 0)
{
if (close <= _entryPrice - atrVal * 2.5m || close >= _entryPrice + atrVal * 1.5m || rsiVal < 25)
{
BuyMarket();
_entryPrice = 0;
}
}
if (Position == 0)
{
if (close > emaVal && _prevClose <= emaVal && rsiVal > 50)
{
_entryPrice = close;
BuyMarket();
}
else if (close < emaVal && _prevClose >= emaVal && rsiVal < 50)
{
_entryPrice = close;
SellMarket();
}
}
_prevClose = close;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Strategies import Strategy
from StockSharp.Algo.Indicators import ExponentialMovingAverage, RelativeStrengthIndex, AverageTrueRange
class ais5_trade_machine_strategy(Strategy):
def __init__(self):
super(ais5_trade_machine_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(8))) \
.SetDisplay("Candle Type", "Timeframe.", "General")
self._ema_length = self.Param("EmaLength", 20) \
.SetDisplay("EMA Length", "Trend filter.", "Indicators")
self._rsi_length = self.Param("RsiLength", 14) \
.SetDisplay("RSI Length", "RSI period.", "Indicators")
self._atr_length = self.Param("AtrLength", 14) \
.SetDisplay("ATR Length", "ATR period.", "Indicators")
self._prev_close = 0.0
self._entry_price = 0.0
@property
def CandleType(self):
return self._candle_type.Value
@property
def EmaLength(self):
return self._ema_length.Value
@property
def RsiLength(self):
return self._rsi_length.Value
@property
def AtrLength(self):
return self._atr_length.Value
def OnStarted2(self, time):
super(ais5_trade_machine_strategy, self).OnStarted2(time)
self._prev_close = 0.0
self._entry_price = 0.0
self._ema = ExponentialMovingAverage()
self._ema.Length = self.EmaLength
self._rsi = RelativeStrengthIndex()
self._rsi.Length = self.RsiLength
self._atr = AverageTrueRange()
self._atr.Length = self.AtrLength
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(self._ema, self._rsi, self._atr, self.ProcessCandle).Start()
def ProcessCandle(self, candle, ema_val, rsi_val, atr_val):
if candle.State != CandleStates.Finished:
return
ev = float(ema_val)
rv = float(rsi_val)
av = float(atr_val)
close = float(candle.ClosePrice)
if self._prev_close == 0 or av <= 0:
self._prev_close = close
return
if self.Position > 0:
if close >= self._entry_price + av * 2.5 or close <= self._entry_price - av * 1.5 or rv > 75:
self.SellMarket()
self._entry_price = 0.0
elif self.Position < 0:
if close <= self._entry_price - av * 2.5 or close >= self._entry_price + av * 1.5 or rv < 25:
self.BuyMarket()
self._entry_price = 0.0
if not self.IsFormedAndOnlineAndAllowTrading():
self._prev_close = close
return
if self.Position == 0:
if close > ev and self._prev_close <= ev and rv > 50:
self._entry_price = close
self.BuyMarket()
elif close < ev and self._prev_close >= ev and rv < 50:
self._entry_price = close
self.SellMarket()
self._prev_close = close
def OnReseted(self):
super(ais5_trade_machine_strategy, self).OnReseted()
self._prev_close = 0.0
self._entry_price = 0.0
def CreateClone(self):
return ais5_trade_machine_strategy()