Overall Statistics
Total Trades
669
Average Win
0.19%
Average Loss
-0.14%
Annual Return
0.622%
Drawdown
10.500%
Expectancy
0.132
Net Profit
12.777%
Sharpe Ratio
0.3
Loss Rate
52%
Win Rate
48%
Profit-Loss Ratio
1.34
Trade Frequency
Weekly trades
using System;
using System.Collections;
using System.Collections.Generic; 

namespace QuantConnect 
{
    using QuantConnect.Securities;
    using QuantConnect.Models; 

    public partial class BasicTemplateAlgorithm : QCAlgorithm, IAlgorithm 
    { 

        string symbol = "MSFT";        
        
        bool initialized = false;
        int numTrackers = 80;
        decimal[] movingAverages;
        decimal[] multipliers;
        bool[,] direction;
        decimal[,] movingAverageGain;
        decimal[,] crossPrice;
        decimal gainMultiplier = .2m;
        int[,] crossCount;
        
        int bestI = -1;
        int bestJ = -1;
        //Initialize the data and resolution you require for your strategy:
        public override void Initialize() 
        {            
            //Initialize the start, end dates for simulation; cash and data required.
            SetStartDate(2000, 01, 01);
            SetEndDate(DateTime.Now.Date.AddDays(-1)); 
            SetCash(30000); //Starting Cash in USD.
            AddSecurity(SecurityType.Equity, symbol, Resolution.Minute); //Minute, Second or Tick
            SetRunMode(RunMode.Series); //Series or Parallel for intraday strategies.
            
            movingAverages = new decimal[numTrackers];
            multipliers = new decimal[numTrackers];
            direction = new bool[numTrackers, numTrackers];
            movingAverageGain = new decimal[numTrackers, numTrackers];
            crossPrice = new decimal[numTrackers, numTrackers];
            crossCount = new int[numTrackers, numTrackers];
            
            decimal multiplier = 1;
            for (int i = 0; i < numTrackers; i++) {
                multiplier *= .9m;
                multipliers[i] = multiplier;
            }
        }

        //Handle TradeBar Events: a TradeBar occurs on a time-interval (second or minute bars)
        public override void OnTradeBar(Dictionary<string, TradeBar> data) 
        {
            decimal lastPrice = data[symbol].Close;
            if (initialized) {
                for (int i = 0; i < numTrackers; i++) {
                    movingAverages[i] += (lastPrice - movingAverages[i]) * multipliers[i];
                }
                for (int i = 0; i < numTrackers; i++) {
                    for (int j = 0; j < numTrackers; j++) {
                        bool newDirection = movingAverages[i] > movingAverages[j];
                        if (direction[i, j] != newDirection) {
                            decimal diff = (lastPrice - crossPrice[i, j]) / crossPrice[i, j];
                            if (newDirection) {
                                movingAverageGain[i, j] += (-diff - movingAverageGain[i, j]) * gainMultiplier;
                            } else {
                                movingAverageGain[i, j] += (diff - movingAverageGain[i, j]) * gainMultiplier;
                            }
                            if (i == bestI && j == bestJ) {
                                Debug(bestI + ", " + bestJ + ": " + movingAverageGain[i, j]);
                                if (newDirection) {
                                    if (Portfolio.HoldStock) {
                                        Order(symbol, -200);
                                    }
                                } else {
                                    if (!Portfolio.HoldStock) {
                                        Order(symbol, 200);
                                    }
                                }
                            }
                            direction[i, j] = newDirection;
                            crossPrice[i, j] = lastPrice;
                            crossCount[i, j]++;
                        }
                    }
                }
                decimal maxGain = 0;
                for (int i = 0; i < numTrackers; i++) {
                    for (int j = 0; j < numTrackers; j++) {
                        if (movingAverageGain[i, j] > maxGain && crossCount[i, j] > 5 && i < j) {
                            maxGain = movingAverageGain[i, j];
                            bestI = i;
                            bestJ = j;
                        }
                    }
                }
            } else {
                for (int i = 0; i < numTrackers; i++) {
                    movingAverages[i] = lastPrice;
                }
                for (int i = 0; i < numTrackers; i++) {
                    for (int j = 0; j < numTrackers; j++) {
                        direction[i, j] = movingAverages[i] > movingAverages[j];
                        crossPrice[i, j] = lastPrice;
                    }
                }
                initialized = true;
            }
        }
    }
}