Overall Statistics
Total Orders
343
Average Win
0.34%
Average Loss
-0.06%
Compounding Annual Return
16.912%
Drawdown
19.600%
Expectancy
4.111
Start Equity
10000000
End Equity
21848313.64
Net Profit
118.483%
Sharpe Ratio
0.693
Sortino Ratio
0.837
Probabilistic Sharpe Ratio
41.757%
Loss Rate
19%
Win Rate
81%
Profit-Loss Ratio
5.32
Alpha
0.037
Beta
0.698
Annual Standard Deviation
0.127
Annual Variance
0.016
Information Ratio
0.169
Tracking Error
0.09
Treynor Ratio
0.126
Total Fees
$4103.86
Estimated Strategy Capacity
$15000000.00
Lowest Capacity Asset
NMR SAOX277NPSO5
Portfolio Turnover
0.14%
Drawdown Recovery
483
#region imports
from AlgorithmImports import *
#endregion
# https://quantpedia.com/Screener/Details/26


class BooktoMarketAnomaly(QCAlgorithm):

    def initialize(self):
        self.set_start_date(self.end_date - timedelta(5*365))
        self.settings.seed_initial_prices = True
        self.set_cash(10_000_000)
        # Add a universe of US Equities.
        date_rule = self.date_rules.year_start("SPY")
        self.universe_settings.schedule.on(date_rule)
        self.universe_settings.resolution = Resolution.DAILY
        self._universe = self.add_universe(self._select_assets)
        # Add a Scheduled Event to rebalance the portfolio.
        self.schedule.on(date_rule, self.time_rules.midnight, self._rebalance)
        # Add a warm-up period so the algorithm doesn't wait until year start
        # to trade.
        self.set_warm_up(timedelta(365))
        
    def _select_assets(self, fundamentals):
        # Filter stocks with positive market cap and PB Ratio
        fundamentals = [f for f in fundamentals if f.market_cap and f.valuation_ratios.pb_ratio > 0]
        # Select the largest 20% of companies.
        top_market_cap = sorted(fundamentals, key=lambda f: f.market_cap, reverse=True)[:int(len(fundamentals)*0.2)]
        # Select the 20% of companies with the largest book-to-market ratios.
        top_bm = sorted(top_market_cap, key=lambda f: 1 / f.valuation_ratios.pb_ratio, reverse=True)[:int(len(top_market_cap)*0.2)]
        return [f.symbol for f in top_bm]
    
    def on_warmup_finished(self):
        self._rebalance()

    def _rebalance(self):
        # Get all the securities in the universe.
        equities = []
        for symbol in self._universe.selected:
            equity = self.securities[symbol] 
            if equity.price:
                equities.append(equity)
        # Form a market-cap weighed portfolio.
        total_market_cap = sum([equity.fundamentals.market_cap for equity in equities])
        targets = [PortfolioTarget(equity, equity.fundamentals.market_cap/total_market_cap) for equity in equities]
        self.set_holdings(targets, True)