GitHub で見る
RangeEA ウィークリー グリッド戦略
概要
RangeEA Weekly Grid Strategy は、オリジナルの MetaTrader エキスパート アドバイザーから変換された指値注文グリッド システムです。アルゴリズムは現在の
毎週の取引範囲を設定し、設定可能な保留中の指値注文の数を入力します。各注文は動的なストップロスを使用し、
利食いオフセットは、指値価格と現在の市場価格の間の距離に応じて調整され、同時に以下の条件も考慮されます。
ポイントで表される最小距離。ポートフォリオの資本が 1 倍増加したら帳簿全体をクローズすることで利益を確定できます。
事前に定義された割合。
この実装では、StockSharp の高レベルの API を利用します。ローソク足が意思決定ロジックを駆動し、未決注文は
戦略ヘルパー メソッドとリスク コントロールは、最適化の準備ができたパラメーターとして公開されます。
取引ロジック
- 2 つのキャンドル ストリームを購読します。
- グリッドのメンテナンスを促進するユーザー定義の時間枠 (デフォルトでは 1 時間)。
- 現在の取引範囲を推定するために使用される週ごとのローソク足。
- 完了した週次ローソク足ごとに、過去 2 週間の最高値と最低値を更新します。彼らの違いは次のようになります
アクティブな取引範囲。
- 終了した取引ローソクごとに次のようになります。
- 設定された取引ウィンドウ (
StartTradeHour ~ EndTradeHour) を尊重してください。
- 必要に応じて、各取引日の初めにグリッドをリセットします。
- 未決の指値注文が存在しない場合は、新しい注文をレンジの下限と上限の間で均等に分配します。
- 2 つの注文がすでに約定された後、グリッドが終了したときに最後から 2 番目の約定を同じ価格の新しい注文に置き換えます。
NumberOfOrders - 2 個のアイテムに縮小されます。
- アカウントの資本を継続的に監視し、設定された利益率に達したらすべてを清算します。
- 取引ウィンドウが閉じ、
CloseAllAtEndTrade が有効になったら、すべての未決注文をキャンセルし、既存のポジションを終了します。
パラメーター
| 名前 |
説明 |
デフォルト |
CandleType |
グリッドメンテナンスをトリガーするために使用される取引時間枠。 |
1時間キャンドル |
WeeklyCandleType |
範囲境界を導出するために使用される時間枠。 |
1週間キャンドル |
StartTradeHour |
新しい注文ができる時間帯。 |
0 |
EndTradeHour |
取引が停止する時刻。 |
24 |
CloseAllAtEndTrade |
取引ウィンドウの外ですべての注文とポジションを閉じます。 |
本当の |
MaxOpenOrders |
同時注文とポジションの最大数。 |
5 |
NumberOfOrders |
グリッド内の指値注文の数。 |
10 |
OrderVolume |
各注文に使用される量。 |
0.01 |
ResetOrdersDaily |
各取引日の開始時にグリッドを再構築します。 |
本当の |
StopLossPoints |
ポイント単位の最小ストップロス距離。 |
60 |
TakeProfitPoints |
ポイント単位の最小利食い距離。 |
60 |
StopLossMultiplier |
動的ストップロス距離に適用される乗数。 |
3 |
TakeProfitMultiplier |
動的なテイクプロフィットディスタンスに適用される乗数。 |
1 |
TargetPercentage |
清算を引き起こす株式利益の割合。 |
8 |
リスク管理
- この戦略は、アクティブな注文とポジションの数を制御するために、
MaxOpenOrders の制限を尊重します。
- ストップロスとテイクプロフィットのレベルは、常にエントリーから設定されたポイント数以上離れており、オプションで設定できます。
乗算器パラメータによって拡張されます。
- 毎日のリセット オプションにより、古い注文が新しいセッションに持ち込まれるのを防ぎます。
- ポートフォリオレベルの株式目標により、帳簿を平坦化することで利益を固定する戦略が可能になります。
注意事項
- 選択した証券が毎週のローソク足を提供していることを確認します。そうしないと、ストラテジーは範囲を計算できません。
- 標準以外の価格ステップを持つ商品を使用する場合は、基礎となるティックサイズと一致するようにポイントベースの設定を調整します。
NumberOfOrders、OrderVolume、およびストップ/テイク乗数を最適化すると、グリッドをさまざまなレベルに適応させるのに役立ちます
ボラティリティ。
using System;
using System.Collections.Generic;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Range based grid strategy that detects the trading range from recent price action
/// and places buy/sell limit orders at grid levels within the range.
/// Buys at lower grid levels, sells at upper grid levels.
/// </summary>
public class RangeWeeklyGridStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _rangePeriod;
private readonly StrategyParam<int> _gridLevels;
private decimal _rangeHigh;
private decimal _rangeLow;
private bool _rangeSet;
private decimal _entryPrice;
private DateTimeOffset _lastTradeTime;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int RangePeriod
{
get => _rangePeriod.Value;
set => _rangePeriod.Value = value;
}
public int GridLevels
{
get => _gridLevels.Value;
set => _gridLevels.Value = value;
}
public RangeWeeklyGridStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Primary candle type", "General");
_rangePeriod = Param(nameof(RangePeriod), 100)
.SetDisplay("Range Period", "Number of candles to determine range", "Logic");
_gridLevels = Param(nameof(GridLevels), 5)
.SetDisplay("Grid Levels", "Number of grid levels within the range", "Logic");
}
protected override void OnReseted()
{
base.OnReseted();
_rangeHigh = 0;
_rangeLow = 0;
_rangeSet = false;
_entryPrice = 0;
_lastTradeTime = default;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var highest = new Highest { Length = RangePeriod };
var lowest = new Lowest { Length = RangePeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(highest, lowest, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal highestValue, decimal lowestValue)
{
if (candle.State != CandleStates.Finished)
return;
if (highestValue <= 0 || lowestValue <= 0 || highestValue <= lowestValue)
return;
_rangeHigh = highestValue;
_rangeLow = lowestValue;
_rangeSet = true;
if (!_rangeSet)
return;
var range = _rangeHigh - _rangeLow;
if (range <= 0)
return;
// Cooldown: at least 1 day between trades
if (_lastTradeTime != default && candle.CloseTime - _lastTradeTime < TimeSpan.FromDays(1))
return;
var gridStep = range / (GridLevels + 1);
var close = candle.ClosePrice;
var mid = (_rangeHigh + _rangeLow) / 2;
// Buy when price is in lower portion of range
if (close <= _rangeLow + gridStep && Position <= 0)
{
BuyMarket();
_entryPrice = close;
_lastTradeTime = candle.CloseTime;
}
// Sell when price is in upper portion of range
else if (close >= _rangeHigh - gridStep && Position >= 0)
{
SellMarket();
_entryPrice = close;
_lastTradeTime = candle.CloseTime;
}
// Take profit at mid-range
else if (Position > 0 && close >= mid)
{
SellMarket();
_lastTradeTime = candle.CloseTime;
}
else if (Position < 0 && close <= mid)
{
BuyMarket();
_lastTradeTime = candle.CloseTime;
}
}
}
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 Highest, Lowest
from StockSharp.Algo.Strategies import Strategy
class range_weekly_grid_strategy(Strategy):
def __init__(self):
super(range_weekly_grid_strategy, self).__init__()
self._range_period = self.Param("RangePeriod", 100).SetDisplay("Range Period", "Candles to determine range", "Logic")
self._grid_levels = self.Param("GridLevels", 5).SetDisplay("Grid Levels", "Grid levels within range", "Logic")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))).SetDisplay("Candle Type", "Primary candle type", "General")
@property
def CandleType(self): return self._candle_type.Value
@CandleType.setter
def CandleType(self, value): self._candle_type.Value = value
def OnStarted2(self, time):
super(range_weekly_grid_strategy, self).OnStarted2(time)
highest = Highest()
highest.Length = self._range_period.Value
lowest = Lowest()
lowest.Length = self._range_period.Value
sub = self.SubscribeCandles(self.CandleType)
sub.Bind(highest, lowest, self.OnProcess).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, sub)
self.DrawOwnTrades(area)
def OnProcess(self, candle, highest_val, lowest_val):
if candle.State != CandleStates.Finished:
return
if highest_val <= 0 or lowest_val <= 0 or highest_val <= lowest_val:
return
rng = highest_val - lowest_val
if rng <= 0:
return
grid_step = rng / (self._grid_levels.Value + 1)
close = candle.ClosePrice
mid = (highest_val + lowest_val) / 2.0
if close <= lowest_val + grid_step and self.Position <= 0:
self.BuyMarket()
elif close >= highest_val - grid_step and self.Position >= 0:
self.SellMarket()
elif self.Position > 0 and close >= mid:
self.SellMarket()
elif self.Position < 0 and close <= mid:
self.BuyMarket()
def CreateClone(self):
return range_weekly_grid_strategy()