Overall Statistics
Total Orders
73
Average Win
14.59%
Average Loss
-6.85%
Compounding Annual Return
7.191%
Drawdown
37.200%
Expectancy
0.826
Start Equity
100000
End Equity
570416.44
Net Profit
470.416%
Sharpe Ratio
0.262
Sortino Ratio
0.231
Probabilistic Sharpe Ratio
0.022%
Loss Rate
42%
Win Rate
58%
Profit-Loss Ratio
2.13
Alpha
0.014
Beta
0.413
Annual Standard Deviation
0.14
Annual Variance
0.02
Information Ratio
-0.112
Tracking Error
0.167
Treynor Ratio
0.089
Total Fees
$744.84
Estimated Strategy Capacity
$75000000.00
Lowest Capacity Asset
QQQ RIWIV7K5Z9LX
Portfolio Turnover
0.80%
#region imports
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Linq;
    using System.Globalization;
    using System.Drawing;
    using QuantConnect;
    using QuantConnect.Algorithm.Framework;
    using QuantConnect.Algorithm.Framework.Selection;
    using QuantConnect.Algorithm.Framework.Alphas;
    using QuantConnect.Algorithm.Framework.Portfolio;
    using QuantConnect.Algorithm.Framework.Portfolio.SignalExports;
    using QuantConnect.Algorithm.Framework.Execution;
    using QuantConnect.Algorithm.Framework.Risk;
    using QuantConnect.Algorithm.Selection;
    using QuantConnect.Api;
    using QuantConnect.Parameters;
    using QuantConnect.Benchmarks;
    using QuantConnect.Brokerages;
    using QuantConnect.Commands;
    using QuantConnect.Configuration;
    using QuantConnect.Util;
    using QuantConnect.Interfaces;
    using QuantConnect.Algorithm;
    using QuantConnect.Indicators;
    using QuantConnect.Data;
    using QuantConnect.Data.Auxiliary;
    using QuantConnect.Data.Consolidators;
    using QuantConnect.Data.Custom;
    using QuantConnect.Data.Custom.IconicTypes;
    using QuantConnect.DataSource;
    using QuantConnect.Data.Fundamental;
    using QuantConnect.Data.Market;
    using QuantConnect.Data.Shortable;
    using QuantConnect.Data.UniverseSelection;
    using QuantConnect.Notifications;
    using QuantConnect.Orders;
    using QuantConnect.Orders.Fees;
    using QuantConnect.Orders.Fills;
    using QuantConnect.Orders.OptionExercise;
    using QuantConnect.Orders.Slippage;
    using QuantConnect.Orders.TimeInForces;
    using QuantConnect.Python;
    using QuantConnect.Scheduling;
    using QuantConnect.Securities;
    using QuantConnect.Securities.Equity;
    using QuantConnect.Securities.Future;
    using QuantConnect.Securities.Option;
    using QuantConnect.Securities.Positions;
    using QuantConnect.Securities.Forex;
    using QuantConnect.Securities.Crypto;
    using QuantConnect.Securities.CryptoFuture;
    using QuantConnect.Securities.IndexOption;
    using QuantConnect.Securities.Interfaces;
    using QuantConnect.Securities.Volatility;
    using QuantConnect.Storage;
    using QuantConnect.Statistics;
    using QCAlgorithmFramework = QuantConnect.Algorithm.QCAlgorithm;
    using QCAlgorithmFrameworkBridge = QuantConnect.Algorithm.QCAlgorithm;
    using Calendar = QuantConnect.Data.Consolidators.Calendar;
#endregion
namespace QuantConnect.Algorithm.CSharp
{
    public class VirtualLightBrownGalago : QCAlgorithm
    {
        // Add some class members
        private Symbol _symbol;
        private bool indicatorsReady = false;
        private RateOfChange oneMonth, threeMonth, sixMonth, twelveMonth;
        private Momentum dema50_returns;
        private IDataConsolidator _consolidatorMonthly, _consolidatorDaily;
        private ExponentialMovingAverage dema50, ema50;
        private decimal fundx, stormGuard;
        private List<decimal> eqtyCurveOneMonth, eqtyCurveThreeMonth, eqtyCurveSixMonth, eqtyCurveTwelveMonth;
        private bool holdStockOneMonth = false, holdStockThreeMonth = false, holdStockSixMonth = false, holdStockTwelveMonth = false;
        public override void Initialize()
        {
            SetStartDate(2000, 4, 30);
            SetEndDate(2025, 5, 20);
            SetCash(100000m);
            eqtyCurveOneMonth = new List<decimal>();
            eqtyCurveOneMonth.Add(100000m);
            eqtyCurveThreeMonth = new List<decimal>();
            eqtyCurveThreeMonth.Add(100000m);
            eqtyCurveSixMonth = new List<decimal>();
            eqtyCurveSixMonth.Add(100000m);
            eqtyCurveTwelveMonth = new List<decimal>();
            eqtyCurveTwelveMonth.Add(100000m);
            UniverseSettings.DataNormalizationMode = DataNormalizationMode.Adjusted;
            // In Initialize, subscribe to a security, create the consolidator, and register it for automatic updates
            _symbol = AddEquity("QQQ", Resolution.Minute).Symbol;
            SetBenchmark(_symbol);
            oneMonth = new RateOfChange(1);
            threeMonth = new RateOfChange(3);
            sixMonth = new RateOfChange(6);
            twelveMonth = new RateOfChange(12);
            dema50_returns = new Momentum(21);
            ema50 = IndicatorExtensions.Of(new ExponentialMovingAverage(21,0.02m), dema50_returns);
            dema50 = IndicatorExtensions.Of(new ExponentialMovingAverage(21,0.02m), ema50);
            _consolidatorMonthly = Consolidate(_symbol, Calendar.Monthly, ConsolidationHandler);
            
            _consolidatorDaily = Consolidate(_symbol, TimeSpan.FromDays(1), DailyConsolidationHandler);
            
            // Feed in 100 trading days worth of data before the start date
            SetWarmUp(252+18, Resolution.Daily);
        }

        // Notify yourself when the algorithm is ready to begin trading.
        public override void OnWarmupFinished()
        {
            Log("Algorithm Ready");
        }

         // Define the consolidation handler
        void DailyConsolidationHandler(TradeBar consolidatedBar)
        {
            dema50_returns.Update(consolidatedBar);
            ema50.Update(dema50_returns.Current);
            dema50.Update(ema50.Current);

        }

        // Define the consolidation handler
        void ConsolidationHandler(TradeBar consolidatedBar)
        {
            Plot("MonthlyBars", "SPYMonthly", consolidatedBar);
            oneMonth.Update(consolidatedBar);
            threeMonth.Update(consolidatedBar);
            sixMonth.Update(consolidatedBar);
            twelveMonth.Update(consolidatedBar);

            if (oneMonth.IsReady) {
                Plot("ROCR", "oneMonth", oneMonth.Current.Value);
            }
            if (threeMonth.IsReady) {
                Plot("ROCR", "threeMonth", threeMonth.Current.Value);
            }
            if (sixMonth.IsReady) {
                Plot("ROCR", "sixMonth", sixMonth.Current.Value);
            }
            if (twelveMonth.IsReady) {
                Plot("ROCR", "twelveMonth", twelveMonth.Current.Value);
            }
            if (oneMonth.IsReady && threeMonth.IsReady && sixMonth.IsReady && twelveMonth.IsReady) {
                indicatorsReady = true;

                if (!IsWarmingUp) {
                if (holdStockOneMonth) {
                    eqtyCurveOneMonth.Add(eqtyCurveOneMonth.Last()*consolidatedBar.Close/consolidatedBar.Open);
                } else {
                    eqtyCurveOneMonth.Add(eqtyCurveOneMonth.Last());
                }
                Plot("Strategy eqts","1monthEquityCurve",eqtyCurveOneMonth.Last());

                holdStockOneMonth = oneMonth.Current.Value > 0;

                if (holdStockThreeMonth) {
                    eqtyCurveThreeMonth.Add(eqtyCurveThreeMonth.Last()*consolidatedBar.Close/consolidatedBar.Open);
                } else {
                    eqtyCurveThreeMonth.Add(eqtyCurveThreeMonth.Last());
                }
                Plot("Strategy eqts","3monthEquityCurve",eqtyCurveThreeMonth.Last());

                holdStockThreeMonth = threeMonth.Current.Value > 0;

                if (holdStockSixMonth) {
                    eqtyCurveSixMonth.Add(eqtyCurveSixMonth.Last()*consolidatedBar.Close/consolidatedBar.Open);
                } else {
                    eqtyCurveSixMonth.Add(eqtyCurveSixMonth.Last());
                }
                Plot("Strategy eqt2","6monthEquityCurve",eqtyCurveSixMonth.Last());

                holdStockSixMonth = sixMonth.Current.Value > 0;


                if (holdStockTwelveMonth) {
                    eqtyCurveTwelveMonth.Add(eqtyCurveTwelveMonth.Last()*consolidatedBar.Close/consolidatedBar.Open);
                } else {
                    eqtyCurveTwelveMonth.Add(eqtyCurveTwelveMonth.Last());
                }
                Plot("Strategy eqts2","12monthEquityCurve",eqtyCurveTwelveMonth.Last());

                holdStockTwelveMonth = twelveMonth.Current.Value > 0;

                int lookback_for_optim = 2;
                decimal delta1month = eqtyCurveOneMonth.Last()/eqtyCurveOneMonth[eqtyCurveOneMonth.Count - lookback_for_optim]-1;
                decimal delta3month = eqtyCurveThreeMonth.Last()/eqtyCurveThreeMonth[eqtyCurveThreeMonth.Count - lookback_for_optim]-1;
                decimal delta6month = eqtyCurveSixMonth.Last()/eqtyCurveSixMonth[eqtyCurveSixMonth.Count - lookback_for_optim]-1;
                decimal delta12month = eqtyCurveTwelveMonth.Last()/eqtyCurveTwelveMonth[eqtyCurveTwelveMonth.Count - lookback_for_optim]-1;

                decimal maxCurveBetween12And6 = decimal.Max(delta12month,delta6month);
                decimal maxCurveBetween1And3 = decimal.Max(delta1month,delta3month);
                decimal maxCurveBetween1and12 = decimal.Max(maxCurveBetween12And6,maxCurveBetween1And3);
                decimal w1=0m,w3=0m,w6=0m,w12=0m;
                if (maxCurveBetween1and12 == delta12month)
                    w12=1m;
                else if (maxCurveBetween1and12 == delta6month)
                    w6=1m;
                else if (maxCurveBetween1and12 == delta3month)
                    w3=1m;
                else if (maxCurveBetween1and12 == delta1month)
                    w1=1m;
                
                fundx = w1*oneMonth.Current.Value+w3*threeMonth.Current.Value+w6*sixMonth.Current.Value+w12*twelveMonth.Current.Value;
                Plot("Timers", "fundx", fundx);
                }
            }

            if (dema50.IsReady) {
                stormGuard = dema50.Current.Value;
                Plot("Timers", "stormGuard", dema50.Current.Value);
            }
            if (oneMonth.IsReady && threeMonth.IsReady && sixMonth.IsReady && twelveMonth.IsReady && dema50.IsReady) {
    
                int fundx_timer = 0;
                if (fundx > 0) fundx_timer = 1;
                int stormGuard_timer = 0;
                if (stormGuard > 0) stormGuard_timer = 1;

                Plot("Signals", "fundx_timer", fundx_timer);
                Plot("Signals", "stormGuard_timer", stormGuard_timer);


            }
        }
        /// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
        /// Slice object keyed by symbol containing the stock data
        public override void OnData(Slice data)
        {
            if (!indicatorsReady) return;
            if (fundx > 0) {
                if (!Portfolio.Invested )
                {
                    SetHoldings(_symbol, 1m);
                }
            } else {
                if (Portfolio.Invested)
                    Liquidate();
            }
        }
    }
}