Overall Statistics
Total Trades
106
Average Win
3.70%
Average Loss
-0.90%
Compounding Annual Return
100.687%
Drawdown
23.300%
Expectancy
1.552
Net Profit
71.602%
Sharpe Ratio
1.642
Loss Rate
50%
Win Rate
50%
Profit-Loss Ratio
4.10
Alpha
0.545
Beta
-0.096
Annual Standard Deviation
0.325
Annual Variance
0.106
Information Ratio
1.256
Tracking Error
0.331
Treynor Ratio
-5.542
Total Fees
$0.00
using Newtonsoft.Json;

namespace QuantConnect.Algorithm.CSharp.Algo
{

    /// <summary>
    ///     This is a truncated version of the algorithm made for the Trading Strategies Based on Genetic Algorithms project
    ///     for the QuantConnect platform.
    ///     The main difference is that the rules are hard coded in the TradingRule class, instead if being dynamically
    ///     generated as in the original.
    /// </summary>
    /// <seealso cref="QuantConnect.Algorithm.QCAlgorithm" />
    public partial class TradingStrategiesBasedOnGeneticAlgorithmsQCVersion : QCAlgorithm
    {
        private int _entryIndicatorSignalCount = 6;
        private int _exitIndicatorSignalCount = 6;
        private List<TradingRuleQCVersion> _entryradingRule;
        private List<TradingRuleQCVersion> _exitTradingRule;
        private double accountsize = 10000;
        public string[] Symbols;
        FxRiskManagment RiskManager;
        //[Parameter]
        public string accessToken;

        //[Parameter]
        public string timeZone = "America/New_York";

        //[Parameter]

        private const decimal _leverage = 50m;

        // How much of the total strategy equity can be at risk as maximum in all trades.
        private const decimal _maxExposure = 0.8m;

        // How much of the total strategy equity can be at risk in a single trade.
        private const decimal _maxExposurePerTrade = 0.25m;

        // The max strategy equity proportion to put at risk in a single operation.
        private decimal _riskPerTrade = 0.01m;

        private decimal takeProfit = 0.10m;
        
        private Resolution _resolution = Resolution.Minute;

        // Smallest lot
        private LotSize _lotSize = LotSize.Nano;
        private int ExitSMAFastPeriod = 50;
        private int ExitSMASlowPeriod = 200;
        private int EntrySMAFastPeriod = 50;
        private int EntrySMASlowPeriod = 200;
        private int EntryEMAFastPeriod = 50;
        private int EntryEMASlowPeriod = 200;
        private int EntryMACDFastPeriod = 12;
        private int EntryMACDSlowPeriod = 26;
        private int EntryMACDSignalPeriod = 9;
        private int EntryStochasticPeriod = 14;
        private int EntryRSIPeriod = 14;
        private int EntryCCIPeriod = 14;
        private int EntryMomentumPeriod = 60;
        private int EntryWILRPeriod = 14;
        private int EntryBBPeriod = 20;
         
        //[Parameter]
        public bool isLive = false;

        public bool verbose = false;

        public string[] OandaFXSymbols = {
            "AUDCAD","AUDCHF","AUDHKD","AUDJPY","AUDNZD","AUDSGD","AUDUSD","CADCHF","CADHKD","CADJPY",
            "CADSGD","CHFHKD","CHFJPY","CHFZAR","EURAUD","EURCAD","EURCHF","EURCZK","EURDKK","EURGBP",
            "EURHKD","EURHUF","EURJPY","EURNOK","EURNZD","EURPLN","EURSEK","EURSGD","EURTRY","EURUSD",
            "EURZAR","GBPAUD","GBPCAD","GBPCHF","GBPHKD","GBPJPY","GBPNZD","GBPPLN","GBPSGD","GBPUSD",
            "GBPZAR","HKDJPY","NZDCAD","NZDCHF","NZDHKD","NZDJPY","NZDSGD","NZDUSD","SGDCHF","SGDHKD",
            "SGDJPY","TRYJPY","USDCAD","USDCHF","USDCNH","USDCZK","USDDKK","USDHKD","USDHUF","USDINR",
            "USDJPY","USDMXN","USDNOK","USDPLN","USDSAR","USDSEK","USDSGD","USDTHB","USDTRY","USDZAR",
            "ZARJPY" };

        public string[] OandaFXMajors2 = {
            "AUDJPY","AUDUSD","EURAUD","EURCHF","EURGBP","EURJPY","EURUSD","GBPCHF","GBPJPY","GBPUSD",
            "NZDUSD","USDCAD","USDCHF","USDJPY" };

        public string[] OandaFXMajors1 = {
            "EURCHF","EURGBP","EURJPY","EURUSD","GBPCHF","GBPJPY","GBPUSD","USDCHF","USDJPY" };
        public string[] OandaFXMajors = {
            "EURCHF","EURGBP","EURJPY","EURUSD" };

        public string[] OandaFXMajors0 = {
            "EURUSD" };

        /// <summary>
        ///     Here are the parameters of the individual with the best in-sample fitness.
        /// </summary>
        private readonly Dictionary<string, string> parametersToBacktest = new Dictionary<string, string>
        {
            {"EntryIndicator1", "8"},
            {"EntryIndicator2", "2"},
            {"EntryIndicator3", "3"},
            {"EntryIndicator4", "7"},
            {"EntryIndicator5", "5"},
            {"EntryIndicator6", "0"},
            {"EntryIndicator1Direction", "1"},//0
            {"EntryIndicator2Direction", "1"},//0
            {"EntryIndicator3Direction", "1"}, //1
            {"EntryIndicator4Direction", "1"}, //1
            {"EntryIndicator5Direction", "1"},//0
            {"EntryIndicator6Direction", "1"},//0
            {"EntryIndicator1Operator", "0"},//0//0
            {"EntryIndicator2Operator", "0"},//0//1
            {"EntryIndicator3Operator", "0"},//1
            {"EntryIndicator4Operator", "0"},//1
            {"EntryIndicator5Operator", "0"},//0
            {"ExitIndicator1", "4"},
            {"ExitIndicator2", "0"},
            {"ExitIndicator3", "1"},
            {"ExitIndicator4", "2"},
            {"ExitIndicator5", "7"},
            {"ExitIndicator6", "8"},
            {"ExitIndicator1Direction", "0"},//1
            {"ExitIndicator2Direction", "0"},
            {"ExitIndicator3Direction", "0"},
            {"ExitIndicator4Direction", "0"},
            {"ExitIndicator5Direction", "0"},//0
            {"ExitIndicator6Direction", "0"},//0
            {"ExitIndicator1Operator", "1"},//0//1
            {"ExitIndicator2Operator", "1"},//0//0
            {"ExitIndicator3Operator", "0"},//1
            {"ExitIndicator4Operator", "1"},//0//0
            {"ExitIndicator5Operator", "1"},//0
            {"EntrySMAFastPeriod", "20"},
            {"EntrySMASlowPeriod", "200"},
            {"ExitSMAFastPeriod", "20"},
            {"ExitSMASlowPeriod", "220"},
            {"EntryIndicatorSignalCount", "6"},
            {"ExitIndicatorSignalCount", "6"}
        };

        public override void Initialize()
        {

            SetCash(startingCash: accountsize);
            var startDate = GetGeneDateTimeFromKey("startDate", new DateTime(2017, 1, 1));
            //SetStartDate(startDate);
            SetStartDate(startDate);
            SetEndDate(GetGeneDateTimeFromKey("endDate", new DateTime(2017, 10, 10)));
            //SetEndDate(startDate.AddMonths(months: 20));
            takeProfit = GetGeneDecimalFromKey("takeProfit", 0.05m);
            _riskPerTrade = GetGeneDecimalFromKey("riskPerTrade", 0.01m);
            _entryIndicatorSignalCount = GetGeneIntFromKey("EntryIndicatorSignalCount", 2);
            _exitIndicatorSignalCount = GetGeneIntFromKey("ExitIndicatorSignalCount", 2);
            List<string> list = new List<string>();
            list.AddRange(OandaFXMajors);
            Symbols = list.ToArray();
            foreach (var symbol in Symbols)
            {
                AddSecurity(SecurityType.Forex, symbol, _resolution, Market.Oanda, true, _leverage, false);
                SetBrokerageModel(BrokerageName.OandaBrokerage);
            }

            SetParameters(parametersToBacktest);

            SetUpRules();
        }

        public void OnData(QuoteBars data)
        {
            /*
                foreach (var symbol in Symbols)
                {
                    decimal smaVal = sma[symbol].AddSample(data[symbol].Close);
                    decimal stdVal = std[symbol].AddSample(data[symbol].Close, sma[symbol]);
                    if(sma[symbol].Ready) {
                        decimal upband = smaVal + stdVal;
                        decimal downband = smaVal - stdVal;
                    }
                }
                */

            foreach (var entry in _entryradingRule)
            {
                if (entry.IsReady)
                {
                    EntrySignal(data, entry);
                }
            }
            foreach (var entry in _exitTradingRule)
            {
                if (entry.IsReady)
                {
                    ExitSignal(entry);
                }
            }
            RiskManager.UpdateTrailingStopOrders(data);
            var openStopLossOrders = Portfolio.Transactions.GetOrderTickets(o => o.OrderType == OrderType.StopMarket && o.Status == OrderStatus.Submitted);
            if (verbose)
            {
                foreach (var ticket in openStopLossOrders)
                {
                    Log(String.Format("{0} {1} {2} {3}", ticket.OrderId, ticket.Symbol, ticket.AverageFillPrice, ticket.Quantity));
                }
            }
        }

        public void ExitSignal(TradingRuleQCVersion signal)
        {

            if (verbose && signal.TradeRuleSignal)
            {
                Log(string.Format("signal symbol:: {0}", signal.Symbol));
            }
            if (Portfolio[signal.Symbol].Invested && signal.TradeRuleSignal)
            {
                Liquidate(signal.Symbol);
            }
            else if (Portfolio[signal.Symbol].Invested && Portfolio[signal.Symbol].UnrealizedProfitPercent > takeProfit)
            {
                //safeguard profits, 
                //liquidate half
                MarketOrder(signal.Symbol, Portfolio[signal.Symbol].Quantity/2);

            }
            //                         Log("MarketOrder:: " +activeSignal.Symbol + " :: "+ signal.meta.direction);

        }
        public void EntrySignal(QuoteBars data, TradingRuleQCVersion signal)
        {

            if (verbose && signal.TradeRuleSignal)
            {
                Log(string.Format("signal symbol:: {0}", signal.Symbol));
            }
            if (!Portfolio[signal.Symbol].Invested)
            {
                if (signal.TradeRuleSignal)
                {

                    var openPrice = Securities[signal.Symbol].Price;
                    int size = (int)_lotSize;
                    var actualAction = AgentAction.GoLong;
                    var entryValues = RiskManager.CalculateEntryOrders(data, signal.Symbol, actualAction);
                    if (entryValues.Item1 != 0)
                    {

                        var ticket = MarketOrder(signal.Symbol, entryValues.Item1);
                        StopMarketOrder(signal.Symbol, -entryValues.Item1, entryValues.Item2, tag: entryValues.Item3.ToString("0.000000"));
                        if (verbose)
                        {
                            Log(string.Format("MarketOrder:: {0} {1}", signal.Symbol, size));
                        }
                    }
                    //MarketOrder(signal.Symbol, size, false, "");
                }
            }


            //                         Log("MarketOrder:: " +activeSignal.Symbol + " :: "+ signal.meta.direction);

        }

        /// <summary>
        ///     Sets up indicator signal. This method is where the Technical indicator rules are defined.
        /// </summary>
        /// <param name="pair">The pair.</param>
        /// <param name="indicatorN">The number if indicator.</param>
        /// <param name="ruleAction">
        ///     The rule action. Should be 'Entry' or 'Exit' and is only used to differentiate the genes for
        ///     entry and exit
        /// </param>
        /// <returns></returns>
        /// <exception cref="System.NotImplementedException">WIP</exception>
        public ITechnicalIndicatorSignal SetUpIndicatorSignal(Symbol pair, int indicatorN, string ruleAction)
        {
            var oscillatorThresholds = new OscillatorThresholds { Lower = 20, Upper = 80 };
            var key = ruleAction + "Indicator" + indicatorN + "Direction";
            var intDirection = GetGeneIntFromKey(key);

            var direction = (TradeRuleDirection)intDirection;

            key = ruleAction + "Indicator" + indicatorN;
            var indicatorId = GetGeneIntFromKey(key);
            var indicator = (TechicalIndicators)indicatorId;
            ITechnicalIndicatorSignal technicalIndicator = null;
            switch (indicator)
            {
                case TechicalIndicators.SimpleMovingAverage:
                    // Canonical cross moving average parameters.
                    var fast = SMA(pair, period: GetGeneIntFromKey(ruleAction + "SMAFastPeriod"));
                    var slow = SMA(pair, period: GetGeneIntFromKey(ruleAction + "SMASlowPeriod"));
                    technicalIndicator = new CrossingMovingAverages(fast, slow, direction);
                    break;

                case TechicalIndicators.ExponentialMovingAverage:
                    // Canonical cross moving average parameters.
                    var fastema = EMA(pair, period: 50);
                    var slowema = EMA(pair, period: 200);
                    technicalIndicator = new CrossingMovingAverages(fastema, slowema, direction);
                    break;

                case TechicalIndicators.MovingAverageConvergenceDivergence:
                    var macd = MACD(pair, fastPeriod: 12, slowPeriod: 26, signalPeriod: 9);
                    technicalIndicator = new CrossingMovingAverages(macd, macd.Signal, direction);
                    break;

                case TechicalIndicators.Stochastic:
                    var sto = STO(pair, period: 14);
                    oscillatorThresholds.Lower = 20;
                    oscillatorThresholds.Upper = 80;
                    technicalIndicator = new OscillatorSignal(sto.StochD, oscillatorThresholds, direction, this);
                    break;

                case TechicalIndicators.RelativeStrengthIndex:
                    var rsi = RSI(pair, period: 14);
                    oscillatorThresholds.Lower = 30;
                    oscillatorThresholds.Upper = 70;
                    technicalIndicator = new OscillatorSignal(rsi, oscillatorThresholds, direction, this);
                    break;

                case TechicalIndicators.CommodityChannelIndex:
                    var cci = CCI(pair, period: 20);
                    oscillatorThresholds.Lower = -100;
                    oscillatorThresholds.Upper = 100;
                    technicalIndicator = new OscillatorSignal(cci, oscillatorThresholds, direction, this);
                    break;

                case TechicalIndicators.MomentumPercent:
                    var pm = MOMP(pair, period: 60);
                    //in percentage, above 5% means bull, lower than -5% bear
                    oscillatorThresholds.Lower = -5;
                    oscillatorThresholds.Upper = 5;
                    technicalIndicator = new OscillatorSignal(pm, oscillatorThresholds, direction, this);
                    break;

                case TechicalIndicators.WilliamsPercentR:
                    var wr = WILR(pair, period: 14);
                    oscillatorThresholds.Lower = -80;
                    oscillatorThresholds.Upper = -20;
                    technicalIndicator = new OscillatorSignal(wr, oscillatorThresholds, direction, this);
                    break;

                case TechicalIndicators.PercentagePriceOscillator:
                    var ppo = MACD(pair, fastPeriod: 12, slowPeriod: 26, signalPeriod: 9).Over(EMA(pair, period: 26))
                        .Plus(constant: 100m);
                    var signal = new SimpleMovingAverage(period: 9).Of(ppo);
                    technicalIndicator = new CrossingMovingAverages(ppo, signal, direction);
                    break;


                case TechicalIndicators.BollingerBands:
                    //Log("setting BB");
                    var signalb = BB(pair, period: 20, k: 2);
                    //technicalIndicator = new BolingerBandsIndicator(signalb, this, direction);
                    technicalIndicator = new BBOscillatorSignal(signalb, direction, this);
                    //throw new NotImplementedException("WIP");
                    break;

                case TechicalIndicators.ClenowBreakout:
                    //Set up Indicators:
                    var _atr = ATR(pair, 100, MovingAverageType.Simple, Resolution.Daily);
                    var _max = MAX(pair, 50, Resolution.Daily);
                    var _min = MIN(pair, 50, Resolution.Daily); 
                    var _maxC = MAX(pair, 25, Resolution.Daily);
                    var _minC = MIN(pair, 25, Resolution.Daily); 
                    //Log("setting BB");

                    var signalt = BB(pair, period: 20, k: 2);
                    technicalIndicator = new BolingerBandsIndicator(signalt, this, direction);

                    //throw new NotImplementedException("WIP");
                    break;


            }

            return technicalIndicator;
        }

        /// <summary>
        ///     Gets the gene int from key.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <returns></returns>
        /// <exception cref="System.ArgumentNullException">The gene " + key + " is not present either as Config or as Parameter</exception>
        /// <remarks>
        ///     This method makes the algorithm working with the genes defined from the Config (as in the Lean Optimization) and
        ///     from the Parameters (as the Lean Caller).
        /// </remarks>
        private int GetGeneIntFromKey(string key)
        {
            // I'll keep this line as in the original code. 
            //var gene = Config.GetInt(key, int.MinValue);
            var gene = int.MinValue;
            if (gene == int.MinValue)//not found in config, then get from parameter
            {
                try
                {
                    gene = int.Parse(GetParameter(key));
                    if (verbose)
                    {
                        Log(string.Format("Parameter {0} set to {1}", key, gene));
                    }
                }
#pragma warning disable CS0168 // Variable is declared but never used
                catch (ArgumentNullException e)
#pragma warning restore CS0168 // Variable is declared but never used
                {
                    throw new ArgumentNullException(key,
                        "The gene " + key + " is not present either as Config or as Parameter");
                }
            }
            return gene;
        }

        /// <summary>
        ///     Gets the gene int from key.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <returns></returns>
        /// <exception cref="System.ArgumentNullException">The gene " + key + " is not present either as Config or as Parameter</exception>
        /// <remarks>
        ///     This method makes the algorithm working with the genes defined from the Config (as in the Lean Optimization) and
        ///     from the Parameters (as the Lean Caller).
        /// </remarks>
        private int GetGeneIntFromKey(string key, int def)
        {
            // I'll keep this line as in the original code. 
            //var gene = Config.GetInt(key, int.MinValue);
            var gene = int.MinValue;
            if (gene == int.MinValue)//not found in config, then get from parameter
            {
                try
                {
                    gene = int.Parse(GetParameter(key));
                    if (verbose)
                    {
                        Log(string.Format("Parameter {0} set to {1}", key, gene));
                    }
                }
#pragma warning disable CS0168 // Variable is declared but never used
                catch (ArgumentNullException e)
#pragma warning restore CS0168 // Variable is declared but never used
                {
                    return def;
                }
            }
            return gene;
        }

        /// <summary>
        ///     Gets the gene int from key.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <returns></returns>
        /// <exception cref="System.ArgumentNullException">The gene " + key + " is not present either as Config or as Parameter</exception>
        /// <remarks>
        ///     This method makes the algorithm working with the genes defined from the Config (as in the Lean Optimization) and
        ///     from the Parameters (as the Lean Caller).
        /// </remarks>
        private decimal GetGeneDecimalFromKey(string key, decimal def)
        {
            // I'll keep this line as in the original code. 
            //var gene = Config.GetValue<decimal>(key);
            var gene = decimal.MinValue;
            if (gene == decimal.MinValue)//not found in config, then get from parameter
            {
                try
                {
                    gene = decimal.Parse(GetParameter(key));
                    if (verbose)
                    {
                        Log(string.Format("Parameter {0} set to {1}", key, gene));
                    }
                }
#pragma warning disable CS0168 // Variable is declared but never used
                catch (ArgumentNullException e)
#pragma warning restore CS0168 // Variable is declared but never used
                {
                    return def;
                }
            }
            return gene;
        }

        /// <summary>
        ///     Gets the gene int from key.
        /// </summary>
        /// <param name="key">The key.</param>
        /// <returns></returns>
        /// <exception cref="System.ArgumentNullException">The gene " + key + " is not present either as Config or as Parameter</exception>
        /// <remarks>
        ///     This method makes the algorithm working with the genes defined from the Config (as in the Lean Optimization) and
        ///     from the Parameters (as the Lean Caller).
        /// </remarks>
        private DateTime GetGeneDateTimeFromKey(string key, DateTime def)
        {
            // I'll keep this line as in the original code. 
            //var gene = Config.GetValue<DateTime>(key, null);
            var gene = DateTime.MinValue;
            if (gene == DateTime.MinValue)//not found in config, then get from parameter
            {
                try
                {
                    gene = DateTime.Parse(GetParameter(key));
                    if (verbose)
                    {
                        Log(string.Format("Parameter {0} set to {1}", key, gene));
                    }
                }
#pragma warning disable CS0168 // Variable is declared but never used
                catch (ArgumentNullException e)
#pragma warning restore CS0168 // Variable is declared but never used
                {
                    return def;
                }
            }
            return gene;
        }


        private void SetUpRules()
        {
            bool[] bools = { true, false };
            _entryradingRule = new List<TradingRuleQCVersion>();
            _exitTradingRule = new List<TradingRuleQCVersion>();
            RiskManager = new FxRiskManagment(Portfolio, _riskPerTrade, _maxExposurePerTrade, _maxExposure, _lotSize);


            foreach (var symbol in Symbols)
            {
                Securities[symbol].VolatilityModel = new ThreeSigmaVolatilityModel(STD(symbol: symbol, period: 12 * 60, resolution: _resolution), 20.0m);

                foreach (var isEntryRule in bools)
                {
                    var technicalIndicatorSignals = new List<ITechnicalIndicatorSignal>();
                    var ruleOperators = new List<RuleOperators>();
                    var ruleAction = isEntryRule ? "Entry" : "Exit";
                    var indicatorSignalCount = isEntryRule ? _entryIndicatorSignalCount : _exitIndicatorSignalCount;
                    for (var i = 1; i <= indicatorSignalCount; i++)
                    {
                        var indicatorSignal = SetUpIndicatorSignal(symbol, i, ruleAction);
                        technicalIndicatorSignals.Add(indicatorSignal);
                    }

                    for (var i = 1; i < indicatorSignalCount; i++)
                    {
                        var key = ruleAction + "Indicator" + i + "Operator";
                        ruleOperators.Add((RuleOperators)GetGeneIntFromKey(key));
                    }

                    if (isEntryRule)
                    {
                        _entryradingRule.Add(new TradingRuleQCVersion(technicalIndicatorSignals.ToArray(), ruleOperators.ToArray(), isEntryRule, symbol));
                    }
                    else
                    {
                        _exitTradingRule.Add(new TradingRuleQCVersion(technicalIndicatorSignals.ToArray(), ruleOperators.ToArray(), isEntryRule, symbol));
                    }
                }
            }
        }
    }
}
namespace QuantConnect
{
    /// <summary>
    ///     Interface used by the <see cref="TradingRule" /> class to flag technical indicator signals as crossing moving
    ///     averages or oscillators crossing its thresholds.
    /// </summary>
    public interface ITechnicalIndicatorSignal
    {
        /// <summary>
        ///     Gets a value indicating whether this instance is ready.
        /// </summary>
        /// <value>
        ///     <c>true</c> if this instance is ready; otherwise, <c>false</c>.
        /// </value>
        bool IsReady { get; }

        /// <summary>
        ///     Gets the signal. Only used if the instance will be part of a <see cref="TradingRule" /> class.
        /// </summary>
        /// <returns>
        ///     <c>true</c> if the actual <see cref="Signal" /> correspond with the instance <see cref="TradeRuleDirection" />.
        ///     <c>false</c>
        ///     otherwise.
        /// </returns>
        bool HasSignal();

        ActiveSignal GetSignal();

        TradeRuleDirection GetDirection();
    }

    /// <summary>
    ///     The <see cref="TradingStrategiesBasedOnGeneticAlgorithms" /> implementation requires a direction for every
    ///     technical indicator.
    /// </summary>
    public enum TradeRuleDirection
    {
        LongOnly = 1,
        ShortOnly = 0,
        Any = -2
    }

    /// <summary>
    ///     List of the technical indicator implemented... well not really, Bollinger bands wasn't implemented.
    /// </summary>
    public enum TechicalIndicators
    {
        SimpleMovingAverage = 0,
        MovingAverageConvergenceDivergence = 1,
        Stochastic = 2,
        RelativeStrengthIndex = 3,
        CommodityChannelIndex = 4,
        MomentumPercent = 5,
        WilliamsPercentR = 6,
        PercentagePriceOscillator = 7,
        BollingerBands = 8,
        ExponentialMovingAverage = 9,
        ClenowBreakout = 10
    }


}
namespace QuantConnect
{
    /// <summary>
    ///     Possibles states of two moving averages.
    /// </summary>
    public enum CrossingMovingAveragesSignals
    {
        Bullish = 1,
        FastCrossSlowFromAbove = -2,
        Bearish = -1,
        FastCrossSlowFromBelow = 2
    }

    /// <summary>
    ///     This class keeps track of two crossing moving averages and updates a <see cref="CrossingMovingAveragesSignals" />
    ///     for each given state.
    /// </summary>
    /// <seealso cref="QuantConnect.Algorithm.CSharp.ITechnicalIndicatorSignal" />
    public class CrossingMovingAverages : SignalsBase
    {
        private readonly CompositeIndicator<IndicatorDataPoint> _moving_average_difference;
        private readonly TradeRuleDirection _tradeRuleDirection;
        private int _lastSignal;

        /// <summary>
        ///     Initializes a new instance of the <see cref="CrossingMovingAverages" /> class.
        /// </summary>
        /// <param name="fast_moving_average">The fast moving average.</param>
        /// <param name="slow_moving_average">The slow moving average.</param>
        /// <param name="tradeRuleDirection">
        ///     The trade rule direction. Only used if the instance will be part of a
        ///     <see cref="TradingRule" /> class
        /// </param>
        /// <remarks>
        ///     Both Moving Averages must be registered BEFORE being used by this constructor.
        /// </remarks>
        public CrossingMovingAverages(IndicatorBase<IndicatorDataPoint> fast_moving_average,
            IndicatorBase<IndicatorDataPoint> slow_moving_average, TradeRuleDirection? tradeRuleDirection = null)
        {
            _moving_average_difference = fast_moving_average.Minus(slow_moving_average);
            _moving_average_difference.Updated += ma_Updated;
            if (tradeRuleDirection != null) _tradeRuleDirection = (TradeRuleDirection)tradeRuleDirection;
        }

        /// <summary>
        ///     Gets a value indicating whether this instance is ready.
        /// </summary>
        /// <value>
        ///     <c>true</c> if this instance is ready; otherwise, <c>false</c>.
        /// </value>
        public override bool IsReady
        {
            get { return _moving_average_difference.IsReady; }
        }

        public override TradeRuleDirection GetDirection()
        {
            return _tradeRuleDirection;
        }

        /// <summary>
        ///     Gets the actual state of both moving averages.
        /// </summary>
        public CrossingMovingAveragesSignals Signal { get; private set; }

        /// <summary>
        ///     Gets the signal. Only used if the instance will be part of a <see cref="TradingRule" /> class.
        /// </summary>
        /// <returns>
        ///     <c>true</c> if the actual <see cref="Signal" /> correspond with the instance <see cref="TradeRuleDirection" />.
        ///     <c>false</c>
        ///     otherwise.
        /// </returns>
        public override bool HasSignal()
        {
            var signal = false;
            if (IsReady)
            {
                switch (_tradeRuleDirection)
                {
                    case TradeRuleDirection.LongOnly:
                        signal = Signal == CrossingMovingAveragesSignals.FastCrossSlowFromBelow;
                        break;

                    case TradeRuleDirection.ShortOnly:
                        signal = Signal == CrossingMovingAveragesSignals.FastCrossSlowFromAbove;
                        break;
                    case TradeRuleDirection.Any:
                        signal = Signal == CrossingMovingAveragesSignals.FastCrossSlowFromAbove ||
                            Signal == CrossingMovingAveragesSignals.FastCrossSlowFromBelow;
                        break;
                }
            }
            return signal;
        }

        private void ma_Updated(object sender, IndicatorDataPoint updated)
        {
            if (!IsReady)
            {
                return;
            }
            var actualSignal = Math.Sign(_moving_average_difference);
            if (actualSignal == _lastSignal || _lastSignal == 0)
            {
                Signal = (CrossingMovingAveragesSignals)actualSignal;
            }
            else if (_lastSignal == -1 && actualSignal == 1)
            {
                Signal = CrossingMovingAveragesSignals.FastCrossSlowFromBelow;
            }
            else if (_lastSignal == 1 && actualSignal == -1)
            {
                Signal = CrossingMovingAveragesSignals.FastCrossSlowFromAbove;
            }

            _lastSignal = actualSignal;
        }
    }
}
namespace QuantConnect.Algorithm.CSharp.Algo
{
    /// <summary>
    ///     Possibles states of an oscillator respect to its thresholds.
    /// </summary>
    public enum OscillatorSignals
    {
        CrossLowerThresholdFromAbove = -3,
        BellowLowerThreshold = -2,
        CrossLowerThresholdFromBelow = -1,
        BetweenThresholds = 0,
        CrossUpperThresholdFromBelow = 3,
        AboveUpperThreshold = 2,
        CrossUpperThresholdFromAbove = 1
    }

    public struct OscillatorThresholds
    {
        public decimal Lower;
        public decimal Upper;
    }
    /// <summary>
    ///     This class keeps track of an oscillator respect to its thresholds and updates an <see cref="OscillatorSignal" />
    ///     for each given state.
    /// </summary>
    /// <seealso cref="QuantConnect.Algorithm.CSharp.ITechnicalIndicatorSignal" />
    public class OscillatorSignal : SignalsBase
    {
        private decimal _previousIndicatorValue;
        private OscillatorSignals _previousSignal;
        private OscillatorThresholds _thresholds;
        private TradeRuleDirection _tradeRuleDirection;
        QCAlgorithm _log;
        /// <summary>
        ///     Initializes a new instance of the <see cref="OscillatorSignal" /> class.
        /// </summary>
        /// <param name="indicator">The indicator.</param>
        /// <param name="thresholds">The thresholds.</param>
        /// <param name="tradeRuleDirection">
        ///     The trade rule direction. Only used if the instance will be part of a
        ///     <see cref="TradingRule" /> class
        /// </param>
        /// <remarks>The oscillator must be registered BEFORE being used by this constructor.</remarks>
        public OscillatorSignal(dynamic indicator, OscillatorThresholds thresholds,
            TradeRuleDirection tradeRuleDirection, QCAlgorithm log)
        {
            SetUpClass(ref indicator, ref thresholds, tradeRuleDirection);
            _log = log;
        }

        /// <summary>
        ///     Initializes a new instance of the <see cref="OscillatorSignal" /> class.
        /// </summary>
        /// <param name="indicator">The indicator.</param>
        /// <remarks>The oscillator must be registered BEFORE being used by this constructor.</remarks>
        public OscillatorSignal(dynamic indicator, TradeRuleDirection tradeRuleDirection, QCAlgorithm log)
        {
            var defaultThresholds = new OscillatorThresholds { Lower = 20, Upper = 80 };
            _log = log;
            SetUpClass(ref indicator, ref defaultThresholds, tradeRuleDirection);
        }

        /// <summary>
        ///     The underlying indicator, must be an oscillator.
        /// </summary>
        public dynamic Indicator { get; private set; }

        /// <summary>
        ///     Gets the actual state of the oscillator.
        /// </summary>
        public OscillatorSignals Signal { get; private set; }

        /// <summary>
        ///     Gets a value indicating whether this instance is ready.
        /// </summary>
        /// <value>
        ///     <c>true</c> if this instance is ready; otherwise, <c>false</c>.
        /// </value>
        public override bool IsReady
        {
            get { return Indicator.IsReady; }
        }

        public override TradeRuleDirection GetDirection()
        {
            return _tradeRuleDirection;
        }

        /// <summary>
        ///     Gets the signal. Only used if the instance will be part of a <see cref="TradingRule" /> class.
        /// </summary>
        /// <returns>
        ///     <c>true</c> if the actual <see cref="Signal" /> correspond with the instance <see cref="TradeRuleDirection" />.
        ///     <c>false</c>
        ///     otherwise.
        /// </returns>
        public override bool HasSignal()
        {
            var signal = false;
            if (IsReady)
            {
                switch (_tradeRuleDirection)
                {
                    case TradeRuleDirection.LongOnly:
                        signal = Signal == OscillatorSignals.CrossLowerThresholdFromBelow;
                        break;

                    case TradeRuleDirection.ShortOnly:
                        signal = Signal == OscillatorSignals.CrossUpperThresholdFromAbove;
                        break;

                    case TradeRuleDirection.Any:
                        signal = Signal == OscillatorSignals.CrossUpperThresholdFromAbove ||
                            Signal == OscillatorSignals.CrossLowerThresholdFromBelow;
                        break;
                }
            }
            return signal;
        }

        /// <summary>
        ///     Updates the <see cref="Signal" /> status.
        /// </summary>
        private void Indicator_Updated(object sender, IndicatorDataPoint updated)
        {
            var actualPositionSignal = GetActualPositionSignal(updated);
            if (!Indicator.IsReady)
            {
                _previousIndicatorValue = updated.Value;
                _previousSignal = actualPositionSignal;
                Signal = _previousSignal;
                return;
            }

            var actualSignal = GetActualSignal(_previousSignal, actualPositionSignal);

            Signal = actualSignal;
            _previousIndicatorValue = updated.Value;
            _previousSignal = actualSignal;
        }

        /// <summary>
        ///     Gets the actual position respect to the thresholds.
        /// </summary>
        /// <param name="indicatorCurrentValue">The indicator current value.</param>
        /// <returns></returns>
        protected virtual OscillatorSignals GetActualPositionSignal(decimal indicatorCurrentValue)
        {
            var positionSignal = OscillatorSignals.BetweenThresholds;
            if (indicatorCurrentValue > _thresholds.Upper)
            {
                positionSignal = OscillatorSignals.AboveUpperThreshold;
            }
            else if (indicatorCurrentValue < _thresholds.Lower)
            {
                positionSignal = OscillatorSignals.BellowLowerThreshold;
            }
            return positionSignal;
        }

        /// <summary>
        ///     Gets the actual signal from the actual position respect to the thresholds and the last signal.
        /// </summary>
        /// <param name="previousSignal">The previous signal.</param>
        /// <param name="actualPositionSignal">The actual position signal.</param>
        /// <returns></returns>
        private OscillatorSignals GetActualSignal(OscillatorSignals previousSignal,
            OscillatorSignals actualPositionSignal)
        {
            OscillatorSignals actualSignal;
            var previousSignalInt = (int)previousSignal;
            var actualPositionSignalInt = (int)actualPositionSignal;

            if (actualPositionSignalInt == 0)
            {
                if (Math.Abs(previousSignalInt) > 1)
                {
                    actualSignal = (OscillatorSignals)Math.Sign(previousSignalInt);
                }
                else
                {
                    actualSignal = OscillatorSignals.BetweenThresholds;
                }
            }
            else
            {
                if (previousSignalInt * actualPositionSignalInt <= 0 ||
                    Math.Abs(previousSignalInt + actualPositionSignalInt) == 3)
                {
                    actualSignal = (OscillatorSignals)(Math.Sign(actualPositionSignalInt) * 3);
                }
                else
                {
                    actualSignal = (OscillatorSignals)(Math.Sign(actualPositionSignalInt) * 2);
                }
            }
            return actualSignal;
        }

        /// <summary>
        ///     Sets up class.
        /// </summary>
        /// <param name="indicator">The indicator.</param>
        /// <param name="thresholds">The thresholds.</param>
        /// <param name="tradeRuleDirection">The trade rule direction.</param>
        private void SetUpClass(ref dynamic indicator, ref OscillatorThresholds thresholds,
            TradeRuleDirection? tradeRuleDirection = null)
        {
            _thresholds = thresholds;
            Indicator = indicator;
            indicator.Updated += new IndicatorUpdatedHandler(Indicator_Updated);
            if (tradeRuleDirection != null) _tradeRuleDirection = (TradeRuleDirection)tradeRuleDirection;
        }
    }
}
namespace QuantConnect
{
    public enum LotSize
    {
        Standard = 100000,
        Mini = 10000,
        Micro = 1000,
        Nano = 100,
    }
    
    public enum AgentAction
    {
        GoShort = -1,
        DoNothing = 0,
        GoLong = 1
    }

    public class FxRiskManagment
    {
        // Maximum equity proportion to put at risk in a single operation.
        private decimal _riskPerTrade;

        // Maximum equity proportion at risk in open positions in a given time.
        private decimal _maxExposure;

        // Maximum equity proportion at risk in a single trade.
        private decimal _maxExposurePerTrade;

        private int _lotSize;

        private int _minQuantity;

        private SecurityPortfolioManager _portfolio;

        /// <summary>
        /// Initializes a new instance of the <see cref="FxRiskManagment"/> class.
        /// </summary>
        /// <param name="portfolio">The QCAlgorithm Portfolio.</param>
        /// <param name="riskPerTrade">The max risk per trade.</param>
        /// <param name="maxExposurePerTrade">The maximum exposure per trade.</param>
        /// <param name="maxExposure">The maximum exposure in all trades.</param>
        /// <param name="lotsize">The minimum quantity to trade.</param>
        /// <exception cref="System.NotImplementedException">The pairs should be added to the algorithm before initialize the risk manager.</exception>
        public FxRiskManagment(SecurityPortfolioManager portfolio, decimal riskPerTrade, decimal maxExposurePerTrade,
                               decimal maxExposure, LotSize lotsize = LotSize.Micro, int minQuantity = 5)
        {
            _portfolio = portfolio;
            if (_portfolio.Securities.Count == 0)
            {
                throw new NotImplementedException("The pairs should be added to the algorithm before initialize the risk manager.");
            }
            this._riskPerTrade = riskPerTrade;
            _maxExposurePerTrade = maxExposurePerTrade;
            this._maxExposure = maxExposure;
            _lotSize = (int)lotsize;
            _minQuantity = minQuantity;
        }

        /// <summary>
        /// Calculates the entry orders and stop-loss price.
        /// </summary>
        /// <param name="pair">The Forex pair Symbol.</param>
        /// <param name="action">The order direction.</param>
        /// <returns>a Tuple with the quantity as Item1 and the stop-loss price as Item2. If quantity is zero, then means that no trade must be done.</returns>
        public Tuple<int, decimal, decimal> CalculateEntryOrders(QuoteBars data, Symbol pair, AgentAction action)
        {
            // If exposure is greater than the max exposure, then return zero.
            if (_portfolio.TotalMarginUsed > _portfolio.TotalPortfolioValue * _maxExposure)
            {
                return Tuple.Create(0, 0m, 0m);
            }
            var closePrice = _portfolio.Securities[pair].Price;
            var leverage = _portfolio.Securities[pair].Leverage;
            var exchangeRate = _portfolio.Securities[pair].QuoteCurrency.ConversionRate;
            var volatility = _portfolio.Securities[pair].VolatilityModel.Volatility;

            // Estimate the maximum entry order quantity given the risk per trade.
            var moneyAtRisk = _portfolio.TotalPortfolioValue * _riskPerTrade;
            var maxQuantitybyRisk = moneyAtRisk / (volatility * exchangeRate);
            // Estimate the maximum entry order quantity given the exposure per trade.
            var maxBuySize = Math.Min(_portfolio.MarginRemaining, _portfolio.TotalPortfolioValue * _maxExposurePerTrade) * leverage;
            var maxQuantitybyExposure = maxBuySize / (closePrice * exchangeRate);
            // The final quantity is the lowest of both.
            var quantity = (int)(Math.Round(Math.Min(maxQuantitybyRisk, maxQuantitybyExposure) / _lotSize, 0) * _lotSize);
            // If the final quantity is lower than the minimum quantity of the given lot size, then return zero.
            if (quantity < _lotSize * _minQuantity) return Tuple.Create(0, 0m, 0m);

            quantity = action == AgentAction.GoLong ? quantity : -quantity;
            var stopLossPrice = closePrice + (action == AgentAction.GoLong ? -volatility : volatility);
            return Tuple.Create(quantity, stopLossPrice, action == AgentAction.GoLong ? data[pair].Ask.Close : data[pair].Bid.Close);
        }

        /// <summary>
        /// Updates the stop-loss price of all open StopMarketOrders.
        /// </summary>
        public void UpdateTrailingStopOrders(QuoteBars data)
        {
            // Get all the spot-loss orders.
            var openStopLossOrders = _portfolio.Transactions.GetOrderTickets(o => o.OrderType == OrderType.StopMarket && o.Status == OrderStatus.Submitted);
            foreach (var ticket in openStopLossOrders)
            {
                var stopLossPrice = ticket.SubmitRequest.StopPrice;
                var volatility = _portfolio.Securities[ticket.Symbol].VolatilityModel.Volatility;
                var actualPrice = _portfolio.Securities[ticket.Symbol].Price;
                // The StopLossOrder has the opposite direction of the original order.
                var originalOrderDirection = ticket.Quantity > 0 ? OrderDirection.Sell : OrderDirection.Buy;
                if (originalOrderDirection == OrderDirection.Sell)
{
	actualPrice = data[ticket.Symbol].Ask.Close;
}
                if (originalOrderDirection == OrderDirection.Buy)
{
	actualPrice = data[ticket.Symbol].Bid.Close;
}
                var newStopLossPrice = actualPrice + (volatility * (originalOrderDirection == OrderDirection.Buy ? -1 : 1));
                if ((originalOrderDirection == OrderDirection.Buy && newStopLossPrice > stopLossPrice)
                    || (originalOrderDirection == OrderDirection.Sell && newStopLossPrice < stopLossPrice))
                {
                	
                	/*
		              if (originalOrderDirection == OrderDirection.Sell && data[ticket.Symbol].Ask.Close < System.Convert.ToDecimal(ticket.SubmitRequest.Tag))
		              {
		              	if(newStopLossPrice>System.Convert.ToDecimal(ticket.SubmitRequest.Tag))
		              	{
		              		newStopLossPrice = 	System.Convert.ToDecimal(ticket.SubmitRequest.Tag);
		              	}
		              }
		              if (originalOrderDirection == OrderDirection.Buy && data[ticket.Symbol].Bid.Close > System.Convert.ToDecimal(ticket.SubmitRequest.Tag))
		              {
		              	//price is on right direction
		              	if(newStopLossPrice<System.Convert.ToDecimal(ticket.SubmitRequest.Tag))
		              	{
		              		newStopLossPrice = 	System.Convert.ToDecimal(ticket.SubmitRequest.Tag);
		              	}
		              }
		              */
                    ticket.Update(new UpdateOrderFields { Quantity = _portfolio[ticket.Symbol].Quantity, StopPrice = newStopLossPrice });
                }
            }
        }
    }

}
namespace QuantConnect
{
    /// <summary>
    /// Provides an implementation of <see cref="IVolatilityModel"/> that computes the
    /// relative standard deviation as the volatility of the security
    /// </summary>
    public class ThreeSigmaVolatilityModel : IVolatilityModel
    {
        private readonly TimeSpan _periodSpan;
        private StandardDeviation _standardDeviation;
        private decimal _percentage;

        /// <summary>
        /// Gets the volatility of the security as a percentage
        /// </summary>
        public decimal Volatility
        {
            get { return _standardDeviation * _percentage; }
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="QuantConnect.Securities.RelativeStandardDeviationVolatilityModel"/> class
        /// </summary>
        /// <param name="periodSpan">The time span representing one 'period' length</param>
        /// <param name="periods">The nuber of 'period' lengths to wait until updating the value</param>
        public ThreeSigmaVolatilityModel(StandardDeviation standardDeviation, decimal percentage = 2.5m)
        {
            _standardDeviation = standardDeviation;
            _percentage = percentage;
            _periodSpan = TimeSpan.FromMinutes(standardDeviation.Period);
        }

        /// <summary>
        /// Updates this model using the new price information in
        /// the specified security instance
        /// </summary>
        /// <param name="security">The security to calculate volatility for</param>
        /// <param name="data"></param>
        public void Update(Security security, BaseData data)
        {
        }

        public IEnumerable<HistoryRequest> GetHistoryRequirements(Security security, DateTime utcTime)
        {
            return Enumerable.Empty<HistoryRequest>();
        }
    }
}
namespace QuantConnect
{
    /// <summary>
    ///     Possibles states of two moving averages.
    /// </summary>
    public enum BolingerBandsSignals
    {
        Bullish = 1,
        Bearish = -1,
        Middle = 0
    }


    /// <summary>
    ///     This class keeps track of two crossing moving averages and updates a <see cref="CrossingMovingAveragesSignals" />
    ///     for each given state.
    /// </summary>
    /// <seealso cref="QuantConnect.Algorithm.CSharp.ITechnicalIndicatorSignal" />
    public class BolingerBandsIndicator : SignalsBase
    {
        private  BollingerBands _bb;
        private  TradeRuleDirection _tradeRuleDirection;
        private int _lastSignal;
QCAlgorithm _log;
        /// <summary>
        ///     Initializes a new instance of the <see cref="CrossingMovingAverages" /> class.
        /// </summary>
        /// <param name="fast_moving_average">The fast moving average.</param>
        /// <param name="slow_moving_average">The slow moving average.</param>
        /// <param name="tradeRuleDirection">
        ///     The trade rule direction. Only used if the instance will be part of a
        ///     <see cref="TradingRule" /> class
        /// </param>
        /// <remarks>
        ///     Both Moving Averages must be registered BEFORE being used by this constructor.
        /// </remarks>
        public BolingerBandsIndicator(BollingerBands bb, QCAlgorithm log,
            TradeRuleDirection? tradeRuleDirection = null)
        {
            _bb = bb;
           // _bb.Updated += new IndicatorUpdatedHandler(ma_Updated);
            _log = log;
            SetUpClass(ref bb, tradeRuleDirection);
            //if (tradeRuleDirection != null) _tradeRuleDirection = (TradeRuleDirection)tradeRuleDirection;
        }
        
        private void Indicator_Updated(object sender, IndicatorDataPoint updated)
        {
            if (!IsReady)
            {
                return;
            }
            var actualSignal = GetActualPositionSignal(updated);

            _lastSignal = (int)actualSignal;
        }
        
        private void SetUpClass(ref BollingerBands indicator,
            TradeRuleDirection? tradeRuleDirection = null)
        {
            _bb = indicator;
            indicator.Updated += new IndicatorUpdatedHandler(Indicator_Updated);
            if (tradeRuleDirection != null) _tradeRuleDirection = (TradeRuleDirection) tradeRuleDirection;
        }

        /// <summary>
        ///     Gets a value indicating whether this instance is ready.
        /// </summary>
        /// <value>
        ///     <c>true</c> if this instance is ready; otherwise, <c>false</c>.
        /// </value>
        public override bool IsReady
        {
            get { return _bb.IsReady; }
        }

        public override TradeRuleDirection GetDirection()
        {
             return _tradeRuleDirection;
        }
        
        /// <summary>
        ///     Gets the actual state of both moving averages.
        /// </summary>
        public BolingerBandsSignals Signal { get; private set; }


        /// <summary>
        ///     Gets the signal. Only used if the instance will be part of a <see cref="TradingRule" /> class.
        /// </summary>
        /// <returns>
        ///     <c>true</c> if the actual <see cref="Signal" /> correspond with the instance <see cref="TradeRuleDirection" />.
        ///     <c>false</c>
        ///     otherwise.
        /// </returns>
        public override bool HasSignal()
        {
            var signal = false;
            if (IsReady)
            {
                switch (_tradeRuleDirection)
                {
                    case TradeRuleDirection.LongOnly:
                        signal = _lastSignal == (int)BolingerBandsSignals.Bullish;
                        break;

                    case TradeRuleDirection.ShortOnly:
                        signal = _lastSignal == (int)BolingerBandsSignals.Bearish;
                        break;

                    case TradeRuleDirection.Any:
                        signal = _lastSignal == (int)BolingerBandsSignals.Bearish || 
                                 _lastSignal == (int)BolingerBandsSignals.Bullish;
                        break;
                }
            }
            return signal;
        }

        /// <summary>
        ///     Gets the actual position respect to the thresholds.
        /// </summary>
        /// <param name="indicatorCurrentValue">The indicator current value.</param>
        /// <returns></returns>
        private BolingerBandsSignals GetActualPositionSignal(decimal indicatorCurrentValue)
        {
 
            var positionSignal = BolingerBandsSignals.Middle;
            if (indicatorCurrentValue > _bb.UpperBand)
            {
                _lastActiveSignal = new ActiveSignal();
                _lastActiveSignal.IsShort = true;
                positionSignal = BolingerBandsSignals.Bearish;//Bearish
            }
            else if (indicatorCurrentValue < _bb.LowerBand)
            {
                _lastActiveSignal = new ActiveSignal();
                _lastActiveSignal.IsLong = true;
                positionSignal = BolingerBandsSignals.Bullish;//Bullish
            }
            /*
            if(positionSignal!=BolingerBandsSignals.Middle)
            {

                        _log.Log("indicatorCurrentValue:: " + indicatorCurrentValue);
                        _log.Log("UpperBand:: "+_bb.UpperBand);
                        _log.Log("LowerBand:: "+_bb.LowerBand);
                        _log.Log("positionSignal:: "+positionSignal);
                
            }
            */
            return positionSignal;
        }

    }
}
namespace QuantConnect
{
    public enum RuleOperators
    {
        AND = 1,
        OR = 0
    }
    public class TradingRuleQCVersion
    {
        private readonly ITechnicalIndicatorSignal[] _technicalIndicatorSignals;
        private readonly RuleOperators[] _ruleOperators;
        private readonly bool _isEntryRule;
        private Symbol _symbol;

        public TradingRuleQCVersion(ITechnicalIndicatorSignal[] technicalIndicatorSignals, RuleOperators[] ruleOperators, bool isEntryRule, Symbol symbol)
        {
            _technicalIndicatorSignals = technicalIndicatorSignals;
            _isEntryRule = isEntryRule;
            _symbol = symbol;
            _ruleOperators = ruleOperators;
        }


        public bool IsReady
        {
            get
            {
                var isReady = true;
                foreach (var indicator in _technicalIndicatorSignals)
                {
                    isReady = indicator.IsReady && isReady;
                }
                return isReady;
            }
        }
        
        public Symbol Symbol
        {
            get { return _symbol; }
        }

        public bool TradeRuleSignal
        {
            get { return GetTradeRuleSignal(); }
        }

        /// <summary>
        /// Gets the trade rule signal for the best in-sample performance individual.
        /// </summary>
        /// <returns></returns>
        private bool GetTradeRuleSignal()
        {
            var signal = false;
            //if (_isEntryRule)
            {
            	signal =_technicalIndicatorSignals[0].HasSignal();
                    for (var i = 1; i < _technicalIndicatorSignals.Length; i++)
                    {
                    	signal = op(i, signal, i-1);
                    }
                          /*&&   //  Long SimpleMovingAverage
                          _technicalIndicatorSignals[1].HasSignal() ||   //  Long Stochastic
                          _technicalIndicatorSignals[2].HasSignal() &&   //  Long RelativeStrengthIndex
                          _technicalIndicatorSignals[3].HasSignal() ||   //  Short MovingAverageConvergenceDivergence
                          _technicalIndicatorSignals[4].HasSignal() )||     //  Short MomentumPercent
                    _technicalIndicatorSignals[5].HasSignal();     //  Long BollingerBands
                         
                signal = signal || _technicalIndicatorSignals[5].HasSignal();     //  Long BollingerBands
                */
            }
            /*
            else
            {
                signal = _technicalIndicatorSignals[0].HasSignal() ||   //  Short CommodityChannelIndex
                         _technicalIndicatorSignals[1].HasSignal() &&   //  Long RelativeStrengthIndex
                                                      _technicalIndicatorSignals[2].HasSignal() ||   //  Short Stochastic
                                                      _technicalIndicatorSignals[3].HasSignal() &&   //  Long MovingAverageConvergenceDivergence
                                                      _technicalIndicatorSignals[4].HasSignal();
                         //||   //  Long Stochastic
                         //_technicalIndicatorSignals[5].GetSignal();       //  Short BollingerBands
            }
            */
            return signal;
        }

        private bool op(int ind1, bool ind2, int op)
        {
            if(_ruleOperators[op]==RuleOperators.AND)
            {
                return _technicalIndicatorSignals[ind1].HasSignal() && ind2;
            }
            return _technicalIndicatorSignals[ind1].HasSignal() || ind2;
        }
    }
}
namespace QuantConnect
{
    public abstract class SignalsBase : ITechnicalIndicatorSignal
    {
        protected ActiveSignal _lastActiveSignal;

        protected SignalsBase()
        {
        }

        public abstract bool IsReady { get; }

        public abstract TradeRuleDirection GetDirection();

        public ActiveSignal GetSignal()
        {
            return _lastActiveSignal;
        }

        public abstract bool HasSignal();
    }
}
using Newtonsoft.Json;
namespace QuantConnect
{
    public class ActiveSignal
    {
        public int Id { get; set; }
        public bool IsCompleted { get; set; }
        public bool IsLong { get; set; }
        public bool IsShort { get; set; }
        public string Symbol { get; set; }
        public DateTime Expiration { get; set; }
        public DateTime SetupDate { get; set; }
        public decimal Forecast { get; set; }
        public string GenSignalTag()
        {
            var orderTag = new OrderTag
            {
                SignalId = Id,
                Expiration = Expiration,
                Target = Forecast
            };
            return JsonConvert.SerializeObject(orderTag);
        }
    }
}
namespace QuantConnect
{
    public class OrderTag
    {
        public int SignalId { get; set; } = 0;
        public DateTime Expiration { get; set; } = DateTime.MaxValue;
        public decimal Target { get; set; } = 0;
    }
}
namespace QuantConnect.Algorithm.CSharp.Algo
{
    /// <summary>
    ///     This class keeps track of an oscillator respect to its thresholds and updates an <see cref="BBOscillatorSignal" />
    ///     for each given state.
    /// </summary>
    /// <seealso cref="QuantConnect.Algorithm.CSharp.ITechnicalIndicatorSignal" />
    public class BBOscillatorSignal : OscillatorSignal
    {
        private BollingerBands _bb;

        /// <summary>
        ///     Initializes a new instance of the <see cref="BBOscillatorSignal" /> class.
        /// </summary>
        /// <param name="indicator">The indicator.</param>
        /// <remarks>The oscillator must be registered BEFORE being used by this constructor.</remarks>
        public BBOscillatorSignal(BollingerBands indicator, TradeRuleDirection tradeRuleDirection, QCAlgorithm log) : base(indicator, tradeRuleDirection, log)
        {
            
            _bb = indicator;
        }

        /// <summary>
        ///     Gets the actual position respect to the thresholds.
        /// </summary>
        /// <param name="indicatorCurrentValue">The indicator current value.</param>
        /// <returns></returns>
        protected override OscillatorSignals GetActualPositionSignal(decimal indicatorCurrentValue)
        {
            var positionSignal = OscillatorSignals.BetweenThresholds;
            if (indicatorCurrentValue > _bb.UpperBand)
            {
                positionSignal = OscillatorSignals.AboveUpperThreshold;
            }
            else if (indicatorCurrentValue < _bb.LowerBand)
            {
                positionSignal = OscillatorSignals.BellowLowerThreshold;
            }
            return positionSignal;
        }
    }
}