| 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)