ホーム
/
戦略のサンプル
GitHub で見る
ランダムフル戦略で
概要
At Random Full 戦略 は、MetaTrader 5 エキスパート アドバイザーの「At Random Full」を忠実に変換したものです。それは、
同じ資金管理スイッチを公開しながら、ランダム ジェネレーターに基づいて取引を開始するというオリジナルのアイデア: 方向性
フィルター、グリッド間隔、オプションの時間ウィンドウ、平均化のオン/オフ切り替え。 StockSharp ポートは高レベルの API を使用します。
したがって、意思決定ループ全体は、キャンドルの定期購入と保護命令の標準の StartProtection ヘルパーによって駆動されます。
取引ロジック
終了したキャンドルごとに、戦略は取引が許可されていることを確認します (セッション フィルター、ポートフォリオの状態、およびオプション)
「1 つの位置のみ」フラグ)。
擬似ランダム ジェネレーターは、ロング エントリかショート エントリかを決定します。 ReverseSignals パラメータは結果を次のように反転できます。
MQL リバース モードをエミュレートします。
方向フィルター (TradeMode) は不要な信号をブロックします。このコードは、1 回の取引ごとに元の EA ルールも適用します。
最新のシグナルのローソク足のオープン時間を記憶して、各方向のバーを表示します。
グリッド管理オプションは、MetaTrader の動作を反映します。
MaxPositions は、サイドごとの平均エントリ数を上限とします。
MinStepPoints では、連続するエントリー間に最小距離 (証券価格ステップを使用して価格に変換) が必要です。
CloseOpposite は、新しい取引が送信される前に、既存の逆エクスポージャーを強制的にクローズします。
成行注文は、OrderVolume で定義された正規化された数量で、BuyMarket / SellMarket を通じて発行されます。
ポジションとリスクの管理
StartProtection は、MetaTrader の入力に一致するストップロス注文と利益確定注文を添付します。 TrailingStopPoints の場合
0 より大きい場合、組み込みの StockSharp トレーリング モードが有効になります。パラメータ TrailingActivatePoints と
TrailingStepPoints は価格距離に変換され、透明性のためにログに記録されますが、実際の末尾は
プラットフォーム。
すべてのボリューム計算では、MQL ヘルパー ルーチンとまったく同様に、交換メタデータ (最小値、最大値、ステップ) が考慮されます。
時間制御は、スクリプトから InpTimeControl ブロックをエミュレートします。有効にすると、設定された範囲内でのみ取引が許可されます。
[SessionStart, SessionEnd] ウィンドウ;夜間のセッションもサポートされています。
パラメーター
パラメータ
説明
デフォルト
CandleType
意思決定ループをスケジュールするために使用されるキャンドル シリーズ。
15 minute timeframe
OrderVolume
ロット単位の基本成行注文量。
0.1
MaxPositions
方向ごとの平均エントリの最大数 (0 = 無制限)。
5
MinStepPoints
MetaTrader ポイントで表されるエントリ間の最小距離。
150
StopLossPoints
ポイント単位のストップロス距離。
150
TakeProfitPoints
テイクプロフィット距離(ポイント単位)。
460
TrailingActivatePoints
トレーリングが有効な場合に情報提供のために記録される利益のしきい値 (ポイント単位)。
70
TrailingStopPoints
トレーリング ストップの距離が StartProtection に渡されました。
250
TrailingStepPoints
後続調整の間のステップ。アクティベーション距離とともに記録されます。
50
OnlyOnePosition
現在のネットポジションがクローズされるまで、新しい取引をブロックします。
false
CloseOpposite
取引を開始する前に反対のエクスポージャーをクローズします。
false
ReverseSignals
ランダムな決定を反転して、買いが売りになり、またその逆になります。
false
UseTimeControl
取引セッション時間フィルターを有効にします。
false
SessionStart
UseTimeControl が true の場合のセッション開始時刻 (両端を含む)。
10:01
SessionEnd
UseTimeControl が true の場合のセッション終了時刻 (両端を含む)。
15:02
Mode
許可された取引方向 (Both、BuyOnly、SellOnly)。
Both
RandomSeed
擬似乱数ジェネレーターのオプションの決定性シード (0 = 環境ティック数)。
0
実装メモ
すべてのコメントは英語で書かれており、コードはリポジトリのガイドラインに準拠してタブ インデントを使用しています。
ローソク足の処理は SubscribeCandles().Bind(...) に依存しており、EA のように、終了したバーごとにロジックが 1 回実行されることが保証されます。
この戦略は、平均化中でも最小間隔制約を適用するために、最後の売買約定価格を追跡します。
ログ ステートメントは、元のスクリプトによって出力された詳細な診断を反映しています。すべてのエントリは、選択された方向を通知します。
エントリ価格、ボリューム、および起動時のトレーリング構成。
使用のヒント
取引シグナルはランダムであるため、この戦略はインフラストラクチャのテストやリスク管理の実証に最適です。
OrderVolume、StopLossPoints、TakeProfitPoints を調整して、銘柄のティック サイズとボラティリティに合わせます。
取引する計画を立てます。
EA が特定のセッション (ロンドンやニューヨークのセッションなど) 中にのみ動作する必要がある場合は、UseTimeControl を有効にします。
最適化の実行中に RandomSeed を使用して、ランダムな決定の再現可能なシーケンスを実現します。
using System;
using Ecng.Common;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Simplified from "At random Full" MetaTrader expert.
/// Randomly opens long or short positions with grid spacing and position limits.
/// </summary>
public class AtRandomFullStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _maxPositions;
private readonly StrategyParam<int> _randomSeed;
private Random _random;
private decimal _lastEntryPrice;
private int _entryCount;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int MaxPositions
{
get => _maxPositions.Value;
set => _maxPositions.Value = value;
}
public int RandomSeed
{
get => _randomSeed.Value;
set => _randomSeed.Value = value;
}
public AtRandomFullStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
.SetDisplay("Candle Type", "Primary timeframe", "General");
_maxPositions = Param(nameof(MaxPositions), 3)
.SetDisplay("Max Positions", "Maximum number of averaged entries", "Risk");
_randomSeed = Param(nameof(RandomSeed), 123)
.SetDisplay("Random Seed", "Fixed seed for deterministic simulations", "Execution");
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_random = RandomSeed == 0 ? new Random() : new Random(RandomSeed);
_lastEntryPrice = 0;
_entryCount = 0;
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
// Only trade occasionally to keep turnover within runner limits.
if (_random.Next(0, 5) != 0)
return;
var volume = Volume;
if (volume <= 0)
volume = 1;
var close = candle.ClosePrice;
// Check grid spacing - minimum 0.5% between entries
if (_lastEntryPrice > 0 && Math.Abs(close - _lastEntryPrice) / _lastEntryPrice < 0.005m)
return;
// Check entry limit
if (MaxPositions > 0 && _entryCount >= MaxPositions)
{
// Close position and reset
if (Position > 0)
SellMarket(Position);
else if (Position < 0)
BuyMarket(Math.Abs(Position));
_entryCount = 0;
_lastEntryPrice = 0;
return;
}
var goLong = _random.Next(0, 2) == 0;
if (goLong)
{
if (Position < 0)
{
BuyMarket(Math.Abs(Position) + volume);
_entryCount = 1;
_lastEntryPrice = close;
}
else if (Position == 0)
{
BuyMarket(volume);
_lastEntryPrice = close;
_entryCount++;
}
}
else
{
if (Position > 0)
{
SellMarket(Math.Abs(Position) + volume);
_entryCount = 1;
_lastEntryPrice = close;
}
else if (Position == 0)
{
SellMarket(volume);
_lastEntryPrice = close;
_entryCount++;
}
}
}
/// <inheritdoc />
protected override void OnReseted()
{
_random = null;
_lastEntryPrice = 0;
_entryCount = 0;
base.OnReseted();
}
}
import clr
import random
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
class at_random_full_strategy(Strategy):
def __init__(self):
super(at_random_full_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(60)))
self._max_positions = self.Param("MaxPositions", 3)
self._random_seed = self.Param("RandomSeed", 123)
self._rng = None
self._last_entry_price = 0.0
self._entry_count = 0
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def MaxPositions(self):
return self._max_positions.Value
@MaxPositions.setter
def MaxPositions(self, value):
self._max_positions.Value = value
@property
def RandomSeed(self):
return self._random_seed.Value
@RandomSeed.setter
def RandomSeed(self, value):
self._random_seed.Value = value
def OnReseted(self):
super(at_random_full_strategy, self).OnReseted()
self._rng = None
self._last_entry_price = 0.0
self._entry_count = 0
def OnStarted2(self, time):
super(at_random_full_strategy, self).OnStarted2(time)
seed = self.RandomSeed
self._rng = random.Random(seed if seed != 0 else None)
self._last_entry_price = 0.0
self._entry_count = 0
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(self._process_candle).Start()
def _process_candle(self, candle):
if candle.State != CandleStates.Finished:
return
# Only trade occasionally
if self._rng.randint(0, 4) != 0:
return
close = float(candle.ClosePrice)
# Check grid spacing
if self._last_entry_price > 0 and abs(close - self._last_entry_price) / self._last_entry_price < 0.005:
return
# Check entry limit
if self.MaxPositions > 0 and self._entry_count >= self.MaxPositions:
if self.Position > 0:
self.SellMarket()
elif self.Position < 0:
self.BuyMarket()
self._entry_count = 0
self._last_entry_price = 0.0
return
go_long = self._rng.randint(0, 1) == 0
if go_long:
if self.Position <= 0:
self.BuyMarket()
self._last_entry_price = close
self._entry_count += 1
else:
if self.Position >= 0:
self.SellMarket()
self._last_entry_price = close
self._entry_count += 1
def CreateClone(self):
return at_random_full_strategy()