Overall Statistics
Total Trades
179
Average Win
7.77%
Average Loss
-3.10%
Compounding Annual Return
69.426%
Drawdown
27.400%
Expectancy
1.085
Net Profit
974.543%
Sharpe Ratio
1.709
Loss Rate
41%
Win Rate
59%
Profit-Loss Ratio
2.51
Alpha
0.565
Beta
0.115
Annual Standard Deviation
0.329
Annual Variance
0.108
Information Ratio
1.558
Tracking Error
0.381
Treynor Ratio
4.88
Total Fees
$0.00
// Accord Machine Learning Library
// The Accord.NET Framework
// http://accord-framework.net
//
// AForge Machine Learning Library
// AForge.NET framework
//
// Copyright © Andrew Kirillov, 2007-2008
// andrew.kirillov@gmail.com
//
// Copyright © César Souza, 2009-2017
// cesarsouza at gmail.com
//
//    This library is free software; you can redistribute it and/or
//    modify it under the terms of the GNU Lesser General Public
//    License as published by the Free Software Foundation; either
//    version 2.1 of the License, or (at your option) any later version.
//
//    This library is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//    Lesser General Public License for more details.
//
//    You should have received a copy of the GNU Lesser General Public
//    License along with this library; if not, write to the Free Software
//    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
//

namespace QuantConnect.Algorithm.CSharp
{
    using Newtonsoft.Json;
    using System;
    using System.Linq;

    public class RepeatingQLearning : QLearning
    {
        public RepeatingQLearning(int states, int actions, IExplorationPolicy explorationPolicy)
            : this(states, actions, explorationPolicy, true)
        {

        }

        public RepeatingQLearning(int states, int actions, IExplorationPolicy explorationPolicy, bool randomize)
            : base(states, actions, explorationPolicy, randomize)
        {
        }

        protected override double GetUpdateStep(int state, int action)
        {
            double[] actionEstimations = qvalues[state];
            double sum = 0;

            for (int i = 0; i < actionEstimations.Length; i++)
            {
                sum += actionEstimations[i];
            }

            double actionProbability = actionEstimations[action] / sum;

            double exponent = 1 / actionProbability;
            return 1 - Math.Pow(1 - learningRate, exponent);
        }
    }

    public class DynaQ : QLearning
    {
        private readonly Random _rng = new Random();

        [JsonProperty]
        private readonly double[][] rewards;

        [JsonProperty]
        private readonly int[][][] stateActionCount;

        public DynaQ(int states, int actions, IExplorationPolicy explorationPolicy)
            : this(states, actions, explorationPolicy, true)
        {

        }

        public DynaQ(int states, int actions, IExplorationPolicy explorationPolicy, bool randomize)
            : base(states, actions, explorationPolicy, randomize)
        {
            rewards = new double[states][];
            stateActionCount = new int[states][][];

            for (int i = 0; i < states; i++)
            {
                rewards[i] = new double[actions];
                stateActionCount[i] = new int[actions][];

                for (int j = 0; j < actions; ++j)
                {
                    stateActionCount[i][j] = new int[states];
                }
            }
        }

        public void Hallucinate(int previousState, int action, double reward, int nextState, int numHallucinations)
        {
            stateActionCount[previousState][action][nextState] += 1;
            rewards[previousState][action] = (1 - LearningRate) * rewards[previousState][action] + LearningRate * reward;

            for (int k = 0; k < numHallucinations; ++k)
            {
                Hallucinate();
            }
        }

        private void Hallucinate()
        {
            int pastState = _rng.Next(StatesCount);
            int action = _rng.Next(ActionsCount);
            double reward = rewards[pastState][action];

            var transitions = stateActionCount[pastState][action];

            int countSum = transitions.Sum();
            int nextState;

            if (countSum > 0)
            {
                nextState = 0;
                var r = _rng.Next(countSum);

                for (int n = transitions.Length - 1; nextState < n; ++nextState)
                {
                    var count = transitions[nextState];
                    if (r < count)
                        break;
                    r -= count;
                }
            }
            else
            {
                nextState = _rng.Next(StatesCount);
            }

            UpdateState(pastState, action, reward, nextState);
        }
    }

    /// <summary>
    /// QLearning learning algorithm.
    /// </summary>
    /// 
    /// <remarks>The class provides implementation of Q-Learning algorithm, known as
    /// off-policy Temporal Difference control.</remarks>
    /// 
    /// <seealso cref="Sarsa"/>
    /// 
    public class QLearning
    {
        // amount of possible states
        [JsonProperty]
        protected int states;

        // amount of possible actions
        [JsonProperty]
        protected int actions;

        // q-values
        [JsonProperty]
        protected double[][] qvalues;

        // exploration policy
        protected IExplorationPolicy explorationPolicy;

        // discount factor
        [JsonProperty]
        protected double discountFactor = 0.95;

        // learning rate
        [JsonProperty]
        protected double learningRate = 0.25;


        /// <summary>
        /// Amount of possible states.
        /// </summary>
        /// 
        public int StatesCount
        {
            get { return states; }
        }

        /// <summary>
        /// Amount of possible actions.
        /// </summary>
        /// 
        public int ActionsCount
        {
            get { return actions; }
        }

        /// <summary>
        /// Exploration policy.
        /// </summary>
        /// 
        /// <remarks>Policy, which is used to select actions.</remarks>
        /// 
        public IExplorationPolicy ExplorationPolicy
        {
            get { return explorationPolicy; }
            set { explorationPolicy = value; }
        }

        /// <summary>
        /// Learning rate, [0, 1].
        /// </summary>
        /// 
        /// <remarks>The value determines the amount of updates Q-function receives
        /// during learning. The greater the value, the more updates the function receives.
        /// The lower the value, the less updates it receives.</remarks>
        /// 
        public double LearningRate
        {
            get { return learningRate; }
            set
            {
                if (value < 0 || value > 1.0)
                    throw new ArgumentOutOfRangeException("Argument should be between 0 and 1.");
                learningRate = value;
            }
        }

        /// <summary>
        /// Discount factor, [0, 1].
        /// </summary>
        /// 
        /// <remarks>Discount factor for the expected summary reward. The value serves as
        /// multiplier for the expected reward. So if the value is set to 1,
        /// then the expected summary reward is not discounted. If the value is getting
        /// smaller, then smaller amount of the expected reward is used for actions'
        /// estimates update.</remarks>
        /// 
        public double DiscountFactor
        {
            get { return discountFactor; }
            set
            {
                if (value < 0 || value > 1.0)
                    throw new ArgumentOutOfRangeException("Discount factor should be between 0 and 1.");
                discountFactor = value;
            }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="QLearning"/> class.
        /// </summary>
        /// 
        /// <param name="states">Amount of possible states.</param>
        /// <param name="actions">Amount of possible actions.</param>
        /// <param name="explorationPolicy">Exploration policy.</param>
        /// 
        /// <remarks>Action estimates are randomized in the case of this constructor
        /// is used.</remarks>
        /// 
        public QLearning(int states, int actions, IExplorationPolicy explorationPolicy) :
            this(states, actions, explorationPolicy, true)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="QLearning"/> class.
        /// </summary>
        /// 
        /// <param name="states">Amount of possible states.</param>
        /// <param name="actions">Amount of possible actions.</param>
        /// <param name="explorationPolicy">Exploration policy.</param>
        /// <param name="randomize">Randomize action estimates or not.</param>
        /// 
        /// <remarks>The <b>randomize</b> parameter specifies if initial action estimates should be randomized
        /// with small values or not. Randomization of action values may be useful, when greedy exploration
        /// policies are used. In this case randomization ensures that actions of the same type are not chosen always.</remarks>
        /// 
        public QLearning(int states, int actions, IExplorationPolicy explorationPolicy, bool randomize)
        {
            this.states = states;
            this.actions = actions;
            this.explorationPolicy = explorationPolicy;

            // create Q-array
            qvalues = new double[states][];
            for (int i = 0; i < states; i++)
            {
                qvalues[i] = new double[actions];
            }

            // do randomization
            if (randomize)
            {
                Random rand = new Random();

                for (int i = 0; i < states; i++)
                {
                    for (int j = 0; j < actions; j++)
                    {
                        qvalues[i][j] = rand.NextDouble() / 10;
                    }
                }
            }
        }

        /// <summary>
        /// Get next action from the specified state.
        /// </summary>
        /// 
        /// <param name="state">Current state to get an action for.</param>
        /// 
        /// <returns>Returns the action for the state.</returns>
        /// 
        /// <remarks>The method returns an action according to current
        /// <see cref="ExplorationPolicy">exploration policy</see>.</remarks>
        /// 
        public int GetAction(int state)
        {
            return explorationPolicy.ChooseAction(qvalues[state]);
        }

        protected virtual double GetUpdateStep(int state, int action)
        {
            return learningRate;
        }

        /// <summary>
        /// Update Q-function's value for the previous state-action pair.
        /// </summary>
        /// 
        /// <param name="previousState">Previous state.</param>
        /// <param name="action">Action, which leads from previous to the next state.</param>
        /// <param name="reward">Reward value, received by taking specified action from previous state.</param>
        /// <param name="nextState">Next state.</param>
        /// 
        public void UpdateState(int previousState, int action, double reward, int nextState)
        {
            // next state's action estimations
            double[] nextActionEstimations = qvalues[nextState];

            // find maximum expected summary reward from the next state
            double maxNextExpectedReward = nextActionEstimations[0];

            for (int i = 1; i < actions; i++)
            {
                if (nextActionEstimations[i] > maxNextExpectedReward)
                    maxNextExpectedReward = nextActionEstimations[i];
            }

            // previous state's action estimations
            double[] previousActionEstimations = qvalues[previousState];

            // update expected summary reward of the previous state
            double alpha = GetUpdateStep(previousState, action);
            previousActionEstimations[action] *= (1.0 - alpha);
            previousActionEstimations[action] += (alpha * (reward + discountFactor * maxNextExpectedReward));
        }
    }

    /// <summary>
    /// Sarsa learning algorithm.
    /// </summary>
    /// 
    /// <remarks>The class provides implementation of Sarsa algorithm, known as
    /// on-policy Temporal Difference control.</remarks>
    /// 
    /// <seealso cref="QLearning"/>
    /// 
    public class Sarsa
    {
        // amount of possible states
        private int states;

        // amount of possible actions
        private int actions;

        // q-values
        private double[][] qvalues;

        // exploration policy
        private IExplorationPolicy explorationPolicy;

        // discount factor
        private double discountFactor = 0.95;

        // learning rate
        private double learningRate = 0.25;

        /// <summary>
        /// Amount of possible states.
        /// </summary>
        /// 
        public int StatesCount
        {
            get { return states; }
        }

        /// <summary>
        /// Amount of possible actions.
        /// </summary>
        /// 
        public int ActionsCount
        {
            get { return actions; }
        }

        /// <summary>
        /// Exploration policy.
        /// </summary>
        /// 
        /// <remarks>Policy, which is used to select actions.</remarks>
        /// 
        public IExplorationPolicy ExplorationPolicy
        {
            get { return explorationPolicy; }
            set { explorationPolicy = value; }
        }

        /// <summary>
        /// Learning rate, [0, 1].
        /// </summary>
        /// 
        /// <remarks>The value determines the amount of updates Q-function receives
        /// during learning. The greater the value, the more updates the function receives.
        /// The lower the value, the less updates it receives.</remarks>
        /// 
        public double LearningRate
        {
            get { return learningRate; }
            set
            {
                if (value < 0 || value > 1)
                    throw new ArgumentOutOfRangeException("Learning rate must be between 0 and 1.");
                learningRate = value;
            }
        }

        /// <summary>
        /// Discount factor, [0, 1].
        /// </summary>
        /// 
        /// <remarks>Discount factor for the expected summary reward. The value serves as
        /// multiplier for the expected reward. So if the value is set to 1,
        /// then the expected summary reward is not discounted. If the value is getting
        /// smaller, then smaller amount of the expected reward is used for actions'
        /// estimates update.</remarks>
        /// 
        public double DiscountFactor
        {
            get { return discountFactor; }
            set
            {
                if (value < 0 || value > 1)
                    throw new ArgumentOutOfRangeException("Discount factor must be between 0 and 1.");
                discountFactor = value;
            }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Sarsa"/> class.
        /// </summary>
        /// 
        /// <param name="states">Amount of possible states.</param>
        /// <param name="actions">Amount of possible actions.</param>
        /// <param name="explorationPolicy">Exploration policy.</param>
        /// 
        /// <remarks>Action estimates are randomized in the case of this constructor
        /// is used.</remarks>
        /// 
        public Sarsa(int states, int actions, IExplorationPolicy explorationPolicy) :
            this(states, actions, explorationPolicy, true)
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="Sarsa"/> class.
        /// </summary>
        /// 
        /// <param name="states">Amount of possible states.</param>
        /// <param name="actions">Amount of possible actions.</param>
        /// <param name="explorationPolicy">Exploration policy.</param>
        /// <param name="randomize">Randomize action estimates or not.</param>
        /// 
        /// <remarks>The <b>randomize</b> parameter specifies if initial action estimates should be randomized
        /// with small values or not. Randomization of action values may be useful, when greedy exploration
        /// policies are used. In this case randomization ensures that actions of the same type are not chosen always.</remarks>
        /// 
        public Sarsa(int states, int actions, IExplorationPolicy explorationPolicy, bool randomize)
        {
            this.states = states;
            this.actions = actions;
            this.explorationPolicy = explorationPolicy;

            // create Q-array
            qvalues = new double[states][];
            for (int i = 0; i < states; i++)
            {
                qvalues[i] = new double[actions];
            }

            // do randomization
            if (randomize)
            {
                Random rand = new Random();

                for (int i = 0; i < states; i++)
                {
                    for (int j = 0; j < actions; j++)
                    {
                        qvalues[i][j] = rand.NextDouble() / 10;
                    }
                }
            }
        }

        /// <summary>
        /// Get next action from the specified state.
        /// </summary>
        /// 
        /// <param name="state">Current state to get an action for.</param>
        /// 
        /// <returns>Returns the action for the state.</returns>
        /// 
        /// <remarks>The method returns an action according to current
        /// <see cref="ExplorationPolicy">exploration policy</see>.</remarks>
        /// 
        public int GetAction(int state)
        {
            return explorationPolicy.ChooseAction(qvalues[state]);
        }

        /// <summary>
        /// Update Q-function's value for the previous state-action pair.
        /// </summary>
        /// 
        /// <param name="previousState">Curren state.</param>
        /// <param name="previousAction">Action, which lead from previous to the next state.</param>
        /// <param name="reward">Reward value, received by taking specified action from previous state.</param>
        /// <param name="nextState">Next state.</param>
        /// <param name="nextAction">Next action.</param>
        /// 
        /// <remarks>Updates Q-function's value for the previous state-action pair in
        /// the case if the next state is non terminal.</remarks>
        /// 
        public void UpdateState(int previousState, int previousAction, double reward, int nextState, int nextAction)
        {
            // previous state's action estimations
            double[] previousActionEstimations = qvalues[previousState];

            // update expected summary reward of the previous state
            previousActionEstimations[previousAction] *= (1.0 - learningRate);
            previousActionEstimations[previousAction] += (learningRate * (reward + discountFactor *
                                                           qvalues[nextState][nextAction]));
        }

        /// <summary>
        /// Update Q-function's value for the previous state-action pair.
        /// </summary>
        /// 
        /// <param name="previousState">Curren state.</param>
        /// <param name="previousAction">Action, which lead from previous to the next state.</param>
        /// <param name="reward">Reward value, received by taking specified action from previous state.</param>
        /// 
        /// <remarks>Updates Q-function's value for the previous state-action pair in
        /// the case if the next state is terminal.</remarks>
        /// 
        public void UpdateState(int previousState, int previousAction, double reward)
        {
            // previous state's action estimations
            double[] previousActionEstimations = qvalues[previousState];

            // update expected summary reward of the previous state
            previousActionEstimations[previousAction] *= (1.0 - learningRate);
            previousActionEstimations[previousAction] += (learningRate * reward);
        }
    }
}
// Accord Machine Learning Library
// The Accord.NET Framework
// http://accord-framework.net
//
// AForge Machine Learning Library
// AForge.NET framework
//
// Copyright © Andrew Kirillov, 2007-2008
// andrew.kirillov@gmail.com
//
// Copyright © César Souza, 2009-2017
// cesarsouza at gmail.com
//
//    This library is free software; you can redistribute it and/or
//    modify it under the terms of the GNU Lesser General Public
//    License as published by the Free Software Foundation; either
//    version 2.1 of the License, or (at your option) any later version.
//
//    This library is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
//    Lesser General Public License for more details.
//
//    You should have received a copy of the GNU Lesser General Public
//    License along with this library; if not, write to the Free Software
//    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
//

namespace QuantConnect.Algorithm.CSharp
{
    using System;

    /// <summary>
    /// Exploration policy interface.
    /// </summary>
    /// 
    /// <remarks>The interface describes exploration policies, which are used in Reinforcement
    /// Learning to explore state space.</remarks>
    /// 
    public interface IExplorationPolicy
    {
        /// <summary>
        /// Choose an action.
        /// </summary>
        /// 
        /// <param name="actionEstimates">Action estimates.</param>
        /// 
        /// <returns>Returns selected action.</returns>
        /// 
        /// <remarks>The method chooses an action depending on the provided estimates. The
        /// estimates can be any sort of estimate, which values usefulness of the action
        /// (expected summary reward, discounted reward, etc).</remarks>
        /// 
        int ChooseAction(double[] actionEstimates);
    }

    /// <summary>
    /// Epsilon greedy exploration policy.
    /// </summary>
    /// 
    /// <remarks><para>The class implements epsilon greedy exploration policy. According to the policy,
    /// the best action is chosen with probability <b>1-epsilon</b>. Otherwise,
    /// with probability <b>epsilon</b>, any other action, except the best one, is
    /// chosen randomly.</para>
    /// 
    /// <para>According to the policy, the epsilon value is known also as exploration rate.</para>
    /// </remarks>
    /// 
    /// <seealso cref="RouletteWheelExploration"/>
    /// <seealso cref="BoltzmannExploration"/>
    /// <seealso cref="TabuSearchExploration"/>
    /// 
    public class EpsilonGreedyExploration : IExplorationPolicy
    {
        // exploration rate
        private double epsilon;

        // random number generator
        private Random rand = Accord.Math.Random.Generator.Random;

        /// <summary>
        /// Epsilon value (exploration rate), [0, 1].
        /// </summary>
        /// 
        /// <remarks><para>The value determines the amount of exploration driven by the policy.
        /// If the value is high, then the policy drives more to exploration - choosing random
        /// action, which excludes the best one. If the value is low, then the policy is more
        /// greedy - choosing the beat so far action.
        /// </para></remarks>
        /// 
        public double Epsilon
        {
            get { return epsilon; }
            set
            {
                if (value < 0 || value > 1.0)
                    throw new ArgumentOutOfRangeException("Epsilon should be between 0 and 1.");
                epsilon = value;
            }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="EpsilonGreedyExploration"/> class.
        /// </summary>
        /// 
        /// <param name="epsilon">Epsilon value (exploration rate).</param>
        /// 
        public EpsilonGreedyExploration(double epsilon)
        {
            Epsilon = epsilon;
        }

        /// <summary>
        /// Choose an action.
        /// </summary>
        /// 
        /// <param name="actionEstimates">Action estimates.</param>
        /// 
        /// <returns>Returns selected action.</returns>
        /// 
        /// <remarks>The method chooses an action depending on the provided estimates. The
        /// estimates can be any sort of estimate, which values usefulness of the action
        /// (expected summary reward, discounted reward, etc).</remarks>
        /// 
        public int ChooseAction(double[] actionEstimates)
        {
            // actions count
            int actionsCount = actionEstimates.Length;

            // find the best action (greedy)
            double maxReward = actionEstimates[0];
            int greedyAction = 0;

            for (int i = 1; i < actionsCount; i++)
            {
                if (actionEstimates[i] > maxReward)
                {
                    maxReward = actionEstimates[i];
                    greedyAction = i;
                }
            }

            // try to do exploration
            if (rand.NextDouble() < epsilon)
            {
                int randomAction = rand.Next(actionsCount - 1);

                if (randomAction >= greedyAction)
                    randomAction++;

                return randomAction;
            }

            return greedyAction;
        }
    }

    /// <summary>
    /// Roulette wheel exploration policy.
    /// </summary>
    /// 
    /// <remarks><para>The class implements roulette whell exploration policy. Acording to the policy,
    /// action <b>a</b> at state <b>s</b> is selected with the next probability:</para>
    /// <code lang="none">
    ///                   Q( s, a )
    /// p( s, a ) = ------------------
    ///              SUM( Q( s, b ) )
    ///               b
    /// </code>
    /// <para>where <b>Q(s, a)</b> is action's <b>a</b> estimation (usefulness) at state <b>s</b>.</para>
    /// 
    /// <para><note>The exploration policy may be applied only in cases, when action estimates (usefulness)
    /// are represented with positive value greater then 0.</note></para>
    /// </remarks>
    /// 
    /// <seealso cref="BoltzmannExploration"/>
    /// <seealso cref="EpsilonGreedyExploration"/>
    /// <seealso cref="TabuSearchExploration"/>
    /// 
    public class RouletteWheelExploration : IExplorationPolicy
    {
        // random number generator
        private Random rand = Accord.Math.Random.Generator.Random;

        /// <summary>
        /// Initializes a new instance of the <see cref="RouletteWheelExploration"/> class.
        /// </summary>
        /// 
        public RouletteWheelExploration() { }

        /// <summary>
        /// Choose an action.
        /// </summary>
        /// 
        /// <param name="actionEstimates">Action estimates.</param>
        /// 
        /// <returns>Returns selected action.</returns>
        /// 
        /// <remarks>The method chooses an action depending on the provided estimates. The
        /// estimates can be any sort of estimate, which values usefulness of the action
        /// (expected summary reward, discounted reward, etc).</remarks>
        /// 
        public int ChooseAction(double[] actionEstimates)
        {
            // actions count
            int actionsCount = actionEstimates.Length;

            // actions sum
            double sum = 0, estimateSum = 0;

            for (int i = 0; i < actionsCount; i++)
            {
                estimateSum += actionEstimates[i];
            }

            // get random number, which determines which action to choose
            double actionRandomNumber = rand.NextDouble();

            for (int i = 0; i < actionsCount; i++)
            {
                sum += actionEstimates[i] / estimateSum;
                if (actionRandomNumber <= sum)
                    return i;
            }

            return actionsCount - 1;
        }
    }
}
using QuantConnect.Data;
using QuantConnect.Data.Custom;
using QuantConnect.Indicators;
using QuantConnect.Securities;
using System;
using System.Collections.Generic;
using QuantConnect.Data.Market;
using System.Linq;
using QuantConnect.Data.Consolidators;
using MathNet.Numerics.Statistics;
using Accord.MachineLearning;
using Accord.Statistics.Distributions.DensityKernels;
using QuantConnect.Securities.Equity;

#if PETTER
using System.Windows.Media;
using LiveCharts.Wpf;
#endif

namespace QuantConnect.Algorithm.CSharp
{
    public partial class TrendOppositeEntryAlgorithm : QCAlgorithm
    {
        private enum Charting
        {
            Disabled,
            FullResolution,
            TradesOnly,
            DailyEquityOnly,
            ProfitPerDelay,
        }

        private const Charting _charting = Charting.DailyEquityOnly;

        private const decimal _maxLeverage = 30;
        private const decimal _leverage = 1;

        private static TrendOppositeEntryAlgorithm _instance;

        public override void Initialize()
        {
            SetCash(400000);

            if (true||_charting == Charting.DailyEquityOnly)
            {
                SetStartDate(2014, 1, 15);
                SetEndDate(2018, 7, 15);
            }
            else
            {
                SetStartDate(2014, 1, 25);
                SetEndDate(2018, 7, 10);
            }

            try
            {
                ActualInitialization();
            }
            catch (Exception e)
            {
                ReportException(e, this);
            }
        }

        public static void ReportException(Exception e, QCAlgorithm algo)
        {
            algo.Error(algo.Time + ": " + e.Message + "\n" + e.StackTrace);
            algo.Log(algo.Time + ": " + e.Message + "\n" + e.StackTrace);
        }

        private Security _security;

#if PETTER
        private SignalView _signalView;
#endif

        private void ActualInitialization()
        {
            _instance = this;

            SetBrokerageModel(Brokerages.BrokerageName.OandaBrokerage);

            var res = Resolution.Daily;

            _security = AddCfd("WHEATUSD", res, leverage: _maxLeverage);

            Schedule.On(DateRules.EveryDay(), TimeRules.At(0, 0, 0), AtMidnight);

            //TODO: keeping this disabled unless we figure out it's a good idea
            //Schedule.On(DateRules.EveryDay(), TimeRules.Every(TimeSpan.FromSeconds(5)), CheckForSensitiveEvents);

            SetBenchmark(_security.Symbol);

#if PETTER
            if (_charting != Charting.Disabled)
                _signalView = SignalView.ShowInNewThread(CreateSignalViewOptions());
#endif

            _evalBarMaker.DataConsolidated += _evalBarMaker_DataConsolidated;
            _barMaker.DataConsolidated += _barMaker_DataConsolidated;
            InitKernels();
        }

#if PETTER
        private SignalView.SetupOptions CreateSignalViewOptions()
        {
            var options = new SignalView.SetupOptions();

            options.AxisGenerator = CreateExtraAxes;

            return options;
        }

        private IEnumerable<Axis> CreateExtraAxes()
        {
            yield return new Axis()
            {
                MinValue = -210,
                MaxValue = 210,
                Sections = new SectionsCollection
                {
                    new AxisSection
                    {
                        Value = 0,
                        SectionWidth = 1,
                        Stroke = new SolidColorBrush(Color.FromRgb(248, 213, 72))
                    },
                    /*new AxisSection
                    {
                        Value = 100,
                        SectionWidth = 1,
                        Fill = new SolidColorBrush
                        {
                            Color = Color.FromRgb(0, 255, 0),
                            Opacity = .8
                        }
                    },
                    new AxisSection
                    {
                        Value = -100,
                        SectionWidth = 1,
                        Fill = new SolidColorBrush
                        {
                            Color = Color.FromRgb(255, 0, 0),
                            Opacity = .8
                        }
                    }*/
                }
            };
        }
#endif

        private void AtMidnight()
        {
#if PETTER
            if (_charting != Charting.Disabled && _charting != Charting.ProfitPerDelay)
            {
                _signalView.SetXLabel(Time.ToShortDateString());
            }
#endif

#if PETTER
            if (_charting == Charting.DailyEquityOnly)
            {
                _signalView.PlotEquity((double)Portfolio.TotalPortfolioValue);
            }
#endif

            _equityAtStartOfDay = Portfolio.TotalPortfolioValue;

            foreach (var kernel in _kernels)
                kernel.AtMidnight();
        }


        public override void OnEndOfAlgorithm()
        {
#if PETTER
            if (_signalView != null)
                _signalView.JoinThread();
#endif
        }

        private void CheckForSensitiveEvents()
        {
            /*_sensitiveEvents.Update();

            if (_sensitiveEvents.InSensitiveZone && _components[0].Exchange.ExchangeOpen && _components[0].HoldStock)
            {
                ClosePosition();
            }*/
        }

        private decimal _equityAtStartOfDay;

        public override void OnData(Slice slice)
        {
            foreach (var kv in slice.QuoteBars)
            {
                OnBar(kv.Value);
            }
        }

        private class Kernel
        {
            public int DirBias = -1;

            private readonly RegressionChannel _equityFilter = new RegressionChannel(10, 2);
            private readonly VirtualEquity _equity;

            private decimal _lastSignal;

            public decimal Rank
            {
                get
                {
                    return _equityFilter;
                }
            }

            private decimal _entryPrice;

            public Kernel(Security sec)
            {
                _equity = new VirtualEquity(sec);
                _equity.TradeFeeFraction = 0;
            }

            public void SetPosition(decimal signal)
            {
                if (signal != _lastSignal && _lastSignal != 0)
                {
                    decimal exitPrice = _lastSignal < 0 ? _equity.Security.AskPrice : _equity.Security.BidPrice;
                    decimal profit = _lastSignal * (exitPrice / _entryPrice - 1);
                }

                _lastSignal = signal;
                _equity.SetPosition(signal * DirBias);
                _entryPrice = _lastSignal > 0 ? _equity.Security.AskPrice : _equity.Security.BidPrice;
            }

            public decimal GetPosition()
            {
                return _lastSignal * DirBias;
            }

            private decimal _preEquity;
            public void OnEvalBar(QuoteBar bar)
            {
                if (_preEquity == 0)
                    _preEquity = _equity.GetEquity();

                _equityFilter.Update(bar.Time, _equity.GetEquity() / _preEquity - 1);
                _preEquity = _equity.GetEquity();
            }

            private int _lastMonth = -1;

            public void AtMidnight()
            {
                if (_lastMonth >= 0 && _lastMonth != _instance.Time.Month)
                {
                    //Reoptimize();
                }

                _lastMonth = _instance.Time.Month;
            }

            private class SimPosition
            {
                public decimal Price;
                public int Dir;
                public bool Closed;
                public bool Real = true;
                public decimal MAE;
                public decimal MFE;

                public SimPosition(decimal price, int dir)
                {
                    Price = price;
                    Dir = dir;
                }

                public decimal GetExcursion(decimal price)
                {
                    return Dir * (price / Price - 1);
                }

                public void Update(decimal price, int bias)
                {
                    if (Closed)
                        return;

                    decimal excursion = GetExcursion(price);
                    MFE = Math.Max(MFE, excursion);
                    MAE = Math.Min(MAE, excursion);

                    if (bias != Dir)
                        Closed = true;
                }
            }

            private readonly RollingWindow<SimPosition> _simPos = new RollingWindow<SimPosition>(20);

            private ExponentialMovingAverage _ema20 = new ExponentialMovingAverage(20);
            private decimal _anchorPrice;
            public void OnTriggerBar(QuoteBar bar, decimal slippage)
            {
                int switchdir = 1;
                int bias = Math.Sign(bar.Price - _ema20);
                _ema20.Update(bar.Time, bar.Price);

                if (_simPos.Any())
                {
                    foreach (var pos in _simPos)
                        pos.Update(bar.Price, bias);

                    decimal meanMAE = _simPos.Average(x => x.MAE);
                    decimal meanMFE = _simPos.Average(x => x.MFE);
                    if (meanMAE > meanMFE)
                        switchdir = -1;

                    foreach (var pos in _simPos)
                    {
                        if (!pos.Real)
                            continue;

                        decimal excursion = pos.GetExcursion(bar.Price);
                        if (excursion > meanMFE)
                            pos.Real = false;
                        else if (excursion < meanMAE && bias != pos.Dir)
                            pos.Real = false;
                    }
                }

                if (_anchorPrice == 0)
                    _anchorPrice = bar.Price;
                var change = bar.Price / _anchorPrice - 1;
                if (Math.Abs(change) > 0.4m / 100)
                {
                    _anchorPrice = bar.Price;

                    if (bias < 0)
                    {
                        //consider short entry
                        if (change > 0)
                        {
                            _simPos.Add(new SimPosition(bar.Price, bias));
                        }
                    }
                    else if (bias > 0)
                    {
                        //consider long entry
                        if (change < 0)
                        {
                            _simPos.Add(new SimPosition(bar.Price, bias));
                        }
                    }
                }

                if (_simPos.Count > 10)
                {
                    decimal signal = _simPos.Where(x => x.Real).Sum(x => x.Dir);
                    SetPosition(signal * switchdir);
                }
                else
                {
                    SetPosition(0);
                }
            }
        }

        private void SelectKernel()
        {
            _activeKernel = _kernels.OrderByDescending(x => x.Rank).First();
        }

        private Kernel _activeKernel;
        private List<Kernel> _kernels = new List<Kernel>();

        private readonly SimpleMovingAverage _graphSMA = new SimpleMovingAverage(60); //just charting position
        private readonly QuoteBarConsolidator _evalBarMaker = new QuoteBarConsolidator(TimeSpan.FromDays(1));
        private readonly QuoteBarConsolidator _barMaker = new QuoteBarConsolidator(TimeSpan.FromHours(1));

        private void InitKernels()
        {
            var periods = new int[] { 5 };
            var entries = new decimal[] { 0.6m, 0.66m, 0.7m, 0.75m, 0.8m, 0.85m, 0.9m, 0.95m };
            var exits = new decimal[] { 0.1m, 0.3m, 0.5m, 0.55m, 0.6m, 0.66m, 0.7m, 0.75m };

            //for (int dir = -1; dir <= 1; dir += 2)
            {
                //foreach (var period in periods)
                {
                    //foreach (var exit in exits)
                    {
                        //foreach (var entry in entries)
                        {
                            //if (entry < exit + 0.1m)
                                //continue;

                            _kernels.Add(new Kernel(_security)
                            {
                                //DirBias = dir,
                                //EntryFactor = entry,
                                //ExitFactor = exit,
                            });
                        }
                    }
                }
            }

            SelectKernel();
        }

        private void _evalBarMaker_DataConsolidated(object sender, QuoteBar bar)
        {
            foreach (var kernel in _kernels)
                kernel.OnEvalBar(bar);

            SelectKernel();
        }

        private void Note(string msg)
        {
#if PETTER
            if (!LiveMode)
                Debug(msg);
#endif
        }

        decimal _lastPos;
        decimal _pos;

        //for stats
        decimal _entryPrice;
        decimal _entrySpread;

        private void _barMaker_DataConsolidated(object sender, QuoteBar bar)
        {
            
        }

        private void OnTriggerBar(QuoteBar bar)
        {
            var slippage = _security.AskPrice - _security.BidPrice;

            foreach (var kernel in _kernels)
                kernel.OnTriggerBar(bar, slippage);
        }

        private void OnBar(QuoteBar bar)
        {
            _evalBarMaker.Update(bar);
            _barMaker.Update(bar);

            OnTriggerBar(bar);

            if (_activeKernel == null)
                _pos = 0;
            else
            {
                _pos = _activeKernel.GetPosition();
            }

            if (_pos != _lastPos)
            {
                if (_pos == 0)
                {
                    if (_security.HoldStock)
                    {
                        Note("Liquidate at " + _security.Price);
                        Liquidate(_security.Symbol);

                        decimal exitPrice = _pos > 0 ? _security.BidPrice : _security.AskPrice;
                        decimal exitSpread = _security.AskPrice - _security.BidPrice;

                        Note("Trade profit: " + (exitPrice / _entryPrice - 1).ToString("P2"));
                        Note("Spread cost: " + (_entrySpread / _entryPrice + exitSpread / exitPrice).ToString("P2"));
                    }
                }
                else
                {
                    if (true/*_activeKernel.WillSucceed*/)
                    {
                        if (_pos > 0)
                            Note("Long at " + _security.Price);
                        else
                            Note("Short at " + _security.Price);

                        SetHoldings(_security.Symbol, _pos * _leverage);

                        _entryPrice = _pos > 0 ? _security.AskPrice : _security.BidPrice;
                        _entrySpread = _security.AskPrice - _security.BidPrice;
                    }
                }

                _lastPos = _pos;
            }

            _graphSMA.Update(Time, bar.Close);

#if PETTER
            if (_charting == Charting.FullResolution || _charting == Charting.TradesOnly && _pos != 0)
            {
                const decimal OFFSET = 0.01m;

                //_signalView.PlotBar(bar);
                _signalView.PlotValue("close", (double)_security.Price);
                _signalView.PlotValue("pos", (double)(_graphSMA + _pos * OFFSET));
                _signalView.PlotEquity((double)Portfolio.TotalPortfolioValue);
            };
#endif
        }
    }
}
/*
 * 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.
*/

using QuantConnect.Indicators;
using System;

namespace QuantConnect.Algorithm.CSharp
{
    /// <summary>
    /// This indicator computes the n-period population standard deviation.
    /// </summary>
    public class StandardDeviationOverflowSafe : Variance
    {
        /// <summary>
        /// Initializes a new instance of the StandardDeviation class with the specified period.
        /// 
        /// Evaluates the standard deviation of samples in the lookback period. 
        /// On a dataset of size N will use an N normalizer and would thus be biased if applied to a subset.
        /// </summary>
        /// <param name="period">The sample size of the standard deviation</param>
        public StandardDeviationOverflowSafe(int period)
            : this("STD" + period, period)
        {
        }

        /// <summary>
        /// Initializes a new instance of the StandardDeviation class with the specified name and period.
        /// 
        /// Evaluates the standard deviation of samples in the lookback period. 
        /// On a dataset of size N will use an N normalizer and would thus be biased if applied to a subset.
        /// </summary>
        /// <param name="name">The name of this indicator</param>
        /// <param name="period">The sample size of the standard deviation</param>
        public StandardDeviationOverflowSafe(string name, int period)
            : base(name, period)
        {
        }

        /// <summary>
        /// Gets a flag indicating when this indicator is ready and fully initialized
        /// </summary>
        public override bool IsReady
        {
            get { return Samples >= Period; }
        }

        /// <summary>
        /// Computes the next value of this indicator from the given state
        /// </summary>
        /// <param name="input">The input given to the indicator</param>
        /// <param name="window">The window for the input history</param>
        /// <returns>A new value for this indicator</returns>
        protected override decimal ComputeNextValue(IReadOnlyWindow<IndicatorDataPoint> window, IndicatorDataPoint input)
        {
            double val = Math.Sqrt((double)base.ComputeNextValue(window, input));
            if (val <= _max && val >= _min)
                return (decimal)val;
            return (decimal)(val > _min ? _max : _min);
        }

        private static readonly double _max = (double)decimal.MaxValue * 0.01;
        private static readonly double _min = (double)decimal.MinValue * 0.01;
    }
}
using QuantConnect.Securities;
using System;

namespace QuantConnect.Algorithm.CSharp
{
    public sealed class VirtualEquity
    {
        public interface ISecurity
        {
            decimal GetPrice();
            Security GetSecurityIfSupportedOtherwiseThrow();
        }

        private class SecurityAdapter : ISecurity
        {
            private readonly Security _sec;

            public SecurityAdapter(Security sec)
            {
                _sec = sec;
            }

            public decimal GetPrice()
            {
                return _sec.Price;
            }

            public Security GetSecurityIfSupportedOtherwiseThrow()
            {
                return _sec;
            }
        }

        public decimal TradeFeeFraction { get; set; }

        private readonly ISecurity _security;

        private decimal _entryFee;
        private decimal _entryPrice;
        private decimal _position;
        private decimal _equityBase = 1;

        public VirtualEquity(ISecurity sec)
        {
            _security = sec;
            TradeFeeFraction = 0.005m;
        }

        public VirtualEquity(Security sec) : this(new SecurityAdapter(sec))
        {

        }

        public decimal Slippage
        {
            get; set;
        }

        public decimal Position
        {
            get { return _position; }
            set { SetPosition(value); }
        }

        public Security Security { get { return _security.GetSecurityIfSupportedOtherwiseThrow(); } }

        public decimal GetEquity()
        {
            if (_position == 0)
                return _equityBase;
            return Math.Max(0, _equityBase * (1 + _position * (_security.GetPrice() / _entryPrice - 1) - Slippage - _entryFee - GetTradeFee()));
        }

        public decimal GetReturn()
        {
            return GetEquity() - 1;
        }

        public decimal Equity
        {
            get
            {
                return GetEquity();
            }
        }

        private decimal GetTradeFee()
        {
            if (_security.GetPrice() == 0)
                return TradeFeeFraction;
            return Math.Min(TradeFeeFraction, TradeFeeFraction / _security.GetPrice());
        }

        public void SetPosition(decimal weight)
        {
            var old = _equityBase;
            _equityBase = GetEquity();

            _position = weight;
            _entryPrice = _security.GetPrice();
            _entryFee = GetTradeFee();
        }

        public void ResetEquity(bool keepPosition = true)
        {
            var oldPos = _position;
            SetPosition(0);
            _equityBase = 1;
            if (oldPos != 0 && keepPosition)
            {
                _equityBase += Slippage;
                SetPosition(oldPos);
            }
        }
    }
}
using QuantConnect.Indicators;
using System;
using System.Collections.Generic;

namespace QuantConnect.Algorithm.CSharp
{
    public sealed class BinaryNgramTable
    {
        private readonly int[] _upCount, _downCount;

        public BinaryNgramTable(int N)
        {
            _upCount = new int[1 << N];
            _downCount = new int[1 << N];
        }

        public static int EncodeSequence(IEnumerable<int> seq, int numSymbols)
        {
            int code = 0;
            foreach (int symbol in seq)
            {
                code *= numSymbols;
                code += symbol;
            }

            return code;
        }

        public void Feedback(int code, bool up)
        {
            if (up)
                _upCount[code] += 1;
            else
                _downCount[code] += 1;
        }

        public double GetUpProbability(int code)
        {
            return (double)(_upCount[code] + 1) / (_upCount[code] + _downCount[code] + 2);
        }

        public int GetCount(int code)
        {
            return _upCount[code] + _downCount[code];
        }
    }

    public sealed class BinaryNgramSequence
    {
        private readonly int _numSymbols;
        private readonly int _minCount;
        private RollingWindow<int> _sequence;
        private readonly BinaryNgramTable[] _tables;

        public BinaryNgramSequence(int maxN, int numSymbols, int minCount)
        {
            _numSymbols = numSymbols;
            _minCount = minCount;
            _sequence = new RollingWindow<int>(maxN);

            _tables = new BinaryNgramTable[maxN + 1];
            for (int n = 0; n <= maxN; ++n)
            {
                _tables[n] = new BinaryNgramTable(n);
            }
        }

        public void ClearTables()
        {
            for (int n = 0; n <= _tables.Length - 1; ++n)
            {
                _tables[n] = new BinaryNgramTable(n);
            }
        }

        public bool IsReady
        {
            get { return _sequence.IsReady; }
        }

        public IEnumerable<int> GetSequence()
        {
            CheckReady();
            return _sequence;
        }

        private void CheckReady()
        {
            if (!_sequence.IsReady)
                throw new Exception("Sequence not filled, check IsReady first");
        }

        public void Advance(int symbol)
        {
            _sequence.Add(symbol);
        }

        public double GetUpProbability()
        {
            CheckReady();

            double best = _tables[0].GetUpProbability(0);

            int code = 0;
            int n = 1;
            foreach (int symbol in _sequence)
            {
                code *= _numSymbols;
                code += symbol;
                var table = _tables[n++];

                if (table.GetCount(code) < _minCount)
                    break;

                best = table.GetUpProbability(code);
            }

            return best;
        }

        public void Feedback(bool up)
        {
            CheckReady();

            _tables[0].Feedback(0, up);

            int code = 0;
            int n = 1;
            foreach (int symbol in _sequence)
            {
                code *= _numSymbols;
                code += symbol;

                _tables[n++].Feedback(code, up);
            }
        }
    }
}