Behavioral theories suggest that investor misperceptions and market mispricing will be correlated across firms. We use equity and debt financing to identify common misvaluation across firms. A zero-investment portfolio (UMO, Undervalued Minus Overvalued) built from repurchase and new issue firms captures comovement in returns beyond that in some standard multifactor models, and substantially improves the Sharpe ratio of the tangency portfolio. Loadings on UMO incrementally predict the cross-section of returns on both portfolios and individual stocks, even among firms not recently involved in external financing activities. Further evidence suggests that UMO loadings proxy for the common component of a stock's misvaluation.
Keywords: Misvaluation, financing, new issues, repurchase, factor models, market efficiency, behavioral finance
- Eligible Stocks: Stocks from NYSE, AMEX, and NASDAQ.
- Overvalued group: Companies that have had IPOs, SEOs, or issued debt (both straight and convertible) in the last two years.
- Undervalued group: Companies that have reduced equity or debt by more than 1% of their average total assets during any of the previous two fiscal years.
- Exemptions: Exclude companies that fall into both the high-valuation and low-valuation categories.
- Strategy: Adopt a long position for the undervalued group and a short position for the overvalued group.
- Portfolio adjustment: Once a year at the close of June, ensuring uniform distribution for each stock.
import backtrader as bt import pandas as pd class RepurchaseNewIssueEffect(bt.Strategy): def __init__(self): self.date_month = None def next(self): current_date = self.data.datetime.date() if self.date_month != current_date.month and current_date.month == 6: self.date_month = current_date.month overvalued_stocks =  undervalued_stocks =  for stock_data in self.datas: stock = stock_data._name # Implement logic to filter stocks based on IPOs, SEOs, and debt offerings # within the past 24 months as well as equity/debt reduction criteria. # This information is not directly available in price data and needs # to be obtained from a different source (e.g., financial statements). if stock_meets_overvalued_criteria(stock): overvalued_stocks.append(stock_data) elif stock_meets_undervalued_criteria(stock): undervalued_stocks.append(stock_data) # Equal weight for stocks in the overvalued and undervalued portfolios overvalued_weight = -1 / len(overvalued_stocks) undervalued_weight = 1 / len(undervalued_stocks) # Open positions for stock_data in overvalued_stocks: self.order_target_percent(stock_data, target=overvalued_weight) for stock_data in undervalued_stocks: self.order_target_percent(stock_data, target=undervalued_weight) # Implement helper functions for filtering stocks based on IPOs, SEOs, debt offerings # and equity/debt reduction criteria. You will need additional data sources for this. def stock_meets_overvalued_criteria(stock): pass # Implement the logic here def stock_meets_undervalued_criteria(stock): pass # Implement the logic here# Initialize the Backtrader engine cerebro = bt.Cerebro() # Add data feeds for each stock in the investment universe (NYSE, AMEX, NASDAQ) # You will need to obtain the stock data from a source and add it to the cerebro object # Example: cerebro.adddata(stock_data) # Add the strategy to the cerebro object cerebro.addstrategy(RepurchaseNewIssueEffect) # Run the backtest results = cerebro.run()
Please note that the provided code is a starting point and requires additional data sources and modifications to handle IPOs, SEOs, debt offerings, and equity/debt reduction criteria. The logic for filtering stocks based on these criteria should be implemented in the