Overall Statistics
Total Trades
422
Average Win
0.16%
Average Loss
-0.16%
Compounding Annual Return
-6.053%
Drawdown
9.700%
Expectancy
-0.048
Net Profit
-4.096%
Sharpe Ratio
-0.009
Probabilistic Sharpe Ratio
20.711%
Loss Rate
52%
Win Rate
48%
Profit-Loss Ratio
0.98
Alpha
0.049
Beta
-0.363
Annual Standard Deviation
0.154
Annual Variance
0.024
Information Ratio
-0.791
Tracking Error
0.179
Treynor Ratio
0.004
Total Fees
$691.56
from Alphas.EmaCrossAlphaModel import EmaCrossAlphaModel
from Execution.ImmediateExecutionModel import ImmediateExecutionModel
from Portfolio.EqualWeightingPortfolioConstructionModel import EqualWeightingPortfolioConstructionModel
from Risk.MaximumDrawdownPercentPerSecurity import MaximumDrawdownPercentPerSecurity
import numpy as np
    
class TrailingStopPerSecurity(RiskManagementModel):
    '''Provides an implementation of IRiskManagementModel that limits the drawdown per holding to the specified percentage'''

    def __init__(self, maximumDrawdownPercent = 0.05):
        '''Initializes a new instance of the MaximumDrawdownPercentPerSecurity class
        Args:
            maximumDrawdownPercent: The maximum percentage drawdown allowed for any single security holding'''
        self.maximumDrawdownPercent = -abs(maximumDrawdownPercent)
        self.asset_best_pnl = {}
        
    def ManageRisk(self, algorithm, targets):
        '''Manages the algorithm's risk at each time step
        Args:
            algorithm: The algorithm instance
            targets: The current portfolio targets to be assessed for risk'''
        # Clear History of items in self.asset_best_pnl by setting valid symbol for symbol with holding !=0
        syms_quantities = {kvp.Value.Symbol.Value:kvp.Value.Holdings.Quantity for  kvp in algorithm.Securities}
        valid_syms = [key for key,val in syms_quantities.items() if val!=0]
        new_assets = {key:val for key,val in self.asset_best_pnl.items() if key in valid_syms}
        self.asset_best_pnl = new_assets

        targets = []
         
        for kvp in algorithm.Securities:
            security = kvp.Value
            symbol = security.Symbol.Value
            if symbol not in self.asset_best_pnl.keys():
               self.asset_best_pnl[symbol] = security.Holdings.UnrealizedProfitPercent
            self.asset_best_pnl[symbol] = np.maximum(self.asset_best_pnl[symbol], security.Holdings.UnrealizedProfitPercent)
            if not security.Invested:
                continue

            pnl = security.Holdings.UnrealizedProfitPercent -  self.asset_best_pnl[symbol]
            if pnl < self.maximumDrawdownPercent:
                # liquidate
                targets.append(PortfolioTarget(symbol, 0))

        return targets
class ParticleModulatedAntennaArray(QCAlgorithm):

    def Initialize(self):
        self.SetStartDate(2016, 12, 13)  # Set Start Date
        self.SetCash(100000)  # Set Strategy Cash
        # self.AddEquity("SPY", Resolution.Minute)
        self.AddAlpha(EmaCrossAlphaModel(50, 200, Resolution.Hour))

        self.SetExecution(ImmediateExecutionModel())

        self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel())

        self.SetRiskManagement(TrailingStopPerSecurity(0.1))

        self.SetUniverseSelection(TechnologyETFUniverse())


    def OnData(self, data):
        '''OnData event is the primary entry point for your algorithm. Each new data point will be pumped in here.
            Arguments:
                data: Slice object keyed by symbol containing the stock data
        '''

        # if not self.Portfolio.Invested:
        #    self.SetHoldings("SPY", 1)