GitHub で見る
Virtual Robot戦略
概要
Virtual Robot戦略は、元のMetaTraderエキスパートアドバイザーのグリッドベース平均化手法を再現します。アルゴリズムは、設定可能なローソク足時間軸上で、ロングとショートの2つの独立した仮想グリッドを維持します。仮想レベル数が定義されたしきい値に達したときだけ、実際の成行注文が送信されます。これにより、仮想レベルが実際のポジション管理を導くMT4動作をシミュレートできます。
取引ロジック
- 仮想ラダー作成: 各確定ローソク足で、戦略は終値と始値を比較します。
- ローソク足が始値より高く閉じた場合、前回ロングレベルからの距離がpipステップを超えると、新しい仮想ロングレベルを追加します。
- ローソク足が低く閉じた場合、同じロジックを仮想ショートラダーに適用します。
- 最初の
VirtualStepper仮想取引は基本ロットを使い、後続レベルはMultiplierでサイズを拡大します。
- 実注文への昇格: 片側に少なくとも
StartingRealOrdersの仮想レベルが存在する(または既存バスケットが少なくとも1pipステップ分ドローダウンする)と、戦略はマーチンゲール乗数(Multiplier * distance / PipStep)で計算した数量の実成行注文を開きます。
- バスケット管理: 戦略は次を追跡します。
- 各側の最後の約定価格と数量。
- オープンバスケットの加重平均(
RealAverageThresholdに応じて実または仮想)。
- テイクプロフィットロジック: 次のいずれかを満たすとポジションを閉じます。
- 最初の仮想注文から価格が
MinTakeProfitPips動く(単一レベルのテイクプロフィット)。
- 複数レベルグリッドで、価格が加重仮想平均プラス/マイナス
AverageTakeProfitPipsへ戻る。
TakeProfitPips / AverageTakeProfitPipsから導かれる単一注文または平均テイクプロフィット水準に到達する。
- ストップロスロジック: 最後に約定した注文から
StopLossPipsを使ってソフトストップを導きます。価格が保護水準を越えるとバスケットを清算します。
- 数量安全性: ロットサイズは銘柄メタデータ(
VolumeStep、MinVolume、MaxVolume)に合わせて正規化され、MaxVolumeで上限が設定されます。
パラメーター
| パラメーター |
説明 |
CandleType |
仮想ラダー形成に使うローソク足系列(既定: 60分足)。 |
StopLossPips |
直近約定注文からのストップ距離(pips)。 |
TakeProfitPips |
単一注文バスケットのテイクプロフィット距離。 |
MinTakeProfitPips |
単一仮想レベルを閉じるために必要な最小利益。 |
AverageTakeProfitPips |
バスケットの加重平均に適用する利益目標。 |
BaseVolume |
最初のグリッド注文の基本ロットサイズ。 |
MaxVolume |
許容される最大ロットサイズ。 |
Multiplier |
平均化エントリー用のロット乗数。 |
RealStepper |
乗数が有効になる前の約定済み実注文数。 |
VirtualStepper |
スケーリング前に基本ロットで埋められる仮想注文数。 |
PipStepPips |
連続するグリッドレベル間の最小逆行幅(pips)。 |
MaxTrades |
片側の実注文数の厳格な上限。 |
StartingRealOrders |
最初の実注文を置く前に必要な仮想注文数。 |
RealAverageThreshold |
この数の注文が約定すると、平均価格を仮想から実へ切り替えます。 |
VisualMode |
MT4入力との互換性のため保持(StockSharpでは効果なし)。 |
実装メモ
- 戦略はネットポジション(StockSharpポートフォリオモデル)を使うため、MT4ヘッジモードのように独立したロング/ショートバスケットを同時に維持できません。両方の仮想ラダーが発動すると、最新シグナルがネットポジションを反転します。
- 元EAのチャート描画は意図的に省略されています。すべての仮想レベルは内部で維持されます。
- 価格ステップは、MT4のpip変換ロジックを反映するため、
Security.PriceStepから導かれます(3桁/5桁FX銘柄には10倍調整)。
- 保護注文は、ブローカー側のストップ/リミット注文を付与する代わりに、ローソク足ハンドラーで価格を監視し、成行決済を送信する形でモデル化されます。
使用のヒント
- pip変換とロット正規化がブローカー規則に合うよう、銘柄メタデータ(
PriceStep、VolumeStep、MinVolume、MaxVolume)を入力してください。
- グリッド距離と乗数が取引予定ブローカーに合うことを確認するため、シミュレーションまたは小さい数量で開始してください。
- マーチンゲールスケーリングの積極性を制御するには、
StartingRealOrdersとRealStepperを調整してください。
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Virtual Robot strategy: RSI mean reversion.
/// Buys when RSI < 40, sells when RSI > 60.
/// </summary>
public class VirtualRobotStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _rsiPeriod;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int RsiPeriod
{
get => _rsiPeriod.Value;
set => _rsiPeriod.Value = value;
}
public VirtualRobotStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_rsiPeriod = Param(nameof(RsiPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("RSI Period", "RSI period", "Indicators");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var rsi = new RelativeStrengthIndex { Length = RsiPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(rsi, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal rsi)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (rsi < 25m && Position <= 0)
{
BuyMarket();
}
else if (rsi > 75m && Position >= 0)
{
SellMarket();
}
}
}
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.Indicators import RelativeStrengthIndex
from StockSharp.Algo.Strategies import Strategy
class virtual_robot_strategy(Strategy):
def __init__(self):
super(virtual_robot_strategy, self).__init__()
self._rsi_period = self.Param("RsiPeriod", 14) \
.SetDisplay("RSI Period", "RSI period", "Indicators")
self._rsi = None
@property
def rsi_period(self):
return self._rsi_period.Value
def OnReseted(self):
super(virtual_robot_strategy, self).OnReseted()
self._rsi = None
def OnStarted2(self, time):
super(virtual_robot_strategy, self).OnStarted2(time)
self._rsi = RelativeStrengthIndex()
self._rsi.Length = self.rsi_period
subscription = self.SubscribeCandles(DataType.TimeFrame(TimeSpan.FromMinutes(30)))
subscription.Bind(self._rsi, self._process_candle)
subscription.Start()
def _process_candle(self, candle, rsi_value):
if candle.State != CandleStates.Finished:
return
if not self._rsi.IsFormed:
return
rsi = float(rsi_value)
if rsi < 25.0 and self.Position <= 0:
self.BuyMarket()
elif rsi > 75.0 and self.Position >= 0:
self.SellMarket()
def CreateClone(self):
return virtual_robot_strategy()