Overall Statistics
Total Trades
990
Average Win
0.23%
Average Loss
-0.22%
Compounding Annual Return
0.195%
Drawdown
4.100%
Expectancy
0.004
Net Profit
0.196%
Sharpe Ratio
0.052
Loss Rate
51%
Win Rate
49%
Profit-Loss Ratio
1.04
Alpha
0.003
Beta
0.001
Annual Standard Deviation
0.049
Annual Variance
0.002
Information Ratio
-0.003
Tracking Error
0.14
Treynor Ratio
3.07
Total Fees
$0.00
namespace QuantConnect {

    // Tracking all the Trade information in a single class
    public class TradeProfile 
    {
    	
    	 //Ticket tracking the open order
        public OrderTicket OpenTicket, StopTicket;
        //Keeps track of the current price and the direction of the trade
        public decimal CurrentPrice;
        public int TradeDirection;

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

        // Calclate the quantity based on the target risk in dollars.
        public int Quantity
        {
            get
            {
                if (_volatility == 0) return 0;

                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;
            }
        }

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

        //Create a new tradeProfile and limit the maximum risk.
        public TradeProfile(decimal volatility, decimal risk, decimal currentPrice, decimal maximumTradeSize)
        {
            _volatility = volatility;
            _risk = risk;
            CurrentPrice = currentPrice;
            _maximumTradeQuantity = (int)(maximumTradeSize / CurrentPrice);
        }
    }
}
namespace QuantConnect 
{  
    public class BasicTemplateAlgorithm : QCAlgorithm
    {
       //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 = 1.2m;

        //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, TradeProfile> _trades;
        private Slice _data;
        private Random random = new Random(131);

        public override void Initialize()
        {
            SetStartDate(2015, 1, 1);
            SetEndDate(2016, 01, 01);
            SetCash(2500);

            //Hold a trade profile per asset we're trading.
            _trades = new Dictionary<Symbol, TradeProfile>();

            //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);

                //Roughly 4c per 1000 traded, roughly 8c fees per trade.
                Securities[symbol].FeeModel = new ConstantFeeModel(0.0m);

                //Set our volatility model: the expected price movement for the day is 3 sigma of the standard deviation
                Securities[symbol].VolatilityModel = new ThreeSigmaVolatilityModel(_dataResolution.ToTimeSpan(), (int)AverageInvestmentPeriod.TotalMinutes);
            }

            //Might but bug with the FXCM model? Fees way higher than normal?
            // SetBrokerageModel(BrokerageName.FxcmBrokerage);
            var dates = new[] { DayOfWeek.Monday, DayOfWeek.Tuesday, DayOfWeek.Wednesday, DayOfWeek.Thursday, DayOfWeek.Friday };


            // SUPER SECRET ALHA INDICATOR!!!!! Trade every day at 930, exit at 4pm :D
            Schedule.On(DateRules.Every(dates), TimeRules.At(09, 30), () =>
            {
                foreach (var symbol in Symbols)
                {
                    // ENTER THE MARKET RANDOM DIRECTION...!
                    if (Securities[symbol].VolatilityModel.Volatility == 0) continue;
                    _trades[symbol] = Enter(symbol, RandomOrderDirection());
                }
            });

            Schedule.On(DateRules.Every(dates), TimeRules.At(16, 00), () =>
            {
                foreach (var symbol in Symbols)
                {
                    // If the stoploss hasn't triggered, quit
                    if (!Portfolio[symbol].Invested) continue;
                    Exit(_trades[symbol]);
                }
            });
        }

        /// <summary>
        /// Generate a random order direction for the "super secret alpha signal"
        /// </summary>
        private OrderDirection RandomOrderDirection()
        {
            if (random.NextDouble() > 0.5) return OrderDirection.Buy;
            return OrderDirection.Sell;
        }

        /// <summary>
        /// OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
        /// </summary>
        public override void OnData(Slice data)
        {
            _data = data;
            
            foreach (var symbol in Symbols)
            {
                if (_trades.ContainsKey(symbol) && _trades[symbol].OpenTicket.AverageFillPrice != 0)
                {
                    _trades[symbol].CurrentPrice = data[symbol].Close;
                    
                    if (_trades[symbol].ProfitLossRatio >= TargetProfitLossRatio)
                    {
                        //Exit the trade if we hit our profit to loss target
                        Exit(_trades[symbol]);
                    }
                }
            }     
        }

        /// <summary>
        /// Enter the market, for a given direction, and symbol: add a stop loss to the trade we make.
        /// </summary>
        public TradeProfile Enter(string symbol, OrderDirection orderDirection)
        {
            var price = _data[symbol].Close;
            var trade = new TradeProfile(Securities[symbol].VolatilityModel.Volatility, RiskPerTrade, price, MaximumTradeSize);
            trade.TradeDirection = (orderDirection == OrderDirection.Buy) ? 1 : -1;

            trade.OpenTicket = MarketOrder(symbol, trade.TradeDirection * trade.Quantity);

            // Attach a stop loss at the average fill price - stopPrice.
            var stopPrice = trade.OpenTicket.AverageFillPrice - (trade.TradeDirection * trade.DeltaStopLoss);
            trade.StopTicket = StopMarketOrder(symbol, -trade.TradeDirection * trade.Quantity, stopPrice);

            return trade;
        }

        /// <summary>
        /// Exit the market for a given trade profile
        /// </summary>
        public void Exit(TradeProfile trade)
        {
            Liquidate(trade.OpenTicket.Symbol);
            if (trade.StopTicket != null && trade.StopTicket.Status != OrderStatus.Filled)
            {
                //If we haven't hit the stop loss then kill it.
                trade.StopTicket.Cancel();
            }
        }
    }
}
using System;
using MathNet.Numerics.Statistics;
using QuantConnect.Data;
using QuantConnect.Indicators;

namespace QuantConnect {

	
	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;
            }
        }
	}
	
}