Overall Statistics
Total Trades
16285
Average Win
0.15%
Average Loss
-0.88%
Compounding Annual Return
281.049%
Drawdown
23.000%
Expectancy
0.012
Net Profit
117.261%
Sharpe Ratio
2.659
Loss Rate
13%
Win Rate
87%
Profit-Loss Ratio
0.17
Alpha
1.157
Beta
-0.149
Annual Standard Deviation
0.442
Annual Variance
0.195
Information Ratio
2.792
Tracking Error
0.462
Treynor Ratio
-7.896
Total Fees
$651.40
/*
 * 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 System;
using System.Collections.Generic;
using QuantConnect.Brokerages;
using QuantConnect.Data;
using QuantConnect.Data.Custom;
using QuantConnect.Data.Market;
using QuantConnect.Indicators;
using QuantConnect.Orders;
using QuantConnect.Orders.Fees;
using QuantConnect.Securities;

namespace QuantConnect.Algorithm.CSharp
{
    /// <summary>
    /// Basic template algorithm simply initializes the date range and cash
    /// </summary>
    public class BasicTemplateAlgorithm : QCAlgorithm, IRequiredOrderMethods
    {
        //Configure which securities you'd like to use:
        public string[] Symbols = { "EURUSD", "NZDUSD", "GBPUSD" , "NZDCHF"};

        //Risk in dollars per trade ($ or the quote currency of the assets)
        public decimal RiskPerTrade = 40;

        //Sets the profit to loss ratio we want to hit before we exit
        public decimal TargetProfitLossRatio = 0.125m;

        //Cap the investment maximum size ($).
        public decimal MaximumTradeSize = 10000;

        private Resolution _dataResolution = Resolution.Minute;
        private Dictionary<Symbol, TradingAsset> _tradingAssets;

        private WilliamsFractals _williamsFractals;

        public override void Initialize()
        {
            SetStartDate(2015, 1, 1);
            SetEndDate(2015, 8, 1);
            SetCash(3000);
            _tradingAssets = new Dictionary<Symbol, TradingAsset>();
            
            //Add as many securities as you like. All the data will be passed into the event handler:
            foreach (var symbol in Symbols)
            {
                AddSecurity(SecurityType.Forex, symbol, _dataResolution);
                Securities[symbol].FeeModel = new ConstantFeeModel(0.04m);
//                Securities[symbol].FeeModel = new FxcmFeeModel();
                //SetBrokerageModel(BrokerageName.FxcmBrokerage);

                _williamsFractals = new WilliamsFractals();

                Securities[symbol].VolatilityModel = new ThreeSigmaVolatilityModel(STD(symbol, 60, _dataResolution));

                _tradingAssets.Add(symbol,
                    new TradingAsset(Securities[symbol],
                        new OneShotTrigger(new FractalSignal(_williamsFractals, Portfolio[symbol])),
                        // new FractalExit(null, _williamsFractals, Portfolio[symbol]), 
                        new ProfitTargetSignalExit(null, TargetProfitLossRatio),
                        RiskPerTrade,
                        MaximumTradeSize,
                        this
                    ));
            }
            SetBenchmark("EURUSD");
        }

        /// <summary>
        /// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
        /// </summary>
        public void OnData(TradeBars data)
        {
            if (data.Count < Symbols.Length) return;

//            if (!_williamsFractals.IsReady) return;
            
            foreach (var symbol in Symbols)
            {
                _williamsFractals.Update(data[symbol]);

                //Create a trading asset package for each symbol 
                _tradingAssets[symbol].Scan(data[symbol]);
            }
        }

//        public void OnData(Quandl data)
//        {
//
//        }


    }

    /// <summary>
    /// Interface for the two types of orders required to make the trade
    /// </summary>
    public interface IRequiredOrderMethods
    {
        OrderTicket StopMarketOrder(Symbol symbol, int quantity, decimal stopPrice, string tag = "");
        OrderTicket MarketOrder(Symbol symbol, int quantity, bool asynchronous = false, string tag = "");
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using QuantConnect.Data.Market;
using QuantConnect.Indicators;

namespace QuantConnect.Algorithm.CSharp
{
    class WilliamsFractals : TradeBarIndicator
    {
        private readonly RollingWindow<TradeBar> _fractal;
        private readonly int _fractalMidIndex;

        private decimal _barryUp;
        private decimal _barryDown;

        public decimal BarryUp => _barryUp;
        public decimal BarryDown => _barryDown;
        public decimal MidPoint => (_barryUp - _barryDown) / 2m;

        public override bool IsReady => _fractal.IsReady;

        public WilliamsFractals(int fractalLength = 5) : this("WilliamsFractals" + fractalLength, fractalLength)
        {
        }

        public WilliamsFractals(string name, int fractalLength = 5) : base(name)
        {
            _fractal = new RollingWindow<TradeBar>(fractalLength);
            _fractalMidIndex = fractalLength / 2 - (fractalLength % 2 == 0 ? 1 : 0);
        }

        protected override decimal ComputeNextValue(TradeBar input)
        {
            _fractal.Add(input);

            if (!_fractal.IsReady) return MidPoint;

            if (_fractal.Max(bar => bar.High) == _fractal[_fractalMidIndex].High)
            {
                _barryUp = input.High;
            }

            if (_fractal.Min(bar => bar.Low) == _fractal[_fractalMidIndex].Low)
            {
                _barryDown = input.Low;
            }

            return MidPoint;
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using QuantConnect.Data.Market;
using QuantConnect.Securities;

namespace QuantConnect.Algorithm.CSharp
{
    class FractalExit :IExitSignal
    {
        private TradeProfile _tradeProfile;
        private WilliamsFractals _williamsFractals;
        private SecurityHolding _securityHolding;

        public FractalExit(TradeProfile tradeProfile, WilliamsFractals williamsFractals, SecurityHolding securityHolding)
        {
            _tradeProfile = tradeProfile;
            _williamsFractals = williamsFractals;
            _securityHolding = securityHolding;
        }

        public void Scan(TradeBar data)
        {
            _williamsFractals.Update(data);

            if (_securityHolding.IsLong)
            {
                Signal = data.Price >= _williamsFractals.BarryUp ? SignalType.Exit : SignalType.NoSignal;
            }
            else if (_securityHolding.IsShort)
            {
                Signal = data.Price <= _williamsFractals.BarryDown ? SignalType.Exit : SignalType.NoSignal;
            }
            else
            {
                Signal = SignalType.NoSignal;
            }
        }

        public SignalType Signal { get; private set; }


        public ISignal ExitSignalFactory(TradeProfile tradeProfile)
        {
            return new FractalExit(tradeProfile, _williamsFractals, _securityHolding);
        }
    }
}
using QuantConnect.Orders;

namespace QuantConnect.Algorithm.CSharp
{
    public class TradeProfile
    {

        //Ticket tracking the open order
        public OrderTicket OpenTicket, StopTicket, ExitTicket;
        //Keeps track of the current price and the direction of the trade
        public Symbol TradeSymbol;
        public int TradeDirection;
        public decimal CurrentPrice;

        private readonly decimal _risk;
        private readonly int _maximumTradeQuantity;

        protected decimal Volatility;

        /// <summary>
        /// Calclate the quantity based on the target risk in dollars.
        /// </summary>
        public int Quantity
        {
            get
            {
                if (Volatility == 0) return 0;
                long quantity = (long)(_risk / Volatility);
                if (quantity > _maximumTradeQuantity)
                {
                    return _maximumTradeQuantity < 1000 ? 1000 : _maximumTradeQuantity;
                }

                return (int) quantity < 1000 ? 1000 : (int) quantity;
            }
        }

        /// <summary>
        /// What is the stoploss move from current price
        /// </summary>
        public decimal DeltaStopLoss
        {
            get
            {
                if (Quantity == 0) return 0m;
                return _risk / Quantity;
            }
        }

        /// <summary>
        /// Calculates  the Profit:Loss ratio
        /// </summary>
        public decimal ProfitLossRatio
        {
            get
            {
                if(OpenTicket != null)
                {
                      return OpenTicket.Quantity*(CurrentPrice - OpenTicket.AverageFillPrice)  /_risk;
                }
                return 0m;
            }
        }

        /// <summary>
        /// Exit signal for each trade
        /// </summary>
        public ISignal ExitSignal
        {
            get;
            set;
        }

        public bool IsTradeFinished { get; set; }


        /// <summary>
        /// Create a new tradeProfile and limit the maximum risk.
        /// </summary>
        /// <param name="symbol"></param>
        /// <param name="volatility"></param>
        /// <param name="risk"></param>
        /// <param name="currentPrice"></param>
        /// <param name="maximumTradeSize"></param>
        /// <param name="exitSignal"></param>
        public TradeProfile(Symbol symbol, decimal volatility, decimal risk, decimal currentPrice, decimal maximumTradeSize)
        {
            TradeSymbol = symbol;
            Volatility = volatility;
            _risk = risk;
            CurrentPrice = currentPrice;
            _maximumTradeQuantity = (int) (maximumTradeSize/CurrentPrice);
        }
    }
}
using QuantConnect.Data.Market;
using QuantConnect.Securities;

namespace QuantConnect.Algorithm.CSharp
{
    class FractalSignal : ISignal
    {
        private WilliamsFractals _williamsFractals;
        private SecurityHolding _securityHolding;

        public FractalSignal(WilliamsFractals williamsFractals, SecurityHolding securityHolding)
        {
            _williamsFractals = williamsFractals;
            _securityHolding = securityHolding;
        }

        public void Scan(TradeBar data)
        {
            _williamsFractals.Update(data);
            if (_williamsFractals.IsReady)
            {
                if (data.Price >= _williamsFractals.BarryUp && !_securityHolding.Invested)
                {
                    Signal = SignalType.Short;
                }
                else if (data.Price <= _williamsFractals.BarryDown && !_securityHolding.Invested)
                {
                    Signal = SignalType.Long;
                }
                else
                {
                    Signal = SignalType.NoSignal;
                }
            }
            else
            {
                Signal = SignalType.NoSignal;
            }
        }

        public SignalType Signal { get; private set; }
    }
}
using System.Collections.Generic;
using System.Linq;
using QuantConnect.Data.Market;
using QuantConnect.Orders;
using QuantConnect.Securities;

namespace QuantConnect.Algorithm.CSharp
{
    class TradingAsset
    {
        public IExitSignal ExitSignal;
        public ISignal EnterSignal;

        private readonly decimal _risk;
        private readonly Symbol _symbol;
        private readonly Security _security;
        private readonly decimal _maximumTradeSize;
        private List<TradeProfile> _tradeProfiles;
        private readonly IRequiredOrderMethods _orderMethods;

        /// <summary>
        /// Initializes each Trading Asset
        /// </summary>
        /// <param name="security"></param>
        /// <param name="enterSignal"></param>
        /// <param name="exitSignal"></param>
        /// <param name="risk"></param>
        /// <param name="maximumTradeSize"></param>
        /// <param name="orderMethods"></param>
        public TradingAsset(Security security, ISignal enterSignal, IExitSignal exitSignal, decimal risk, decimal maximumTradeSize, IRequiredOrderMethods orderMethods)
        {
            _security = security;
            _symbol = _security.Symbol;
            EnterSignal = enterSignal;
            ExitSignal = exitSignal;
            _risk = risk;
            _maximumTradeSize = maximumTradeSize;
            _orderMethods = orderMethods;
            _tradeProfiles = new List<TradeProfile>();
        }

        /// <summary>
        /// Scan
        /// </summary>
        /// <param name="data"></param>
        public void Scan(TradeBar data)
        {
            UpdateCurrentPrice(data);
            MarkStopTicketsFilled();
            EnterTradeSignal(data);
            ExitTradeSignal(data);
            RemoveAllFinishedTrades();
        }

        /// <summary>
        /// Executes all the logic when the Enter Signal is triggered
        /// </summary>
        /// <param name="data"></param>
        public void EnterTradeSignal(TradeBar data)
        {
            EnterSignal.Scan(data);
            if (EnterSignal.Signal == SignalType.Long || EnterSignal.Signal == SignalType.Short)
            {
                //Creates a new trade profile once it enters a trade
                var profile = new TradeProfile(_symbol, _security.VolatilityModel.Volatility, _risk, data.Close, _maximumTradeSize);
               
                //Creates a new instance of the exit signal
                profile.ExitSignal = ExitSignal.ExitSignalFactory(profile);

                var profileQuantity = profile.Quantity;

                if (profileQuantity <= 0) return;

                profile.OpenTicket = _orderMethods.MarketOrder(_symbol, (int)EnterSignal.Signal * profile.Quantity);
                profile.StopTicket = _orderMethods.StopMarketOrder(_symbol, -(int)EnterSignal.Signal * profile.Quantity,
                    profile.OpenTicket.AverageFillPrice - (int)EnterSignal.Signal * profile.DeltaStopLoss);

                _tradeProfiles.Add(profile);
            }
        }

        /// <summary>
        /// Executes all the logic when the Exit Signal is triggered
        /// </summary>
        /// <param name="data"></param>
        public void ExitTradeSignal(TradeBar data)
        {
            foreach (var tradeProfile in _tradeProfiles.Where(x => x.IsTradeFinished == false))
            {
                tradeProfile.ExitSignal.Scan(data);

                if (tradeProfile.ExitSignal.Signal == SignalType.Exit)
                {
                    if (tradeProfile.StopTicket.Status != OrderStatus.Filled)
                    {
                        tradeProfile.ExitTicket = _orderMethods.MarketOrder(_symbol, -(int)tradeProfile.OpenTicket.QuantityFilled);
                        tradeProfile.StopTicket.Cancel();

                        tradeProfile.IsTradeFinished = true;
                    }
                }
            }
        }

        /// <summary>
        /// Marks all the trades as finished which are completed due to hitting the stop loss
        /// </summary>
        public void MarkStopTicketsFilled()
        {
            foreach (var tradeProfile in _tradeProfiles)
            {
                if (tradeProfile.StopTicket.Status == OrderStatus.Filled)
                {
                    tradeProfile.IsTradeFinished = true;
                }
            }
        }

        /// <summary>
        /// Removes all the completed trades from the trade profile list
        /// </summary>
        public void RemoveAllFinishedTrades()
        {
            _tradeProfiles = _tradeProfiles.Where(x => !x.IsTradeFinished).ToList();
        }

        /// <summary>
        /// Update the current price of the asset
        /// </summary>
        /// <param name="data"></param>
        public void UpdateCurrentPrice(TradeBar data)
        {
            foreach (var tradeProfile in _tradeProfiles)
            {
                tradeProfile.CurrentPrice = data.Close;
            }
        }
    }
}
using QuantConnect.Data.Market;

namespace QuantConnect.Algorithm.CSharp
{
    class OneShotTrigger : ISignal
    {
        private readonly ISignal _signal;
        private SignalType _previousSignalType;

        /// <summary>
        /// Initializes our one shot trigger
        /// </summary>
        /// <param name="signal"></param>
        public OneShotTrigger(ISignal signal)
        {
            _signal = signal;
            Signal = SignalType.NoSignal;
            _previousSignalType = SignalType.NoSignal;
        }

        /// <summary>
        /// Scans if the trigger is hit
        /// </summary>
        /// <param name="data"></param>
        public void Scan(TradeBar data)
        {
            _signal.Scan(data);

            if(_signal.Signal != _previousSignalType)
            {
                Signal = _signal.Signal;
            }
            else
            {
                Signal = SignalType.NoSignal;
            }
            _previousSignalType = _signal.Signal;
        }

        public SignalType Signal { get; private set; }
    }
}
/*
 * 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.Data;
using QuantConnect.Indicators;

namespace QuantConnect.Securities
{
    /// <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 StandardDeviation _standardDeviation;


        /// <summary>
        /// Gets the volatility of the security
        /// </summary>
        public decimal Volatility
        {
            get { return _standardDeviation*2.5m; }
        }

        /// <summary>
        /// Initializes an instance of the standard deviation
        /// </summary>
        /// <param name="standardDeviation"></param>
        public ThreeSigmaVolatilityModel(StandardDeviation standardDeviation)
        {
            _standardDeviation = standardDeviation;
        }

        /// <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) {}
        
    }
}
using QuantConnect.Data.Market;

namespace QuantConnect.Algorithm.CSharp
{
    /// <summary>
    /// Base Signal Interface
    /// </summary>
    public interface ISignal
    {
        void Scan(TradeBar data);

        SignalType Signal { get; }
    }

    /// <summary>
    /// Exit Signal for the trade
    /// </summary>
    public interface IExitSignal : ISignal
    {
        ISignal ExitSignalFactory(TradeProfile tradeProfile);
    }
    
    /// <summary>
    /// Indicates the type of signal
    /// </summary>
    public enum SignalType
    {
        Long = 1,
        Short = -1,
        Exit = 2,
        NoSignal = 0
    }
}
using QuantConnect.Data.Market;
using QuantConnect.Indicators;
using QuantConnect.Securities;

namespace QuantConnect.Algorithm.CSharp
{
    class ProfitTargetSignalExit : IExitSignal
    {
        private readonly TradeProfile _tradeProfile;
        private readonly decimal _targetProfitLossRatio;

        public ProfitTargetSignalExit() { }

        /// <summary>
        /// Initializes the profit target indicator for the exits
        /// </summary>
        /// <param name="tradeProfile"></param>
        /// <param name="targetProfitLossRatio"></param>
        public ProfitTargetSignalExit(TradeProfile tradeProfile, decimal targetProfitLossRatio)
        {
            _tradeProfile = tradeProfile;
            _targetProfitLossRatio = targetProfitLossRatio;
        }

        /// <summary>
        /// Scans if the current profit ratio goes above the target ratio 
        /// </summary>
        /// <param name="data"></param>
        public void Scan(TradeBar data)
        {
            if (_tradeProfile.ProfitLossRatio > _targetProfitLossRatio)
            {
                Signal = SignalType.Exit;
            }
            else
            {
                Signal = SignalType.NoSignal;
            }
        }

        public SignalType Signal { get; private set; }

        /// <summary>
        /// Create a new instance of our exit signal
        /// </summary>
        /// <param name="tradeProfile"></param>
        /// <returns></returns>
        public ISignal ExitSignalFactory(TradeProfile tradeProfile)
        {
            return new ProfitTargetSignalExit(tradeProfile, _targetProfitLossRatio);
        }
    }
}