Monatliche Kaufstrategie mit dynamischer Kontraktgröße
Kauft an einem gewählten Tag jedes Monats eine dynamische Anzahl von Kontrakten unter Verwendung eines festen Prozentsatzes des Kontokapitals. Der Drawdown wird zu Informationszwecken verfolgt.
Details
- Einstiegskriterien: Zeit >= StartDate UND Monatstag = BuyDay
- Long/Short: Nur Long
- Ausstiegskriterien: keine
- Stops: keine
- Standardwerte:
CandleType= 1 TagStartDate= 2010-01-01PercentOfEquity= 0.03BuyDay= 1
- Filter:
- Kategorie: Cost-Averaging
- Richtung: Long
- Indikatoren: Nein
- Stops: Nein
- Komplexität: Anfänger
- Zeitrahmen: Langfristig
- Saisonalität: Monatlich
- Neuronale Netze: Nein
- Divergenz: Nein
- Risikolevel: Niedrig
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>
/// Buys a percentage of equity on a specific day each month.
/// </summary>
public class MonthlyPurchaseWithDynamicContractSizeStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<DateTimeOffset> _startDate;
private readonly StrategyParam<decimal> _percentOfEquity;
private readonly StrategyParam<int> _buyDay;
private decimal? _highestEquity;
private DateTimeOffset? _lastBuyTime;
/// <summary>
/// Candle type for strategy.
/// </summary>
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
/// <summary>
/// Start date after which purchases are allowed.
/// </summary>
public DateTimeOffset StartDate
{
get => _startDate.Value;
set => _startDate.Value = value;
}
/// <summary>
/// Percentage of equity used for each purchase.
/// </summary>
public decimal PercentOfEquity
{
get => _percentOfEquity.Value;
set => _percentOfEquity.Value = value;
}
/// <summary>
/// Day of the month to buy.
/// </summary>
public int BuyDay
{
get => _buyDay.Value;
set => _buyDay.Value = value;
}
/// <summary>
/// Initializes a new instance of the <see cref="MonthlyPurchaseWithDynamicContractSizeStrategy"/>.
/// </summary>
public MonthlyPurchaseWithDynamicContractSizeStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Type of candles for strategy", "General");
_startDate = Param(nameof(StartDate), new DateTimeOffset(2010, 1, 1, 0, 0, 0, TimeSpan.Zero))
.SetDisplay("Start Date", "Purchases start from this date", "Strategy");
_percentOfEquity = Param(nameof(PercentOfEquity), 0.03m)
.SetRange(0.01m, 10m)
.SetDisplay("Percent of Equity", "Percentage of equity per purchase", "Strategy");
_buyDay = Param(nameof(BuyDay), 1)
.SetRange(1, 31)
.SetDisplay("Buy Day", "Day of month to buy", "Strategy");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_highestEquity = null;
_lastBuyTime = null;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
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;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var equity = Portfolio.CurrentValue ?? 0m;
if (_highestEquity == null || equity > _highestEquity)
_highestEquity = equity;
var isAfterStart = candle.OpenTime >= StartDate;
if (!isAfterStart)
return;
var currentDay = candle.OpenTime.Day;
var lastMonth = _lastBuyTime?.Month;
var lastYear = _lastBuyTime?.Year;
if (currentDay >= BuyDay && (lastMonth != candle.OpenTime.Month || lastYear != candle.OpenTime.Year))
{
var effectiveEquity = equity > candle.ClosePrice ? equity : candle.ClosePrice;
var contracts = (int)(effectiveEquity * PercentOfEquity / candle.ClosePrice);
if (contracts <= 0)
contracts = 1;
if (contracts > 0)
{
BuyMarket(contracts);
_lastBuyTime = candle.OpenTime;
}
}
}
}
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 monthly_purchase_with_dynamic_contract_size_strategy(Strategy):
def __init__(self):
super(monthly_purchase_with_dynamic_contract_size_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Candle Type", "Type of candles for strategy", "General")
self._percent_of_equity = self.Param("PercentOfEquity", 0.03) \
.SetDisplay("Percent of Equity", "Percentage of equity per purchase", "Strategy")
self._buy_day = self.Param("BuyDay", 1) \
.SetDisplay("Buy Day", "Day of month to buy", "Strategy")
self._last_buy_month = -1
self._last_buy_year = -1
@property
def candle_type(self):
return self._candle_type.Value
@candle_type.setter
def candle_type(self, value):
self._candle_type.Value = value
def OnReseted(self):
super(monthly_purchase_with_dynamic_contract_size_strategy, self).OnReseted()
self._last_buy_month = -1
self._last_buy_year = -1
def OnStarted2(self, time):
super(monthly_purchase_with_dynamic_contract_size_strategy, self).OnStarted2(time)
self._last_buy_month = -1
self._last_buy_year = -1
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(self.OnProcess).Start()
def OnProcess(self, candle):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
if close <= 0.0:
return
current_day = candle.OpenTime.Day
current_month = candle.OpenTime.Month
current_year = candle.OpenTime.Year
buy_day = self._buy_day.Value
if current_day >= buy_day and (self._last_buy_month != current_month or self._last_buy_year != current_year):
pct = float(self._percent_of_equity.Value)
effective_equity = close
contracts = int(effective_equity * pct / close)
if contracts <= 0:
contracts = 1
self.BuyMarket()
self._last_buy_month = current_month
self._last_buy_year = current_year
def CreateClone(self):
return monthly_purchase_with_dynamic_contract_size_strategy()