Overall Statistics
Total Trades
988
Average Win
0.02%
Average Loss
-0.02%
Compounding Annual Return
-0.843%
Drawdown
1.100%
Expectancy
-0.092
Net Profit
-0.844%
Sharpe Ratio
-0.988
Loss Rate
57%
Win Rate
43%
Profit-Loss Ratio
1.09
Alpha
-0.006
Beta
-0.005
Annual Standard Deviation
0.006
Annual Variance
0
Information Ratio
-0.068
Tracking Error
0.132
Treynor Ratio
1.129
Total Fees
$0.00
using QuantConnect.Data.Market;

namespace QuantConnect.Algorithm.CSharp
{
    /// <summary>
    /// Base Signal Interface
    /// </summary>
    public interface ISignal
    {
        void Scan(TradeBar data);
        int Signal
        {       
            get;
        }
    }
}
using System.Collections.Generic;
using System.Linq;
using QuantConnect.Data.Market;
using QuantConnect.Orders;
using QuantConnect.Securities;

namespace QuantConnect.Algorithm.CSharp
{
    class TradingAsset
    {
        public ISignal ExitSignal;
        public ISignal EnterSignal;
       
        private decimal _risk;
        private Symbol _symbol;
        private Security _security;
        private decimal _maximumTradeSize;
        private List<TradeProfile> _tradeProfiles;
        private 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, ISignal 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)
        {
            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 != 0)
            {
                //Creates a new trade profile once it enters a trade
                var profile = new TradeProfile(_symbol, _security.VolatilityModel.Volatility, _risk, data.Close, _maximumTradeSize, ExitSignal);

                profile.OpenTicket = _orderMethods.MarketOrder(_symbol, EnterSignal.Signal * profile.Quantity);
                profile.StopTicket = _orderMethods.StopMarketOrder(_symbol, -EnterSignal.Signal * profile.Quantity,
                    profile.OpenTicket.AverageFillPrice - 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 != 0)
                {
                    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();
        }
    }
}
using System;
using QuantConnect.Data.Market;
using QuantConnect.Orders;

namespace QuantConnect.Algorithm.CSharp
{
    /// <summary>
    /// This Time Signal Enters the trade at a particular time and exits the trade at a particular time set for the entery and exit
    /// </summary>
    public class TimeSignal : ISignal
    {
        private Random random = new Random(131);
        private TimeSpan _timeOfDay;

        public TimeSignal(TimeSpan timeOfDay)
        {
            _timeOfDay = timeOfDay;
        }

        /// <summary>
        /// Scans the new data coming in and randomly assigns direction if entry conditions are met
        /// </summary>
        /// <param name="data"></param>
        public void Scan(TradeBar data)
        {
            if (data.Time.TimeOfDay == _timeOfDay)
            {
                Signal = (RandomOrderDirection() == OrderDirection.Buy) ? 1 : -1;
            }
            else
            {
                Signal = 0;
            }
        }

        /// <summary>
        /// Signal value for the binary signal
        /// </summary>
        public int Signal
        {
            get;
            private set;
        }

        /// <summary>
        /// Produces a random direction for the signal to trade
        /// </summary>
        /// <returns></returns>
        private OrderDirection RandomOrderDirection()
        {
            if (random.NextDouble() > 0.5)
                return OrderDirection.Buy;
            return OrderDirection.Sell;
        }
    }
}
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 decimal CurrentPrice;
        public int TradeDirection;
        public Symbol TradeSymbol;
        private bool isTradeFinished;

        private decimal _risk;
        private int _maximumTradeQuantity;
        protected decimal _volatility;

        // Calclate the quantity based on the target risk in dollars.
        public int Quantity
        {
            get
            {
                long quantity = (long)(_risk / _volatility);
                if (quantity > _maximumTradeQuantity) return _maximumTradeQuantity;
                return (int)quantity;
            }
        }

        //What is the stoploss move from current price
        public decimal DeltaStopLoss
        {
            get
            {
                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
            {
                return isTradeFinished;
            }

            set
            {
                isTradeFinished = value;
            }
        }


        /// <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, ISignal exitSignal)
        {
            TradeSymbol = symbol;
            _volatility = volatility;
            _risk = risk;
            CurrentPrice = currentPrice;
            _maximumTradeQuantity = (int)(maximumTradeSize / CurrentPrice);
            ExitSignal = exitSignal;
        }
    }
}
/*
 * 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.Data.Market;
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", "GBPUSD"};

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

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

        //Roughly how long does our "alpha" take to run
        public TimeSpan AverageInvestmentPeriod = TimeSpan.FromHours(6.5);

        //Cap the investment maximum size ($).
        public decimal MaximumTradeSize = 10000;
        
        private Resolution _dataResolution = Resolution.Minute;
        private Dictionary<Symbol, TradingAsset> _tradingAssets;

        public override void Initialize()
        {
            SetStartDate(2015, 1, 1);
            SetEndDate(2016, 01, 01);
            SetCash(25000);
            _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.0m);
                //SetBrokerageModel(BrokerageName.FxcmBrokerage);

                Securities[symbol].VolatilityModel = new ThreeSigmaVolatilityModel(_dataResolution.ToTimeSpan(), (int)AverageInvestmentPeriod.TotalMinutes);
                _tradingAssets.Add(symbol,
                    new TradingAsset(Securities[symbol], 
                        new TimeSignal(TimeSpan.FromHours(9.5)),
                        new TimeSignal(TimeSpan.FromHours(16)), 
                        RiskPerTrade,
                        MaximumTradeSize,
                        this
                    ));
            }
        }

        /// <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)
        {
            foreach (var symbol in Symbols)
            {
                //Create a trading asset package for each symbol 
                _tradingAssets[symbol].Scan(data[symbol]);
            }
        } 
    }

    /// <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 = "");
    }
}
/*
 * 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 MathNet.Numerics.Statistics;
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 bool _needsUpdate;
        private decimal _volatility;
        private DateTime _lastUpdate;
        private readonly TimeSpan _periodSpan;
        private readonly object _sync = new object();
        private readonly RollingWindow<double> _window;

        /// <summary>
        /// Gets the volatility of the security as a percentage
        /// </summary>
        public decimal Volatility
        {
            get
            {
                lock (_sync)
                {
                    if (_window.Count < 2)
                    {
                        return 0m;
                    }

                    if (_needsUpdate)
                    {
                        _needsUpdate = false;
                        // volatility here is supposed to be a percentage
                        var std = _window.StandardDeviation().SafeDecimalCast();
                        _volatility = std * 3;
                    }
                }
                return _volatility;
            }
        }

        /// <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(TimeSpan periodSpan, int periods)
        {
            if (periods < 2) throw new ArgumentOutOfRangeException("periods", "'periods' must be greater than or equal to 2.");
            _periodSpan = periodSpan;
            _window = new RollingWindow<double>(periods);
            _lastUpdate = DateTime.MinValue + TimeSpan.FromMilliseconds(periodSpan.TotalMilliseconds * periods);
        }

        /// <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)
        {
            var timeSinceLastUpdate = data.EndTime - _lastUpdate;
            if (timeSinceLastUpdate >= _periodSpan)
            {
                lock (_sync)
                {
                    _needsUpdate = true;
                    // we purposefully use security.Price for consistency in our reporting
                    // some streams of data will have trade/quote data, so if we just use
                    // data.Value we could be mixing and matching data streams
                    _window.Add((double)security.Price);
                }
                _lastUpdate = data.EndTime;
            }
        }
    }
}