Overall Statistics |
Total Trades 910 Average Win 0.42% Average Loss -0.33% Compounding Annual Return 20.970% Drawdown 39.400% Expectancy 1.096 Net Profit 1116.155% Sharpe Ratio 0.869 Probabilistic Sharpe Ratio 20.349% Loss Rate 8% Win Rate 92% Profit-Loss Ratio 1.28 Alpha 0.024 Beta 1.198 Annual Standard Deviation 0.184 Annual Variance 0.034 Information Ratio 0.845 Tracking Error 0.055 Treynor Ratio 0.134 Total Fees $954.47 Estimated Strategy Capacity $320000.00 Lowest Capacity Asset DBP TP2MIF0KNIAT |
using System; using System.Collections; using System.Collections.Generic; using System.Linq; using Common.Logging.Factory; using QuantConnect.Data; using QuantConnect.Indicators; using QuantConnect.Orders; using QuantConnect.Securities; using QuantConnect.Util; namespace QuantConnect.Algorithm.CSharp { public class AllWeather : QCAlgorithm { private Strat[] _strategies; public override void Initialize() { SetStartDate(2009, 1, 1); SetCash(100000); var weightings = new (string Sector, Weighting Target)[] { ("Industrial", new("SPY", 0.35m)), ("Metals", new("DBP", 0.10m)), ("Crypto", new("GBTC", 0.35m)), ("China", new("GXC", 0.06m)), ("Tech", new("XLK", 0.16m)), ("Energy", new("XLE", 0.09m)), ("Finance", new("XLF", 0.08m)), ("Health", new("XLV", 0.07m)), ("Fixed", new("TLT", 0.15m)) }; var coreInvestor = new LongFixedRatio(weightings.Select(x => x.Target), leverage: 3.3m); Schedule.On(DateRules.MonthStart(), TimeRules.At(10, 00), coreInvestor.ScheduleRebalance); _strategies = new[] { coreInvestor }; foreach (var inv in _strategies) { foreach (var sym in inv.Symbols) { var equity = AddEquity(sym, Resolution.Daily); equity.SetDataNormalizationMode(DataNormalizationMode.Raw); } } } public override void OnData(Slice data) { Plot("Values", "Margin Remaining", Portfolio.MarginRemaining / Portfolio.TotalPortfolioValue); Plot("Values", "Margin Used", Portfolio.TotalMarginUsed / Portfolio.TotalPortfolioValue); foreach (var inv in _strategies) { inv.OnData(this, data); } } } internal interface Strat { public decimal Leverage { get; } public IEnumerable<Symbol> Symbols { get; } public void OnData(QCAlgorithm algo, Slice slice); } internal class LongFixedRatio : Strat { private readonly Weighting[] _weightings; private bool _shouldRebalance = true; public decimal Leverage { get; } public IEnumerable<Symbol> Symbols => _weightings.Select(x => x.Symbol); public LongFixedRatio(IEnumerable<Weighting> weightings, decimal leverage) { _weightings = weightings.ToArray(); Leverage = leverage; } public void ScheduleRebalance() { _shouldRebalance = true; } public void OnData(QCAlgorithm algo, Slice slice) { if (_shouldRebalance) { var P = algo.Portfolio; var validWeightings = _weightings.Where(w => slice.Bars.ContainsKey(w.Symbol)).ToArray(); var totalWeight = validWeightings.Select(w => w.Weight).Sum(); var realizedWeightings = validWeightings.Select(x => x with { Weight = x.Weight / totalWeight }); var totalMargin = 2 * P.TotalMarginUsed + P.MarginRemaining; foreach (var wt in realizedWeightings) { var close = slice.Bars[wt.Symbol].Close; int goalQty = (int)Math.Truncate(0.9m * totalMargin * wt.Weight / close); var currentQty = (int)P[wt.Symbol].Quantity; int toBuyQty = goalQty - currentQty; algo.Plot("Space", wt.Symbol, (P.MarginRemaining - toBuyQty * close) / P.TotalPortfolioValue); algo.LimitOrder(wt.Symbol, toBuyQty, close); } _shouldRebalance = false; } } } record Weighting(Symbol Symbol, decimal Weight) { public Weighting(string symbol, decimal weight) : this(Symbol.Create(symbol, SecurityType.Equity, Market.USA), weight) { } } }