终极 T3 斐波那契 BTC 剥头皮策略
该策略使用两条Tilson T3均线捕捉比特币的短期波动。斐波那契调校的T3与标准T3的交叉产生做多或做空信号,可选择在反向信号或百分比止盈/止损下平仓。
测试显示年化收益约为38%,在低延迟的BTC交易对上表现最佳。
当快速T3上穿慢速T3时买入,下穿时卖出。可选择在反向交叉时直接平仓,或使用百分比止盈止损管理仓位。
细节
- 入场条件:
- 多头:快速T3上穿慢速T3。
- 空头:快速T3下穿慢速T3。
- 方向:双向。
- 出场条件:
- 反向交叉或启用的止盈/止损。
- 止损:可选百分比。
- 过滤器:
- 无。
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>
/// Strategy based on two T3-style moving averages for BTC scalping.
/// </summary>
public class UltimateT3FibonacciBtcScalpingStrategy : Strategy
{
private readonly StrategyParam<int> _t3Length;
private readonly StrategyParam<int> _t3FiboLength;
private readonly StrategyParam<bool> _useOpposite;
private readonly StrategyParam<bool> _useTradeManagement;
private readonly StrategyParam<decimal> _takeProfit;
private readonly StrategyParam<decimal> _stopLoss;
private readonly StrategyParam<DataType> _candleType;
private decimal _entryPrice;
private decimal _prevT3;
private decimal _prevT3Fibo;
public int T3Length { get => _t3Length.Value; set => _t3Length.Value = value; }
public int T3FiboLength { get => _t3FiboLength.Value; set => _t3FiboLength.Value = value; }
public bool UseOpposite { get => _useOpposite.Value; set => _useOpposite.Value = value; }
public bool UseTradeManagement { get => _useTradeManagement.Value; set => _useTradeManagement.Value = value; }
public decimal TakeProfit { get => _takeProfit.Value; set => _takeProfit.Value = value; }
public decimal StopLoss { get => _stopLoss.Value; set => _stopLoss.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public UltimateT3FibonacciBtcScalpingStrategy()
{
_t3Length = Param(nameof(T3Length), 33)
.SetGreaterThanZero()
.SetDisplay("T3 Length", "Main T3 length", "General");
_t3FiboLength = Param(nameof(T3FiboLength), 19)
.SetGreaterThanZero()
.SetDisplay("T3 Fibo Length", "Fibonacci T3 length", "General");
_useOpposite = Param(nameof(UseOpposite), true)
.SetDisplay("Use Opposite", "Close on opposite signal", "General");
_useTradeManagement = Param(nameof(UseTradeManagement), true)
.SetDisplay("Use Trade Management", "Enable TP/SL", "General");
_takeProfit = Param(nameof(TakeProfit), 15m)
.SetGreaterThanZero()
.SetDisplay("Take Profit %", "Take profit percentage", "Risk");
_stopLoss = Param(nameof(StopLoss), 2m)
.SetGreaterThanZero()
.SetDisplay("Stop Loss %", "Stop loss percentage", "Risk");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Type of candles", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_entryPrice = 0;
_prevT3 = 0;
_prevT3Fibo = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var t3 = new ExponentialMovingAverage { Length = T3Length };
var t3Fibo = new ExponentialMovingAverage { Length = T3FiboLength };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(t3, t3Fibo, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal t3, decimal t3Fibo)
{
if (candle.State != CandleStates.Finished)
return;
var crossUp = _prevT3Fibo <= _prevT3 && t3Fibo > t3;
var crossDown = _prevT3Fibo >= _prevT3 && t3Fibo < t3;
_prevT3 = t3;
_prevT3Fibo = t3Fibo;
if (crossUp && Position <= 0)
{
BuyMarket();
_entryPrice = candle.ClosePrice;
}
else if (crossDown && Position >= 0)
{
SellMarket();
_entryPrice = candle.ClosePrice;
}
else
{
if (UseOpposite)
{
if (Position > 0 && crossDown)
SellMarket();
else if (Position < 0 && crossUp)
BuyMarket();
}
}
if (UseTradeManagement && Position != 0)
{
var tp = _entryPrice * (1 + (Position > 0 ? TakeProfit : -TakeProfit) / 100m);
var sl = _entryPrice * (1 - (Position > 0 ? StopLoss : -StopLoss) / 100m);
if (Position > 0)
{
if (candle.ClosePrice >= tp || candle.ClosePrice <= sl)
SellMarket();
}
else if (Position < 0)
{
if (candle.ClosePrice <= tp || candle.ClosePrice >= sl)
BuyMarket();
}
}
}
}
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 ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class ultimate_t3_fibonacci_btc_scalping_strategy(Strategy):
def __init__(self):
super(ultimate_t3_fibonacci_btc_scalping_strategy, self).__init__()
self._t3_length = self.Param("T3Length", 33) \
.SetDisplay("T3 Length", "Main T3 length", "General")
self._t3_fibo_length = self.Param("T3FiboLength", 19) \
.SetDisplay("T3 Fibo Length", "Fibonacci T3 length", "General")
self._use_opposite = self.Param("UseOpposite", True) \
.SetDisplay("Use Opposite", "Close on opposite signal", "General")
self._use_trade_management = self.Param("UseTradeManagement", True) \
.SetDisplay("Use Trade Management", "Enable TP/SL", "General")
self._take_profit = self.Param("TakeProfit", 15.0) \
.SetDisplay("Take Profit %", "Take profit percentage", "Risk")
self._stop_loss = self.Param("StopLoss", 2.0) \
.SetDisplay("Stop Loss %", "Stop loss percentage", "Risk")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Type of candles", "General")
self._entry_price = 0.0
self._prev_t3 = 0.0
self._prev_t3_fibo = 0.0
@property
def t3_length(self):
return self._t3_length.Value
@property
def t3_fibo_length(self):
return self._t3_fibo_length.Value
@property
def use_opposite(self):
return self._use_opposite.Value
@property
def use_trade_management(self):
return self._use_trade_management.Value
@property
def take_profit(self):
return self._take_profit.Value
@property
def stop_loss(self):
return self._stop_loss.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(ultimate_t3_fibonacci_btc_scalping_strategy, self).OnReseted()
self._entry_price = 0.0
self._prev_t3 = 0.0
self._prev_t3_fibo = 0.0
def OnStarted2(self, time):
super(ultimate_t3_fibonacci_btc_scalping_strategy, self).OnStarted2(time)
t3 = ExponentialMovingAverage()
t3.Length = self.t3_length
t3_fibo = ExponentialMovingAverage()
t3_fibo.Length = self.t3_fibo_length
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(t3, t3_fibo, self.on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def on_process(self, candle, t3, t3_fibo):
if candle.State != CandleStates.Finished:
return
cross_up = self._prev_t3_fibo <= self._prev_t3 and t3_fibo > t3
cross_down = self._prev_t3_fibo >= self._prev_t3 and t3_fibo < t3
self._prev_t3 = t3
self._prev_t3_fibo = t3_fibo
if cross_up and self.Position <= 0:
self.BuyMarket()
self._entry_price = candle.ClosePrice
elif cross_down and self.Position >= 0:
self.SellMarket()
self._entry_price = candle.ClosePrice
else:
if self.use_opposite:
if self.Position > 0 and cross_down:
self.SellMarket()
elif self.Position < 0 and cross_up:
self.BuyMarket()
if self.use_trade_management and self.Position != 0:
tp_sign = self.take_profit if self.Position > 0 else -self.take_profit
sl_sign = self.stop_loss if self.Position > 0 else -self.stop_loss
tp = self._entry_price * (1 + tp_sign / 100.0)
sl = self._entry_price * (1 - sl_sign / 100.0)
if self.Position > 0:
if candle.ClosePrice >= tp or candle.ClosePrice <= sl:
self.SellMarket()
elif self.Position < 0:
if candle.ClosePrice <= tp or candle.ClosePrice >= sl:
self.BuyMarket()
def CreateClone(self):
return ultimate_t3_fibonacci_btc_scalping_strategy()