Overall Statistics
Total Orders
6455
Average Win
0.03%
Average Loss
-0.06%
Compounding Annual Return
-7.815%
Drawdown
62.100%
Expectancy
-0.299
Start Equity
10000000
End Equity
6656434.31
Net Profit
-33.436%
Sharpe Ratio
-0.409
Sortino Ratio
-0.53
Probabilistic Sharpe Ratio
0.056%
Loss Rate
53%
Win Rate
47%
Profit-Loss Ratio
0.50
Alpha
-0.153
Beta
1.035
Annual Standard Deviation
0.185
Annual Variance
0.034
Information Ratio
-1.324
Tracking Error
0.114
Treynor Ratio
-0.073
Total Fees
$12074.07
Estimated Strategy Capacity
$0
Lowest Capacity Asset
GIFI R735QTJ8XC9X
Portfolio Turnover
0.27%
Drawdown Recovery
5
# region imports
from AlgorithmImports import *
# endregion
class NetCurrentAssetValue(QCAlgorithm):

    def Initialize(self):
        self.set_start_date(self.end_date - timedelta(5*365))
        self.set_cash(10_000_000)
        self.settings.seed_initial_prices = True
        self.settings.minimum_order_margin_portfolio_percentage = 0
        date_rule = self.date_rules.month_start("SPY")
        self._rebalance_month = 7  # July
        self.universe_settings.schedule.on(date_rule)
        self.universe_settings.resolution = Resolution.DAILY
        self._universe = self.add_universe(self._select_assets)
        self.schedule.on(date_rule, self.time_rules.at(8, 0), self._rebalance)
        self.set_warm_up(timedelta(400))

    def _select_assets(self, fundamentals):
        if self.time.month != self._rebalance_month:
            return Universe.UNCHANGED
        # Calculate the net current asset value per share for each company.
        ncav_by_symbol = {}
        for f in fundamentals:
            # Drop stocks which have no fundamental data or have low price.
            if (f.has_fundamental_data and 
                f.adjusted_price > 5 and
                # Filter out the companies in the financial sector, as suggested.
                f.company_reference.industry_template_code not in ['B', 'I'] and
                # Filter out companies that don't have enough data to calculate NCAV/MV.
                f.financial_statements.balance_sheet.current_assets.value > 0 and
                f.financial_statements.balance_sheet.current_liabilities.value > 0 and
                f.financial_statements.balance_sheet.total_non_current_liabilities_net_minority_interest.value > 0 and
                f.earning_reports.basic_average_shares.value > 0):
                total_liabilities = (
                    f.financial_statements.balance_sheet.current_liabilities.value
                    + f.financial_statements.balance_sheet.total_non_current_liabilities_net_minority_interest.value
                )
                ncav_by_symbol[f.symbol] = (
                    (f.financial_statements.balance_sheet.current_assets.value - total_liabilities)
                    / f.earning_reports.basic_average_shares.value
                )
        # Select stocks that have a NCAV/MV higher than 1.5.
        selected = [symbol for symbol, ncav in ncav_by_symbol.items() if ncav > 1.5]
        return selected

    def _rebalance(self, skip_guard=False):
        if (self.time.month != self._rebalance_month or self.is_warming_up) and not skip_guard:
            return []
        weight = 1 / len(self._universe.selected)
        targets = [PortfolioTarget(symbol, weight) for symbol in self._universe.selected]
        self.set_holdings(targets, True)
    
    def on_warmup_finished(self):
        self._rebalance(True)