Ichimoku Barabashkakvn 策略
该策略在 StockSharp 平台上重现了 Vladimir Karputov(barabashkakvn 版本)的 Ichimoku 专家顾问。核心是 Tenkan/Kijun 的交叉配合云层位置,同时保留原始 EA 中的全部风控逻辑。
策略原理
- 指标组合:使用一个 Ichimoku Kinko Hyo 指标(默认周期 9/26/52),获取 Tenkan、Kijun、Senkou Span A、Senkou Span B。
- 做多条件:Tenkan 上穿 Kijun,且收盘价高于 Senkou Span B。交叉检测使用上一根 Tenkan 值,与原始 MQL 实现一致。
- 做空条件:Tenkan 下穿 Kijun,且收盘价低于 Senkou Span A。
- 持仓管理:始终只保留一个净头寸;反向信号会先平掉现有仓位,与 EA 的两步反转流程相同。
- 交易时段:可选的时间过滤器,按开始/结束小时(包含端点)限制交易,判定方式复制自原代码。
风险控制
- 独立止损/止盈:多空分别设置止损与止盈点数,使用品种的最小价格跳动,并对 3 位和 5 位小数报价乘以 10,完全复刻 EA 的点值换算。
- 移动止损:多空各自拥有独立的移动距离,并共享一个“步长”。只有当浮盈超过“距离 + 步长”后才会上移/下移止损,行为与原脚本相同。
- 保护执行:每根完结 K 线都会检查虚拟止损/止盈,以模拟 MetaTrader 上的服务器委托效果。
参数
TenkanPeriod(默认 9)– Tenkan 周期。KijunPeriod(26)– Kijun 周期。SenkouSpanBPeriod(52)– Senkou Span B 周期。CandleType(1 小时)– 计算所用的 K 线类型。OrderVolume(1 手)– 交易手数。BuyStopLossPips/SellStopLossPips(100)– 多/空止损点数。BuyTakeProfitPips/SellTakeProfitPips(300)– 多/空止盈点数。BuyTrailingStopPips/SellTrailingStopPips(50)– 多/空移动止损距离。TrailingStepPips(5)– 调整移动止损所需的额外盈利点数。UseTradeHours(false)– 是否启用时间过滤。StartHour/EndHour(0 / 23)– 允许交易的小时范围,0–23 之间。
所有参数均通过 StrategyParam<T> 暴露,可在 StockSharp Designer 中直接调整或优化,无需修改源码。
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;
/// <summary>
/// Ichimoku cloud strategy inspired by barabashkakvn's MQL implementation.
/// Executes Tenkan/Kijun crosses with Kumo confirmation and optional timed trading window.
/// Includes independent stop-loss/take-profit targets per direction and pip-based trailing stops.
/// </summary>
public class IchimokuBarabashkakvnStrategy : Strategy
{
private readonly StrategyParam<int> _tenkanPeriod;
private readonly StrategyParam<int> _kijunPeriod;
private readonly StrategyParam<int> _senkouSpanBPeriod;
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<decimal> _orderVolume;
private readonly StrategyParam<int> _buyStopLossPips;
private readonly StrategyParam<int> _buyTakeProfitPips;
private readonly StrategyParam<int> _sellStopLossPips;
private readonly StrategyParam<int> _sellTakeProfitPips;
private readonly StrategyParam<int> _buyTrailingStopPips;
private readonly StrategyParam<int> _sellTrailingStopPips;
private readonly StrategyParam<int> _trailingStepPips;
private readonly StrategyParam<bool> _useTradeHours;
private readonly StrategyParam<int> _startHour;
private readonly StrategyParam<int> _endHour;
private Ichimoku _ichimoku = null!;
private decimal? _prevTenkan;
private decimal? _entryPrice;
private decimal? _stopLossPrice;
private decimal? _takeProfitPrice;
private decimal _pipValue;
/// <summary>
/// Tenkan-sen period.
/// </summary>
public int TenkanPeriod
{
get => _tenkanPeriod.Value;
set => _tenkanPeriod.Value = value;
}
/// <summary>
/// Kijun-sen period.
/// </summary>
public int KijunPeriod
{
get => _kijunPeriod.Value;
set => _kijunPeriod.Value = value;
}
/// <summary>
/// Senkou Span B period.
/// </summary>
public int SenkouSpanBPeriod
{
get => _senkouSpanBPeriod.Value;
set => _senkouSpanBPeriod.Value = value;
}
/// <summary>
/// Candle type used for calculations.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Order volume.
/// </summary>
public decimal OrderVolume
{
get => _orderVolume.Value;
set => _orderVolume.Value = value;
}
/// <summary>
/// Stop-loss distance for long trades in pips.
/// </summary>
public int BuyStopLossPips
{
get => _buyStopLossPips.Value;
set => _buyStopLossPips.Value = value;
}
/// <summary>
/// Take-profit distance for long trades in pips.
/// </summary>
public int BuyTakeProfitPips
{
get => _buyTakeProfitPips.Value;
set => _buyTakeProfitPips.Value = value;
}
/// <summary>
/// Stop-loss distance for short trades in pips.
/// </summary>
public int SellStopLossPips
{
get => _sellStopLossPips.Value;
set => _sellStopLossPips.Value = value;
}
/// <summary>
/// Take-profit distance for short trades in pips.
/// </summary>
public int SellTakeProfitPips
{
get => _sellTakeProfitPips.Value;
set => _sellTakeProfitPips.Value = value;
}
/// <summary>
/// Trailing stop distance for long trades in pips.
/// </summary>
public int BuyTrailingStopPips
{
get => _buyTrailingStopPips.Value;
set => _buyTrailingStopPips.Value = value;
}
/// <summary>
/// Trailing stop distance for short trades in pips.
/// </summary>
public int SellTrailingStopPips
{
get => _sellTrailingStopPips.Value;
set => _sellTrailingStopPips.Value = value;
}
/// <summary>
/// Trailing step in pips for both directions.
/// </summary>
public int TrailingStepPips
{
get => _trailingStepPips.Value;
set => _trailingStepPips.Value = value;
}
/// <summary>
/// Enable trading only within the configured hour window.
/// </summary>
public bool UseTradeHours
{
get => _useTradeHours.Value;
set => _useTradeHours.Value = value;
}
/// <summary>
/// First trading hour (0-23).
/// </summary>
public int StartHour
{
get => _startHour.Value;
set => _startHour.Value = value;
}
/// <summary>
/// Last trading hour (0-23).
/// </summary>
public int EndHour
{
get => _endHour.Value;
set => _endHour.Value = value;
}
/// <summary>
/// Initialize <see cref="IchimokuBarabashkakvnStrategy"/>.
/// </summary>
public IchimokuBarabashkakvnStrategy()
{
_tenkanPeriod = Param(nameof(TenkanPeriod), 9)
.SetGreaterThanZero()
.SetDisplay("Tenkan Period", "Tenkan-sen periods", "Ichimoku");
_kijunPeriod = Param(nameof(KijunPeriod), 26)
.SetGreaterThanZero()
.SetDisplay("Kijun Period", "Kijun-sen periods", "Ichimoku");
_senkouSpanBPeriod = Param(nameof(SenkouSpanBPeriod), 52)
.SetGreaterThanZero()
.SetDisplay("Senkou Span B Period", "Senkou Span B periods", "Ichimoku");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Source candles for processing", "General");
_orderVolume = Param(nameof(OrderVolume), 1m)
.SetGreaterThanZero()
.SetDisplay("Order Volume", "Position size in lots", "Trading");
_buyStopLossPips = Param(nameof(BuyStopLossPips), 100)
.SetNotNegative()
.SetDisplay("Buy Stop Loss (pips)", "Long stop-loss distance", "Risk");
_buyTakeProfitPips = Param(nameof(BuyTakeProfitPips), 300)
.SetNotNegative()
.SetDisplay("Buy Take Profit (pips)", "Long take-profit distance", "Risk");
_sellStopLossPips = Param(nameof(SellStopLossPips), 100)
.SetNotNegative()
.SetDisplay("Sell Stop Loss (pips)", "Short stop-loss distance", "Risk");
_sellTakeProfitPips = Param(nameof(SellTakeProfitPips), 300)
.SetNotNegative()
.SetDisplay("Sell Take Profit (pips)", "Short take-profit distance", "Risk");
_buyTrailingStopPips = Param(nameof(BuyTrailingStopPips), 50)
.SetNotNegative()
.SetDisplay("Buy Trailing Stop (pips)", "Long trailing distance", "Risk");
_sellTrailingStopPips = Param(nameof(SellTrailingStopPips), 50)
.SetNotNegative()
.SetDisplay("Sell Trailing Stop (pips)", "Short trailing distance", "Risk");
_trailingStepPips = Param(nameof(TrailingStepPips), 5)
.SetNotNegative()
.SetDisplay("Trailing Step (pips)", "Step for trailing adjustments", "Risk");
_useTradeHours = Param(nameof(UseTradeHours), false)
.SetDisplay("Use Trade Hours", "Restrict trading to a time range", "Timing");
_startHour = Param(nameof(StartHour), 0)
.SetDisplay("Start Hour", "First hour allowed for trading", "Timing")
.SetRange(0, 23);
_endHour = Param(nameof(EndHour), 23)
.SetDisplay("End Hour", "Last hour allowed for trading", "Timing")
.SetRange(0, 23);
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevTenkan = null;
_pipValue = 0m;
ResetPositionState();
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
if (UseTradeHours && StartHour >= EndHour)
throw new InvalidOperationException("Start hour must be less than end hour when time filter is enabled.");
_ichimoku = new Ichimoku
{
Tenkan = { Length = TenkanPeriod },
Kijun = { Length = KijunPeriod },
SenkouB = { Length = SenkouSpanBPeriod }
};
_pipValue = CalculatePipValue();
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;
var ichimokuValue = _ichimoku.Process(candle);
if (!ichimokuValue.IsFinal)
return;
var ichimokuTyped = (IchimokuValue)ichimokuValue;
if (ichimokuTyped.Tenkan is not decimal tenkan ||
ichimokuTyped.Kijun is not decimal kijun ||
ichimokuTyped.SenkouA is not decimal senkouA ||
ichimokuTyped.SenkouB is not decimal senkouB)
{
return;
}
if (!_ichimoku.IsFormed)
{
_prevTenkan = tenkan;
return;
}
if (_prevTenkan is null)
{
_prevTenkan = tenkan;
return;
}
// Ensure state is cleared if positions were closed externally.
if (Position == 0 && (_entryPrice.HasValue || _stopLossPrice.HasValue || _takeProfitPrice.HasValue))
ResetPositionState();
if (Position != 0 && CheckProtectiveLevels(candle))
{
_prevTenkan = tenkan;
return;
}
if (UseTradeHours)
{
var hour = candle.OpenTime.Hour;
if (!(hour >= StartHour && hour <= EndHour))
{
_prevTenkan = tenkan;
return;
}
}
var buySignal = _prevTenkan < kijun && tenkan >= kijun && candle.ClosePrice > senkouB;
var sellSignal = _prevTenkan > kijun && tenkan <= kijun && candle.ClosePrice < senkouA;
if (Position == 0)
{
if (buySignal)
{
OpenLong(candle);
}
else if (sellSignal)
{
OpenShort(candle);
}
}
else if (Position < 0)
{
if (buySignal)
{
CloseShort();
_prevTenkan = tenkan;
return;
}
}
else if (Position > 0)
{
if (sellSignal)
{
CloseLong();
_prevTenkan = tenkan;
return;
}
}
UpdateTrailingStops(candle);
_prevTenkan = tenkan;
}
private void OpenLong(ICandleMessage candle)
{
if (OrderVolume <= 0)
return;
BuyMarket(OrderVolume);
_entryPrice = candle.ClosePrice;
var stopOffset = GetPriceOffset(BuyStopLossPips);
var takeOffset = GetPriceOffset(BuyTakeProfitPips);
_stopLossPrice = stopOffset > 0 ? candle.ClosePrice - stopOffset : null;
_takeProfitPrice = takeOffset > 0 ? candle.ClosePrice + takeOffset : null;
}
private void OpenShort(ICandleMessage candle)
{
if (OrderVolume <= 0)
return;
SellMarket(OrderVolume);
_entryPrice = candle.ClosePrice;
var stopOffset = GetPriceOffset(SellStopLossPips);
var takeOffset = GetPriceOffset(SellTakeProfitPips);
_stopLossPrice = stopOffset > 0 ? candle.ClosePrice + stopOffset : null;
_takeProfitPrice = takeOffset > 0 ? candle.ClosePrice - takeOffset : null;
}
private void CloseLong()
{
if (Position <= 0)
return;
SellMarket(Math.Abs(Position));
ResetPositionState();
}
private void CloseShort()
{
if (Position >= 0)
return;
BuyMarket(Math.Abs(Position));
ResetPositionState();
}
private void UpdateTrailingStops(ICandleMessage candle)
{
if (_entryPrice is null)
return;
if (Position > 0)
{
var trailingStop = GetPriceOffset(BuyTrailingStopPips);
var trailingStep = GetPriceOffset(TrailingStepPips);
if (trailingStop > 0 && trailingStep >= 0)
{
var profit = candle.ClosePrice - _entryPrice.Value;
if (profit > trailingStop + trailingStep)
{
var threshold = candle.ClosePrice - (trailingStop + trailingStep);
if (!_stopLossPrice.HasValue || _stopLossPrice.Value < threshold)
{
_stopLossPrice = candle.ClosePrice - trailingStop;
}
}
}
CheckProtectiveLevels(candle);
}
else if (Position < 0)
{
var trailingStop = GetPriceOffset(SellTrailingStopPips);
var trailingStep = GetPriceOffset(TrailingStepPips);
if (trailingStop > 0 && trailingStep >= 0)
{
var profit = _entryPrice.Value - candle.ClosePrice;
if (profit > trailingStop + trailingStep)
{
var threshold = candle.ClosePrice + (trailingStop + trailingStep);
if (!_stopLossPrice.HasValue || _stopLossPrice.Value > threshold)
{
_stopLossPrice = candle.ClosePrice + trailingStop;
}
}
}
CheckProtectiveLevels(candle);
}
}
private bool CheckProtectiveLevels(ICandleMessage candle)
{
if (Position > 0)
{
if (_stopLossPrice is decimal sl && candle.LowPrice <= sl)
{
SellMarket(Math.Abs(Position));
ResetPositionState();
return true;
}
if (_takeProfitPrice is decimal tp && candle.HighPrice >= tp)
{
SellMarket(Math.Abs(Position));
ResetPositionState();
return true;
}
}
else if (Position < 0)
{
if (_stopLossPrice is decimal sl && candle.HighPrice >= sl)
{
BuyMarket(Math.Abs(Position));
ResetPositionState();
return true;
}
if (_takeProfitPrice is decimal tp && candle.LowPrice <= tp)
{
BuyMarket(Math.Abs(Position));
ResetPositionState();
return true;
}
}
return false;
}
private void ResetPositionState()
{
_entryPrice = null;
_stopLossPrice = null;
_takeProfitPrice = null;
}
private decimal GetPriceOffset(int pips)
{
if (pips <= 0)
return 0m;
return pips * _pipValue;
}
private decimal CalculatePipValue()
{
var priceStep = Security?.PriceStep ?? 0m;
if (priceStep <= 0m)
priceStep = 1m;
var decimals = GetDecimalPlaces(priceStep);
var multiplier = decimals is 3 or 5 ? 10m : 1m;
return priceStep * multiplier;
}
private static int GetDecimalPlaces(decimal value)
{
var bits = decimal.GetBits(value);
return (bits[3] >> 16) & 0xFF;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Math
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import Ichimoku, CandleIndicatorValue
from StockSharp.Algo.Strategies import Strategy
class ichimoku_barabashkakvn_strategy(Strategy):
def __init__(self):
super(ichimoku_barabashkakvn_strategy, self).__init__()
self._tenkan_period = self.Param("TenkanPeriod", 9)
self._kijun_period = self.Param("KijunPeriod", 26)
self._senkou_span_b_period = self.Param("SenkouSpanBPeriod", 52)
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1)))
self._order_volume = self.Param("OrderVolume", 1.0)
self._buy_stop_loss_pips = self.Param("BuyStopLossPips", 100)
self._buy_take_profit_pips = self.Param("BuyTakeProfitPips", 300)
self._sell_stop_loss_pips = self.Param("SellStopLossPips", 100)
self._sell_take_profit_pips = self.Param("SellTakeProfitPips", 300)
self._buy_trailing_stop_pips = self.Param("BuyTrailingStopPips", 50)
self._sell_trailing_stop_pips = self.Param("SellTrailingStopPips", 50)
self._trailing_step_pips = self.Param("TrailingStepPips", 5)
self._use_trade_hours = self.Param("UseTradeHours", False)
self._start_hour = self.Param("StartHour", 0)
self._end_hour = self.Param("EndHour", 23)
self._ichimoku = None
self._prev_tenkan = None
self._entry_price = None
self._stop_loss_price = None
self._take_profit_price = None
self._pip_value = 0.0
@property
def TenkanPeriod(self):
return self._tenkan_period.Value
@property
def KijunPeriod(self):
return self._kijun_period.Value
@property
def SenkouSpanBPeriod(self):
return self._senkou_span_b_period.Value
@property
def CandleType(self):
return self._candle_type.Value
@property
def OrderVolume(self):
return self._order_volume.Value
@property
def BuyStopLossPips(self):
return self._buy_stop_loss_pips.Value
@property
def BuyTakeProfitPips(self):
return self._buy_take_profit_pips.Value
@property
def SellStopLossPips(self):
return self._sell_stop_loss_pips.Value
@property
def SellTakeProfitPips(self):
return self._sell_take_profit_pips.Value
@property
def BuyTrailingStopPips(self):
return self._buy_trailing_stop_pips.Value
@property
def SellTrailingStopPips(self):
return self._sell_trailing_stop_pips.Value
@property
def TrailingStepPips(self):
return self._trailing_step_pips.Value
@property
def UseTradeHours(self):
return self._use_trade_hours.Value
@property
def StartHour(self):
return self._start_hour.Value
@property
def EndHour(self):
return self._end_hour.Value
def OnStarted2(self, time):
super(ichimoku_barabashkakvn_strategy, self).OnStarted2(time)
self._ichimoku = Ichimoku()
self._ichimoku.Tenkan.Length = self.TenkanPeriod
self._ichimoku.Kijun.Length = self.KijunPeriod
self._ichimoku.SenkouB.Length = self.SenkouSpanBPeriod
self._pip_value = self._calculate_pip_value()
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(self._process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def _process_candle(self, candle):
if candle.State != CandleStates.Finished:
return
civ = CandleIndicatorValue(self._ichimoku, candle)
civ.IsFinal = True
ichimoku_value = self._ichimoku.Process(civ)
if not ichimoku_value.IsFinal:
return
try:
tenkan = float(ichimoku_value.Tenkan)
kijun = float(ichimoku_value.Kijun)
senkou_a = float(ichimoku_value.SenkouA)
senkou_b = float(ichimoku_value.SenkouB)
except:
return
if not self._ichimoku.IsFormed:
self._prev_tenkan = tenkan
return
if self._prev_tenkan is None:
self._prev_tenkan = tenkan
return
pos = float(self.Position)
if pos == 0 and (self._entry_price is not None or self._stop_loss_price is not None or self._take_profit_price is not None):
self._reset_position_state()
if pos != 0 and self._check_protective_levels(candle):
self._prev_tenkan = tenkan
return
if self.UseTradeHours:
hour = candle.OpenTime.Hour
if not (hour >= self.StartHour and hour <= self.EndHour):
self._prev_tenkan = tenkan
return
buy_signal = self._prev_tenkan < kijun and tenkan >= kijun and float(candle.ClosePrice) > senkou_b
sell_signal = self._prev_tenkan > kijun and tenkan <= kijun and float(candle.ClosePrice) < senkou_a
if pos == 0:
if buy_signal:
self._open_long(candle)
elif sell_signal:
self._open_short(candle)
elif pos < 0:
if buy_signal:
self._close_short()
self._prev_tenkan = tenkan
return
elif pos > 0:
if sell_signal:
self._close_long()
self._prev_tenkan = tenkan
return
self._update_trailing_stops(candle)
self._prev_tenkan = tenkan
def _open_long(self, candle):
if float(self.OrderVolume) <= 0:
return
self.BuyMarket(float(self.OrderVolume))
self._entry_price = float(candle.ClosePrice)
stop_offset = self._get_price_offset(self.BuyStopLossPips)
take_offset = self._get_price_offset(self.BuyTakeProfitPips)
self._stop_loss_price = float(candle.ClosePrice) - stop_offset if stop_offset > 0 else None
self._take_profit_price = float(candle.ClosePrice) + take_offset if take_offset > 0 else None
def _open_short(self, candle):
if float(self.OrderVolume) <= 0:
return
self.SellMarket(float(self.OrderVolume))
self._entry_price = float(candle.ClosePrice)
stop_offset = self._get_price_offset(self.SellStopLossPips)
take_offset = self._get_price_offset(self.SellTakeProfitPips)
self._stop_loss_price = float(candle.ClosePrice) + stop_offset if stop_offset > 0 else None
self._take_profit_price = float(candle.ClosePrice) - take_offset if take_offset > 0 else None
def _close_long(self):
pos = float(self.Position)
if pos <= 0:
return
self.SellMarket(abs(pos))
self._reset_position_state()
def _close_short(self):
pos = float(self.Position)
if pos >= 0:
return
self.BuyMarket(abs(pos))
self._reset_position_state()
def _update_trailing_stops(self, candle):
if self._entry_price is None:
return
pos = float(self.Position)
if pos > 0:
trailing_stop = self._get_price_offset(self.BuyTrailingStopPips)
trailing_step = self._get_price_offset(self.TrailingStepPips)
if trailing_stop > 0 and trailing_step >= 0:
profit = float(candle.ClosePrice) - self._entry_price
if profit > trailing_stop + trailing_step:
threshold = float(candle.ClosePrice) - (trailing_stop + trailing_step)
if self._stop_loss_price is None or self._stop_loss_price < threshold:
self._stop_loss_price = float(candle.ClosePrice) - trailing_stop
self._check_protective_levels(candle)
elif pos < 0:
trailing_stop = self._get_price_offset(self.SellTrailingStopPips)
trailing_step = self._get_price_offset(self.TrailingStepPips)
if trailing_stop > 0 and trailing_step >= 0:
profit = self._entry_price - float(candle.ClosePrice)
if profit > trailing_stop + trailing_step:
threshold = float(candle.ClosePrice) + (trailing_stop + trailing_step)
if self._stop_loss_price is None or self._stop_loss_price > threshold:
self._stop_loss_price = float(candle.ClosePrice) + trailing_stop
self._check_protective_levels(candle)
def _check_protective_levels(self, candle):
pos = float(self.Position)
if pos > 0:
if self._stop_loss_price is not None and float(candle.LowPrice) <= self._stop_loss_price:
self.SellMarket(abs(pos))
self._reset_position_state()
return True
if self._take_profit_price is not None and float(candle.HighPrice) >= self._take_profit_price:
self.SellMarket(abs(pos))
self._reset_position_state()
return True
elif pos < 0:
if self._stop_loss_price is not None and float(candle.HighPrice) >= self._stop_loss_price:
self.BuyMarket(abs(pos))
self._reset_position_state()
return True
if self._take_profit_price is not None and float(candle.LowPrice) <= self._take_profit_price:
self.BuyMarket(abs(pos))
self._reset_position_state()
return True
return False
def _reset_position_state(self):
self._entry_price = None
self._stop_loss_price = None
self._take_profit_price = None
def _get_price_offset(self, pips):
if pips <= 0:
return 0.0
return pips * self._pip_value
def _calculate_pip_value(self):
sec = self.Security
if sec is None:
return 1.0
price_step = float(sec.PriceStep) if sec.PriceStep is not None else 1.0
if price_step <= 0:
price_step = 1.0
decimals = self._get_decimal_places(price_step)
multiplier = 10.0 if decimals == 3 or decimals == 5 else 1.0
return price_step * multiplier
def _get_decimal_places(self, value):
value = abs(value)
count = 0
while value != int(value) and count < 10:
value *= 10.0
count += 1
return count
def OnReseted(self):
super(ichimoku_barabashkakvn_strategy, self).OnReseted()
self._prev_tenkan = None
self._pip_value = 0.0
self._reset_position_state()
def CreateClone(self):
return ichimoku_barabashkakvn_strategy()