Overall Statistics
Total Trades
2273
Average Win
0.25%
Average Loss
-0.23%
Compounding Annual Return
7.848%
Drawdown
13.400%
Expectancy
-0.019
Net Profit
19.952%
Sharpe Ratio
0.666
Loss Rate
53%
Win Rate
47%
Profit-Loss Ratio
1.11
Alpha
NaN
Beta
NaN
Annual Standard Deviation
0.125
Annual Variance
0.016
Information Ratio
NaN
Tracking Error
NaN
Treynor Ratio
NaN
Total Fees
$2284.88
/*
 * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals.
 * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); 
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
*/

namespace QuantConnect
{
	public class BasicLaguerre : QCAlgorithm
    {
        public static string[] symbols = { "AAPL", "AMZN", "FB", "GE", "GOOGL", "JNJ", "JPM",
                                           "MSFT", "NVS", "PFE", "PG", "PTR", "TM", "VZ", "WFC" };

        public static double LaguerreFactor = 0.4;
        Dictionary<string, Laguerre> Strategy = new Dictionary<string, Laguerre>();

        public override void Initialize()
        {
            SetStartDate(2013, 1, 1);  //Set Start Date
            SetEndDate(2015, 5, 31);    //Set End Date
            SetCash(100000);             //Set Strategy Cash
            // Find more symbols here: http://quantconnect.com/data
            foreach (string symbol in symbols)
            {
                AddSecurity(SecurityType.Equity, symbol, Resolution.Minute);
                Strategy.Add(symbol, new Laguerre(LaguerreFactor));
            }
        }
        /// <summary>
        /// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
        /// </summary>
        /// <param name="data">TradeBars IDictionary object with your stock data</param>
        public void OnData(TradeBars data)
        {
            foreach (string symbol in symbols)
            {
                Strategy[symbol].Add(data[symbol].Price);
                if (Strategy[symbol].Signal != 0)
                {
                    bool longSignal = (Strategy[symbol].Signal == 1) ? true : false;
                    bool shortSignal = (Strategy[symbol].Signal == -1) ? true : false;
                    if (!Portfolio[symbol].HoldStock)
                    {
                        SetHoldings(symbol, Strategy[symbol].Signal * 0.25);
                    }
                    else
                    {
                        if (Portfolio[symbol].IsLong && shortSignal) Liquidate(symbol);
                        if (Portfolio[symbol].IsShort && longSignal) Liquidate(symbol);
                    }
                }
            }
        }
    }
}
namespace QuantConnect
{
    class Laguerre
    {
        decimal factor;                       // the factor constant
        decimal tolerance = 0.09m;
        decimal[] previousL = new decimal[4]; // contains the previous values of the L series
        decimal[] actualL = new decimal[4];   // contains the previous values of the L series
        decimal previousLaguerre;
        decimal actualLaguerre;
        decimal actualFIR;
        decimal previousFIR;
        int signal = 0;

        public decimal PreviousLaguerre
        {
            get { return previousLaguerre; }
            set { previousLaguerre = value; }
        }

        public decimal ActualLaguerre
        {
            get { return actualLaguerre; }
        }

        public decimal ActualFIR
        {
            get { return actualFIR; }
        }

        RollingWindow<decimal> windowFIR = new RollingWindow<decimal>(4);

        public bool IsReady()
        {
            return windowFIR.IsReady;
        }

        public int Signal
        {
            get { return signal; }
        }
        
        
        
        public Laguerre(double Factor)
        {
            factor = new decimal(Factor);
        }


        /// <summary>
        /// Adds the last value and estimate the Laguerre and FIR indicators.
        /// </summary>
        /// <param name="lastValue">The last value.</param>
        /// <returns>Void.</returns>
        public void Add(decimal lastValue)
        {
            if (windowFIR.Count == 0)
            {
                for (int i = 0; i < previousL.Length; i++) previousL[i] = lastValue;
                previousLaguerre = lastValue;
                previousFIR = lastValue;
                windowFIR.Add(lastValue);
            }
            CalculateNextValue(lastValue);
            CheckCross(previousLaguerre, actualLaguerre, previousFIR, actualFIR);
            previousLaguerre = actualLaguerre;
            previousFIR = actualFIR;
            for (int i = 0; i < actualL.Length; i++) previousL[i] = actualL[i];
        }

        private void CalculateNextValue(decimal lastValue)
        {
            // Estimate L0
            actualL[0] = (1m - factor) * lastValue + factor * previousL[0];
            // Estimate L1 to L3
            for (int i = 1; i < 4; i++)
            {
                actualL[i] = - factor * actualL[i - 1] + previousL[i - 1] + factor * previousL[i];
            }
            actualLaguerre = (actualL[3] + 2 * actualL[2] + 2 * actualL[1] + actualL[0]) / 6;
            

            // Update the Fir window.
            windowFIR.Add(lastValue);
            if (windowFIR.IsReady)
            {
                actualFIR = (windowFIR[3] + 2 * windowFIR[2] + 2 * windowFIR[1] + windowFIR[0]) / 6;
            }
            else
            {
                actualFIR = lastValue;
            }
        }

        private void CheckCross(decimal prevLaguerre, decimal actLaguerre, decimal prevFir, decimal actFIR)
        {
            decimal prevOscilator = prevLaguerre - prevFir;
            decimal actualOscilator = actLaguerre - actFIR;
            
            if (prevOscilator - tolerance > 0 && actualOscilator + tolerance < 0) signal = 1;
            else if (prevOscilator + tolerance < 0 && actualOscilator - tolerance > 0) signal = -1;
            else signal = 0;

        }

    }
}