Overall Statistics
Total Orders
135
Average Win
3.79%
Average Loss
-5.47%
Compounding Annual Return
7.730%
Drawdown
50.500%
Expectancy
0.016
Start Equity
100000
End Equity
145096.86
Net Profit
45.097%
Sharpe Ratio
0.213
Sortino Ratio
0.289
Probabilistic Sharpe Ratio
3.285%
Loss Rate
40%
Win Rate
60%
Profit-Loss Ratio
0.69
Alpha
-0.012
Beta
1.13
Annual Standard Deviation
0.305
Annual Variance
0.093
Information Ratio
-0.013
Tracking Error
0.261
Treynor Ratio
0.058
Total Fees
$484.12
Estimated Strategy Capacity
$1900000.00
Lowest Capacity Asset
JSPR XS705BNI7QLH
Portfolio Turnover
0.58%
Drawdown Recovery
812
# region imports
from AlgorithmImports import *
# endregion


class SmallCapsLowPERatioUniverseSelectionModel(FundamentalUniverseSelectionModel):
    
    '''
    Description:
        This Universe model selects Small Cap stocks with low P/E Ratio (in the 1st percentile)
    Details:
        The important thing to understand here is the internal flow of the Universe module:
            1) Select stocks with price above $5.
            2) Further filter those stocks by fundamental data. In this case, we use Market Cap and P/E Ratio.
    '''

    def select(self, algorithm, fundamental):        
        # Securities must have:
        # - Fundamental data (to avoid ETFs)
        # - Price > $5
        # - $300M < Market cap < $2B (small caps only)
        filtered = [
            f for f in fundamental 
            if (f.has_fundamental_data and 
                f.price > 5 and
                3e8 < f.market_cap < 2e9 and
                f.valuation_ratios.pe_ratio > 0)
        ]
        # Select the stocks that have a PE Ratio in the 1st percentile.
        lowest_pe_ratio_percentile = np.percentile([f.valuation_ratios.pe_ratio for f in filtered], 1)
        selected = list(filter(lambda f: f.valuation_ratios.pe_ratio <= lowest_pe_ratio_percentile, filtered))       
        return [f.symbol for f in selected]
# region imports
from AlgorithmImports import *
from SmallCapsLowPERatioUniverseSelection import SmallCapsLowPERatioUniverseSelectionModel
# endregion
### PRODUCT INFORMATION --------------------------------------------------------------------------------
# Copyright InnoQuantivity.com, granted to the public domain.
# Use entirely at your own risk.
# This algorithm contains open source code from other sources and no claim is being made to such code.
# Do not remove this copyright notice.
### ----------------------------------------------------------------------------------------------------


class LongOnlySmallCapsLowPERatioFrameworkAlgorithm(QCAlgorithmFramework):
    
    '''
    Trading Logic:
        This algorithm buys at the start of every year Small Caps with low P/E Ratio
    Universe: Dynamically selects stocks at the start of each year based on:
        - Price above $5
        - Small Caps (Market Cap between $300 million and $2 billion)
        - Then select stocks in the 1st percentile of Price To Earnings Ratio (PE Ratio)
    Alpha: Constant creation of Up Insights every trading bar
    Portfolio: Equal Weighting (allocate equal amounts of portfolio % to each security)
    Execution: Immediate Execution with Market Orders
    Risk: Null
    '''

    def initialize(self):
        self.set_start_date(self.end_date - timedelta(5*365))
        self.set_cash(100_000)
        # Define the universe settings.
        self.universe_settings.resolution = Resolution.DAILY
        self.universe_settings.fill_forward = False
        self.universe_settings.schedule.on(self.date_rules.year_start('SPY'))
        # Add the framework modules.
        self.set_universe_selection(SmallCapsLowPERatioUniverseSelectionModel())
        self.add_alpha(ConstantAlphaModel(InsightType.PRICE, InsightDirection.UP, timedelta(1)))
        self.settings.rebalance_portfolio_on_insight_changes = False  # Emit new insights when the universe changes
        self.set_portfolio_construction(EqualWeightingPortfolioConstructionModel(lambda time: None))
        self.set_execution(ImmediateExecutionModel())
        self.set_risk_management(NullRiskManagementModel())