Cm Manual Grid
Cm Manual Grid 在当前价格周围放置可配置的止损和限价订单网格。每个新订单的数量按固定值增加。策略可以在达到目标利润时分别关闭多头或空头仓位,并包含跟踪利润机制。
详情
- 类型:网格交易,使用挂单
- 订单:Buy Stop、Sell Stop、Buy Limit、Sell Limit
- 数量:初始
Lot,增量LotPlus - 利润管理:
CloseProfitB关闭多头仓位CloseProfitS关闭空头仓位ProfitClose关闭所有仓位TralStart和TralClose控制跟踪利润
- 默认值:
OrdersBuyStop= 5OrdersSellStop= 5OrdersBuyLimit= 5OrdersSellLimit= 5FirstLevel= 5 步StepBuyStop= 10StepSellStop= 10StepBuyLimit= 10StepSellLimit= 10Lot= 0.1LotPlus= 0.1CloseProfitB= 10CloseProfitS= 10ProfitClose= 10TralStart= 10TralClose= 5
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Grid strategy that places buy/sell orders at regular intervals
/// based on price distance from a reference level (SMA).
/// Buys below SMA, sells above SMA with grid step spacing.
/// </summary>
public class CmManualGridStrategy : Strategy
{
private readonly StrategyParam<int> _smaPeriod;
private readonly StrategyParam<decimal> _gridStep;
private readonly StrategyParam<DataType> _candleType;
private decimal _lastBuyPrice;
private decimal _lastSellPrice;
public int SmaPeriod { get => _smaPeriod.Value; set => _smaPeriod.Value = value; }
public decimal GridStep { get => _gridStep.Value; set => _gridStep.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public CmManualGridStrategy()
{
_smaPeriod = Param(nameof(SmaPeriod), 50)
.SetGreaterThanZero()
.SetDisplay("SMA Period", "Moving average period for center", "Indicators");
_gridStep = Param(nameof(GridStep), 200m)
.SetGreaterThanZero()
.SetDisplay("Grid Step", "Price distance between grid levels", "Grid");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
protected override void OnReseted()
{
base.OnReseted();
_lastBuyPrice = 0;
_lastSellPrice = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_lastBuyPrice = 0;
_lastSellPrice = 0;
var sma = new SimpleMovingAverage { Length = SmaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(sma, ProcessCandle).Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, sma);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal smaValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
var price = candle.ClosePrice;
var step = GridStep;
// Buy when price is below SMA and spaced from last buy
if (price < smaValue - step)
{
if (_lastBuyPrice == 0 || price <= _lastBuyPrice - step)
{
BuyMarket();
_lastBuyPrice = price;
}
}
// Sell when price is above SMA and spaced from last sell
if (price > smaValue + step)
{
if (_lastSellPrice == 0 || price >= _lastSellPrice + step)
{
SellMarket();
_lastSellPrice = price;
}
}
// Reset grid when price returns to center
if (price > smaValue && _lastBuyPrice != 0)
_lastBuyPrice = 0;
if (price < smaValue && _lastSellPrice != 0)
_lastSellPrice = 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.Indicators import SimpleMovingAverage
from StockSharp.Algo.Strategies import Strategy
class cm_manual_grid_strategy(Strategy):
def __init__(self):
super(cm_manual_grid_strategy, self).__init__()
self._sma_period = self.Param("SmaPeriod", 50) \
.SetDisplay("SMA Period", "Moving average period for center", "Indicators")
self._grid_step = self.Param("GridStep", 200.0) \
.SetDisplay("Grid Step", "Price distance between grid levels", "Grid")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles", "General")
self._last_buy_price = 0.0
self._last_sell_price = 0.0
@property
def sma_period(self):
return self._sma_period.Value
@property
def grid_step(self):
return self._grid_step.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(cm_manual_grid_strategy, self).OnReseted()
self._last_buy_price = 0.0
self._last_sell_price = 0.0
def OnStarted2(self, time):
super(cm_manual_grid_strategy, self).OnStarted2(time)
self._last_buy_price = 0.0
self._last_sell_price = 0.0
sma = SimpleMovingAverage()
sma.Length = self.sma_period
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(sma, self.process_candle).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, sma)
self.DrawOwnTrades(area)
def process_candle(self, candle, sma_value):
if candle.State != CandleStates.Finished:
return
price = float(candle.ClosePrice)
sma_value = float(sma_value)
step = float(self.grid_step)
if price < sma_value - step:
if self._last_buy_price == 0.0 or price <= self._last_buy_price - step:
self.BuyMarket()
self._last_buy_price = price
if price > sma_value + step:
if self._last_sell_price == 0.0 or price >= self._last_sell_price + step:
self.SellMarket()
self._last_sell_price = price
if price > sma_value and self._last_buy_price != 0.0:
self._last_buy_price = 0.0
if price < sma_value and self._last_sell_price != 0.0:
self._last_sell_price = 0.0
def CreateClone(self):
return cm_manual_grid_strategy()