Overall Statistics
Total Trades
3230
Average Win
0.13%
Average Loss
-0.14%
Compounding Annual Return
-15.295%
Drawdown
24.200%
Expectancy
-0.122
Net Profit
-23.637%
Sharpe Ratio
-2.197
Loss Rate
55%
Win Rate
45%
Profit-Loss Ratio
0.97
Alpha
-0.134
Beta
0.008
Annual Standard Deviation
0.061
Annual Variance
0.004
Information Ratio
-1.242
Tracking Error
0.153
Treynor Ratio
-16.006
Total Fees
$3230.10
/*
 * 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.Algorithm.Framework.Portfolio;

namespace QuantConnect.Algorithm.Framework.Risk
{
    /// <summary>
    /// Provides an implementation of <see cref="IRiskManagementModel"/> that limits the drawdown
    /// per holding to the specified percentage
    /// </summary>
    public class MaximumDrawdownPercentPerSecurity : RiskManagementModel
    {
        private readonly decimal _maximumDrawdownPercent;

        /// <summary>
        /// Initializes a new instance of the <see cref="MaximumDrawdownPercentPerSecurity"/> class
        /// </summary>
        /// <param name="maximumDrawdownPercent">The maximum percentage drawdown allowed for any single security holding,
        /// defaults to 5% drawdown per security</param>
        public MaximumDrawdownPercentPerSecurity(
            decimal maximumDrawdownPercent = 0.05m
            )
        {
            _maximumDrawdownPercent = -Math.Abs(maximumDrawdownPercent);
        }

        /// <summary>
        /// Manages the algorithm's risk at each time step
        /// </summary>
        /// <param name="algorithm">The algorithm instance</param>
        /// <param name="targets">The current portfolio targets to be assessed for risk</param>
        public override IEnumerable<IPortfolioTarget> ManageRisk(QCAlgorithm algorithm, IPortfolioTarget[] targets)
        {
            foreach (var kvp in algorithm.Securities)
            {
                var security = kvp.Value;

                if (!security.Invested)
                {
                    continue;
                }

                var pnl = security.Holdings.UnrealizedProfitPercent;
                if (pnl < _maximumDrawdownPercent)
                {
                    // liquidate
                    yield return new PortfolioTarget(security.Symbol, 0);
                }
            }
        }
    }
}
namespace QuantConnect
{
    public partial class BootCampTask : QCAlgorithm
    {
        private Dictionary<string, TradeBar> MyStocks = new Dictionary<string, TradeBar>();
        private string[] _stocks = new string[] { "TSLA", "AMD", "BAC", "SYMC", "HP" };
        
        public override void Initialize()
        {
            SetStartDate(2018, 1, 1);
            SetEndDate(2019, 8, 16);
            SetCash(10000);
            AddEquity("SPY", Resolution.Minute);
            AddRiskManagement(new MaximumDrawdownPercentPerSecurity());
            
            for(int i = 0; i < _stocks.Length; i++)
            {
                AddEquity(_stocks[i], Resolution.Minute);
                MyStocks.Add(_stocks[i], null);
                Consolidate(_stocks[i], TimeSpan.FromMinutes(30), OnDataConsolidation);
                Log(_stocks[i] + " Added to Algorithm");
            }
            
            Schedule.On(DateRules.EveryDay(), TimeRules.At(11,30), CloseAllPositions);
        }
        
        private void OnDataConsolidation(TradeBar bar)
        {
            if(bar.Time.Hour == 9 && bar.Time.Minute == 30)
            {
                MyStocks[bar.Symbol.Value] = bar;
            }
        }
        
        private void CloseAllPositions()
        {
        	for(int i = 0; i < _stocks.Length; i++)
        	{
        		Liquidate(_stocks[i]);
        		MyStocks[_stocks[i]] = null;
        	}
        }
        
        private void ClosePosition(string symbol)
        {
        	Liquidate(symbol);
        	MyStocks[symbol] = null;
        }
        
        public override void OnData(Slice data)
        {
        	for(int i = 0; i < _stocks.Length; i++)
        	{
        		if(!Portfolio[_stocks[i]].Invested && MyStocks[_stocks[i]] != null)
        		{
        			Log("Not invested in " + _stocks[i] + " and Consolidator set");
        			
        			if(data[_stocks[i]].Close > MyStocks[_stocks[i]].High)
        			{
        				SetHoldings(_stocks[i], 1.0m/_stocks.Length);
        				Log("Long: " + _stocks[i]);
        			}
        			
        			if(data[_stocks[i]].Close < MyStocks[_stocks[i]].Low)
        			{
	        			SetHoldings(_stocks[i], -1.0m/_stocks.Length);
	        			Log("Short: " + _stocks[i]);
        			}
        		}
        	}
        }
    }
}