Overall Statistics
Total Trades
0
Average Win
0%
Average Loss
0%
Compounding Annual Return
0%
Drawdown
0%
Expectancy
0
Net Profit
0%
Sharpe Ratio
0
Probabilistic Sharpe Ratio
0%
Loss Rate
0%
Win Rate
0%
Profit-Loss Ratio
0
Alpha
0
Beta
0
Annual Standard Deviation
0
Annual Variance
0
Information Ratio
-2.335
Tracking Error
0.094
Treynor Ratio
0
Total Fees
$0.00
Estimated Strategy Capacity
$0
Lowest Capacity Asset
from AlgorithmImports import *
from datetime import *


class EquitiesFundamentalSelectionModel(FineFundamentalUniverseSelectionModel):

    def __init__(self, universe_settings: UniverseSettings = None) -> None:
        self.month = 0
        self.num_coarse = 500
        super().__init__(self.SelectCoarse, self.SelectFine, universe_settings)

    '''
    Required method for all fundamental selection model
    The coarse fundamental selection relies on the CoarseFundamental data
    '''

    def SelectCoarse(self, coarse: List[CoarseFundamental]) -> List[Symbol]:
        if not self.IsRebalanceDue(QCAlgorithm().Time):
            return Universe.Unchanged

        selected = sorted([x for x in cast(Iterable[CoarseFundamental], coarse)
                          if x.HasFundamentalData and x.Price > 5], key=lambda x: x.DollarVolume, reverse=True)

        return [x.Symbol for x in selected[:self.num_coarse]]

    '''
    Optional method for a fundamental selection model
    The fine fundamental selection relies on the FineFundamental data
    '''

    def SelectFine(self, fine: List[FineFundamental]) -> List[Symbol]:

        sectors = [MorningstarSectorCode.FinancialServices, MorningstarSectorCode.RealEstate,
                   MorningstarSectorCode.Healthcare, MorningstarSectorCode.Utilities, MorningstarSectorCode.Technology]

        filtered_fine = [x.Symbol for x in cast(Iterable[FineFundamental], fine)
                         if x.SecurityReference.IPODate + timedelta(5*365) < datetime and
                         x.AssetClassification.MorningstarEconomySphereCode in sectors and
                         x.OperationRatios.ROE.Value > 0 and
                         x.OperationRatios.NetMargin.Value > 0 and
                         x.ValuationRatios.PERatio > 0]

        return filtered_fine

    '''
    Ensure that this model selection only runs once each quarter
    '''

    def IsRebalanceDue(self, time):
        if time.month == self.month or time.month not in [1, 4, 7, 10]:
            return None
        
        self.month = time.month
        return date
from AlgorithmImports import *
from datetime import *


class FundamentalFactorAlphaModel(AlphaModel):

    def __init__(self) -> None:
        self.rebalanceTime = datetime.min
        self.sectors = {}

    def Update(self, algorithm: QCAlgorithm, data: Slice) -> Iterable[Insight]:
        if algorithm.Time < self.rebalanceTime:
            return[]
        self.rebalanceTime = Expiry.EndOfQuarter(algorithm.Time)

        insights = []

        for sector in self.sectors:
            securities = self.sectors[sector]
            sortedByROE = sorted(cast(
                Iterable[Security], securities), key=lambda x: x.Fundamentals.OperationRatios.ROE.Value, reverse=True)
            sortedByPM = sorted(cast(
                Iterable[Security], securities), key=lambda x: x.Fundamentals.OperationRatios.NetMargin.Value, reverse=True)
            sortedByPE = sorted(cast(
                Iterable[Security], securities), key=lambda x: x.Fundamentals.ValuationRatios.PERatio, reverse=True)

        scores = {}

        for security in cast(Iterable[Security], securities):
            score = sum([sortedByROE.index(security), sortedByPM.index(
                security), sortedByPE.index(security)])
            scores[security] = score

        length = max(int(len(scores)/5), 1)
        for security in sorted(scores.items(), key=lambda x: x[1], reverse=False)[:length]:
            symbol = security[0].Symbol
            insights.append(Insight.Price(
                symbol, Expiry.EndOfQuarter, InsightDirection.Up))

        return insights

    def OnSecuritiesChanged(self, algorithm: QCAlgorithm, changes: SecurityChanges) -> None:

        for security in changes.RemovedSecurities:
            for sector in self.sectors:
                if security in cast(Iterable[Security], self.sectors[sector]):
                    self.sectors[sector].remove(security)

        for security in changes.AddedSecurities:
            sector = security.Fundamentals.AssetClassification.MorningstarSectorCode
            if sector not in self.sectors:
                self.sectors[sector] = set()
            self.sectors[sector].add(security)
from AlgorithmImports import *
from EquitiesFundamentalSelectionModel import *
from FundamentalFactorAlphaModel import *


class EquitiesTemplate(QCAlgorithm):
    def Initialize(self):
        self.SetStartDate(2013, 1, 1)  # Set Start Date
        self.SetEndDate(2014, 1, 1)  # Set End Date
        self.SetCash(100000)  # Set Strategy Cash
        self.UniverseSettings.Resolution = Resolution.Daily
        self.AddUniverseSelection(EquitiesFundamentalSelectionModel())
        self.AddAlpha(FundamentalFactorAlphaModel())
        self.SetPortfolioConstruction(EqualWeightingPortfolioConstructionModel(
            EquitiesFundamentalSelectionModel.IsRebalanceDue))
        self.SetRiskManagement(NullRiskManagementModel)
        self.SetExecution(ImmediateExecutionModel())