Ilan14-Strategie
Ilan14 ist eine Hedging-Grid-Strategie, die gleichzeitig Long- und Short-Positionen eröffnet. Wenn sich der Markt um eine benutzerdefinierte Pip-Distanz gegen eine Seite bewegt, fügt die Strategie eine neue Order in diese Richtung hinzu, deren Volumen mit dem Lot Exponent multipliziert wird. Der Durchschnittspreis der Position wird verfolgt, und sobald der Preis um die konfigurierte Take Profit-Distanz zurückkehrt, werden alle Orders dieser Seite geschlossen.
Parameter:
- Pip Step – Abstand in Pips zwischen Grid-Orders.
- Lot Exponent – Multiplikator für das Volumen jeder zusätzlichen Order.
- Max Trades – maximale Anzahl von Orders pro Richtung.
- Take Profit – Gewinnziel in Pips vom gewichteten Durchschnittspreis.
- Initial Volume – Volumen der ersten Order.
- Candle Type – Zeitrahmen für die Kerzensubskription.
Die Implementierung verwendet die High-Level-StockSharp-API mit Kerzensubskriptionen und vermeidet manuelle Datensammlungen. Beide Seiten des Grids werden unabhängig verwaltet, sodass die Strategie Rebounds nach ungünstigen Bewegungen nutzen kann.
using System;
using System.Linq;
using System.Collections.Generic;
using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
public class Ilan14Strategy : Strategy {
private readonly StrategyParam<decimal> _pipStep;
private readonly StrategyParam<decimal> _lotExponent;
private readonly StrategyParam<int> _maxTrades;
private readonly StrategyParam<decimal> _takeProfit;
private readonly StrategyParam<decimal> _initialVolume;
private readonly StrategyParam<DataType> _candleType;
private decimal _lastBuyPrice;
private decimal _lastSellPrice;
private decimal _lastBuyVolume;
private decimal _lastSellVolume;
private decimal _buyVolume;
private decimal _sellVolume;
private decimal _avgBuyPrice;
private decimal _avgSellPrice;
private int _buyCount;
private int _sellCount;
public decimal PipStep {
get => _pipStep.Value;
set => _pipStep.Value = value;
}
public decimal LotExponent {
get => _lotExponent.Value;
set => _lotExponent.Value = value;
}
public int MaxTrades {
get => _maxTrades.Value;
set => _maxTrades.Value = value;
}
public decimal TakeProfit {
get => _takeProfit.Value;
set => _takeProfit.Value = value;
}
public decimal InitialVolume {
get => _initialVolume.Value;
set => _initialVolume.Value = value;
}
public DataType CandleType {
get => _candleType.Value;
set => _candleType.Value = value;
}
public Ilan14Strategy() {
_pipStep =
Param(nameof(PipStep), 30m)
.SetGreaterThanZero()
.SetDisplay("Pip Step", "Distance in pips to add position",
"General")
;
_lotExponent =
Param(nameof(LotExponent), 1.667m)
.SetGreaterThanZero()
.SetDisplay("Lot Exponent",
"Volume multiplier for each additional order",
"General")
;
_maxTrades = Param(nameof(MaxTrades), 1)
.SetGreaterThanZero()
.SetDisplay("Max Trades",
"Maximum number of trades per direction",
"General");
_takeProfit =
Param(nameof(TakeProfit), 300m)
.SetGreaterThanZero()
.SetDisplay("Take Profit",
"Target profit in pips from average price",
"General")
;
_initialVolume = Param(nameof(InitialVolume), 0.1m)
.SetGreaterThanZero()
.SetDisplay("Initial Volume",
"Volume of first order", "General")
;
_candleType =
Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Type of candles to use", "General");
}
public override IEnumerable<(Security sec, DataType dt)>
GetWorkingSecurities() => [(Security, CandleType)];
protected override void OnReseted() {
base.OnReseted();
_lastBuyPrice = 0m;
_lastSellPrice = 0m;
_lastBuyVolume = 0m;
_lastSellVolume = 0m;
_buyVolume = 0m;
_sellVolume = 0m;
_avgBuyPrice = 0m;
_avgSellPrice = 0m;
_buyCount = 0;
_sellCount = 0;
}
protected override void OnStarted2(DateTime time) {
base.OnStarted2(time);
StartProtection(null, null);
var sub = SubscribeCandles(CandleType);
sub.Bind(Process).Start();
}
private void Process(ICandleMessage candle) {
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var step = Security.PriceStep ?? 1m;
var price = candle.ClosePrice;
if (_buyCount == 0 && _sellCount == 0) {
// Open initial hedge positions
BuyMarket(InitialVolume);
SellMarket(InitialVolume);
_lastBuyPrice = price;
_lastSellPrice = price;
_lastBuyVolume = InitialVolume;
_lastSellVolume = InitialVolume;
_buyVolume = InitialVolume;
_sellVolume = InitialVolume;
_avgBuyPrice = price;
_avgSellPrice = price;
_buyCount = 1;
_sellCount = 1;
return;
}
// --- Buy side management ---
if (_buyCount > 0) {
if (_buyCount < MaxTrades &&
price <= _lastBuyPrice - PipStep * step) {
var vol = _lastBuyVolume * LotExponent;
BuyMarket(vol);
_lastBuyVolume = vol;
_lastBuyPrice = price;
_avgBuyPrice = (_avgBuyPrice * _buyVolume + price * vol) /
(_buyVolume + vol);
_buyVolume += vol;
_buyCount++;
}
if (_buyVolume > 0 && price >= _avgBuyPrice + TakeProfit * step) {
// Close all buy positions when profit target is reached
SellMarket(_buyVolume);
_buyVolume = 0m;
_lastBuyPrice = 0m;
_lastBuyVolume = 0m;
_avgBuyPrice = 0m;
_buyCount = 0;
}
}
// --- Sell side management ---
if (_sellCount > 0) {
if (_sellCount < MaxTrades &&
price >= _lastSellPrice + PipStep * step) {
var vol = _lastSellVolume * LotExponent;
SellMarket(vol);
_lastSellVolume = vol;
_lastSellPrice = price;
_avgSellPrice = (_avgSellPrice * _sellVolume + price * vol) /
(_sellVolume + vol);
_sellVolume += vol;
_sellCount++;
}
if (_sellVolume > 0 && price <= _avgSellPrice - TakeProfit * step) {
// Close all sell positions when profit target is reached
BuyMarket(_sellVolume);
_sellVolume = 0m;
_lastSellPrice = 0m;
_lastSellVolume = 0m;
_avgSellPrice = 0m;
_sellCount = 0;
}
}
}
}
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
class ilan14_strategy(Strategy):
def __init__(self):
super(ilan14_strategy, self).__init__()
self._pip_step = self.Param("PipStep", 30.0)
self._lot_exponent = self.Param("LotExponent", 1.667)
self._max_trades = self.Param("MaxTrades", 1)
self._take_profit = self.Param("TakeProfit", 300.0)
self._initial_volume = self.Param("InitialVolume", 0.1)
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1)))
self._last_buy_price = 0.0
self._last_sell_price = 0.0
self._last_buy_volume = 0.0
self._last_sell_volume = 0.0
self._buy_volume = 0.0
self._sell_volume = 0.0
self._avg_buy_price = 0.0
self._avg_sell_price = 0.0
self._buy_count = 0
self._sell_count = 0
@property
def PipStep(self):
return self._pip_step.Value
@PipStep.setter
def PipStep(self, value):
self._pip_step.Value = value
@property
def LotExponent(self):
return self._lot_exponent.Value
@LotExponent.setter
def LotExponent(self, value):
self._lot_exponent.Value = value
@property
def MaxTrades(self):
return self._max_trades.Value
@MaxTrades.setter
def MaxTrades(self, value):
self._max_trades.Value = value
@property
def TakeProfit(self):
return self._take_profit.Value
@TakeProfit.setter
def TakeProfit(self, value):
self._take_profit.Value = value
@property
def InitialVolume(self):
return self._initial_volume.Value
@InitialVolume.setter
def InitialVolume(self, value):
self._initial_volume.Value = value
@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(ilan14_strategy, self).OnStarted2(time)
self._last_buy_price = 0.0
self._last_sell_price = 0.0
self._last_buy_volume = 0.0
self._last_sell_volume = 0.0
self._buy_volume = 0.0
self._sell_volume = 0.0
self._avg_buy_price = 0.0
self._avg_sell_price = 0.0
self._buy_count = 0
self._sell_count = 0
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(self.ProcessCandle).Start()
self.StartProtection(None, None)
def ProcessCandle(self, candle):
if candle.State != CandleStates.Finished:
return
if not self.IsFormedAndOnlineAndAllowTrading():
return
step = float(self.Security.PriceStep) if self.Security is not None and self.Security.PriceStep is not None else 1.0
price = float(candle.ClosePrice)
pip_step = float(self.PipStep)
lot_exp = float(self.LotExponent)
max_trades = int(self.MaxTrades)
tp = float(self.TakeProfit)
init_vol = float(self.InitialVolume)
if self._buy_count == 0 and self._sell_count == 0:
self.BuyMarket(init_vol)
self.SellMarket(init_vol)
self._last_buy_price = price
self._last_sell_price = price
self._last_buy_volume = init_vol
self._last_sell_volume = init_vol
self._buy_volume = init_vol
self._sell_volume = init_vol
self._avg_buy_price = price
self._avg_sell_price = price
self._buy_count = 1
self._sell_count = 1
return
if self._buy_count > 0:
if self._buy_count < max_trades and price <= self._last_buy_price - pip_step * step:
vol = self._last_buy_volume * lot_exp
self.BuyMarket(vol)
self._last_buy_volume = vol
self._last_buy_price = price
self._avg_buy_price = (self._avg_buy_price * self._buy_volume + price * vol) / (self._buy_volume + vol)
self._buy_volume += vol
self._buy_count += 1
if self._buy_volume > 0.0 and price >= self._avg_buy_price + tp * step:
self.SellMarket(self._buy_volume)
self._buy_volume = 0.0
self._last_buy_price = 0.0
self._last_buy_volume = 0.0
self._avg_buy_price = 0.0
self._buy_count = 0
if self._sell_count > 0:
if self._sell_count < max_trades and price >= self._last_sell_price + pip_step * step:
vol = self._last_sell_volume * lot_exp
self.SellMarket(vol)
self._last_sell_volume = vol
self._last_sell_price = price
self._avg_sell_price = (self._avg_sell_price * self._sell_volume + price * vol) / (self._sell_volume + vol)
self._sell_volume += vol
self._sell_count += 1
if self._sell_volume > 0.0 and price <= self._avg_sell_price - tp * step:
self.BuyMarket(self._sell_volume)
self._sell_volume = 0.0
self._last_sell_price = 0.0
self._last_sell_volume = 0.0
self._avg_sell_price = 0.0
self._sell_count = 0
def OnReseted(self):
super(ilan14_strategy, self).OnReseted()
self._last_buy_price = 0.0
self._last_sell_price = 0.0
self._last_buy_volume = 0.0
self._last_sell_volume = 0.0
self._buy_volume = 0.0
self._sell_volume = 0.0
self._avg_buy_price = 0.0
self._avg_sell_price = 0.0
self._buy_count = 0
self._sell_count = 0
def CreateClone(self):
return ilan14_strategy()