Overall Statistics
Total Trades
2110
Average Win
0.03%
Average Loss
-0.01%
Compounding Annual Return
-0.822%
Drawdown
4.600%
Expectancy
-0.003
Net Profit
-0.841%
Sharpe Ratio
-0.291
Loss Rate
70%
Win Rate
30%
Profit-Loss Ratio
2.35
Alpha
-0.033
Beta
1.245
Annual Standard Deviation
0.027
Annual Variance
0.001
Information Ratio
-1.029
Tracking Error
0.027
Treynor Ratio
-0.006
Total Fees
$2121.92
from System import *
from QuantConnect import *
from QuantConnect.Orders import *
from QuantConnect.Algorithm import *
from QuantConnect.Algorithm.Framework import *
from QuantConnect.Algorithm.Framework.Execution import *
from QuantConnect.Algorithm.Framework.Risk import *
from QuantConnect.Algorithm.Framework.Selection import *
import numpy as np
import pandas as pd
from scipy.optimize import minimize

class MeanVarianceOptimizationAlgorithm(QCAlgorithmFramework):
    '''Mean Variance Optimization Algorithm.'''

    def Initialize(self):
        ''' Initialise the data and resolution required, as well as the cash and start-end dates for your algorithm. All algorithms must initialized.'''

        # Set requested data resolution
        self.UniverseSettings.Resolution = Resolution.Minute

        self.SetStartDate(2017, 4, 1)   #Set Start Date
        self.SetEndDate(2018, 4, 9)     #Set End Date
        self.SetCash(100000)            #Set Strategy Cash

        tickers = ['IWD', 'MTUM', 'IWN', 'IWM', 'EFA', 'EEM', 'IEF', 'SPY', 'LQD', 'TLT', 'DBC', 'GLD', 'VNQ']
        
        symbols = [ Symbol.Create(ticker, SecurityType.Equity, Market.USA) for ticker in tickers ]

        self.minimum_weight = -1
        self.maximum_weight = 1

        # set algorithm framework models
        self.SetUniverseSelection( ManualUniverseSelectionModel(symbols) )
        
        self.SetAlpha( HistoricalReturnsAlphaModel(resolution = Resolution.Daily) )
        
        self.SetPortfolioConstruction( MeanVarianceOptimizationPortfolioConstructionModel() )
        
        self.SetExecution( ImmediateExecutionModel() )
        
        self.SetRiskManagement( NullRiskManagementModel() )


    #def OnOrderEvent(self, orderEvent):
    #    if orderEvent.Status == OrderStatus.Filled:
    #        self.Debug(orderEvent.ToString())

    def maximum_sharpe_ratio(self, returns):
        '''Maximum Sharpe Ratio optimization method'''

        # Objective function
        fun = lambda weights: -self.sharpe_ratio(returns, weights)
        
        # Constraint #1: The weights can be negative, which means investors can short a security.
        constraints = [{'type': 'eq', 'fun': lambda w: np.sum(w) - 1}]

        size = returns.columns.size
        x0 = np.array(size * [1. / size])
        bounds = tuple((self.minimum_weight, self.maximum_weight) for x in range(size))
        
        opt = minimize(fun,                         # Objective function
                       x0,                          # Initial guess
                       method='SLSQP',              # Optimization method:  Sequential Least SQuares Programming
                       bounds = bounds,             # Bounds for variables 
                       constraints = constraints)   # Constraints definition

        weights = pd.Series(opt['x'], index = returns.columns)

        return opt, weights

    def sharpe_ratio(self, returns, weights):
        annual_return = np.dot(np.matrix(returns.mean()), np.matrix(weights).T).item()
        annual_volatility = np.sqrt(np.dot(weights.T, np.dot(returns.cov(), weights)))
        return annual_return/annual_volatility