Quality Factor Long-Short Portfolio by Market Cap
Log in to collectOnsite backtest IDE
Quant Buffet native backtest IDEEdit and run Quant Buffet Python for Quality Factor Long-Short Portfolio by Market Cap in the browser. Results update live with equity, drawdown, and metrics charts. Allowed: backtest.data, backtest.engine, backtest.metrics, numpy, pandas. Define ASSETS and make_on_day(prices). Shortcut: Ctrl+Enter. API docs →
Quant Buffet syntax cheat sheet (copy / insert)
Paste these fragments into the editor. The sandbox rejects QuantConnect, os, and network libraries.
from __future__ import annotations
import numpy as np
import pandas as pd
from backtest.data import load_daily_prices
from backtest.engine import EngineConfig, PortfolioEngine
from backtest.metrics import compute_metricsASSETS = ["SPY", "QQQ", "TLT", "GLD", "BIL"]def make_on_day(prices: pd.DataFrame):
cols = [c for c in ASSETS if c in prices.columns]
sma = prices[cols].rolling(200, min_periods=200).mean()
state = {"last": None}
def on_day(engine: PortfolioEngine, dt: pd.Timestamp) -> None:
if sma.loc[dt].isna().all():
return
key = (dt.year, dt.month)
if state["last"] == key:
return
state["last"] = key
long = [
s for s in cols
if pd.notna(prices.at[dt, s]) and pd.notna(sma.at[dt, s])
and prices.at[dt, s] > sma.at[dt, s]
]
weights = {} if not long else {s: 1.0 / len(long) for s in long}
engine.set_target_weights(dt, weights)
ready = sma.dropna(how="all").index.min() if sma.notna().any().any() else None
return on_day, readyengine.set_target_weights(dt, {"SPY": 0.60, "BIL": 0.40})Live backtest performance
Export to your platform
Transform Quant Buffet lab code (ASSETS + make_on_day / PortfolioEngine) into native classes for a third-party IDE — then copy and paste.
# Generated from Quant Buffet → QuantConnect LEAN
# Strategy: Quality Factor Long-Short Portfolio by Market Cap
# Detected pattern: SMA trend
# Source uses Quant Buffet lab APIs (ASSETS + make_on_day / PortfolioEngine).
# Review fees, data, and risk before live trading — educational export only.
from AlgorithmImports import *
class QuantBuffetExport(QCAlgorithm):
def Initialize(self):
self.SetStartDate(2010, 1, 1)
self.SetCash(100000)
tickers = ["SPY", "TLT", "GLD", "BIL"]
self.symbols = []
for t in tickers:
if "-" in t: # crypto proxy e.g. BTC-USD
self.symbols.append(self.AddCrypto(t.replace("-USD", ""), Resolution.Daily).Symbol)
else:
self.symbols.append(self.AddEquity(t, Resolution.Daily).Symbol)
self.Schedule.On(
self.DateRules.MonthStart(self.symbols[0]),
self.TimeRules.AfterMarketOpen(self.symbols[0], 30),
self.Rebalance,
)
# Logic: Long assets where close > SMA(200); equal-weight; monthly.
def Rebalance(self):
longs = []
for symbol in self.symbols:
hist = self.History(symbol, 200 + 5, Resolution.Daily)
if hist.empty: continue
close = hist["close"].unstack(level=0).iloc[:, 0] if hasattr(hist["close"], "unstack") else hist["close"]
if len(close) < 200: continue
if float(close.iloc[-1]) > float(close.iloc[-200:].mean()):
longs.append(symbol)
weight = 1.0 / len(longs) if longs else 0.0
for symbol in self.symbols:
self.SetHoldings(symbol, weight if symbol in longs else 0.0)
Exported code uses the platform’s native classes and libraries. Install dependencies in your third-party IDE, then run. Validate before live trading.
Academic paper
Nadja Guenster; Erik Kole; Ben Jacobsen
- University of California, Berkeley
- ?University of Muenster - Finance Center Muenster
- NLTinbergen Institute
- NLErasmus University Rotterdam
- Environmental Research Institute of Michigan
- ?ERIM
- ?Erasmus University Rotterdam - Erasmus School of Economics - Econometric Institute
- NLTilburg University
- NZMassey University
- NLTIAS School for Business and Society
- ?Tilburg University - TIAS School for Business and Society
https://papers.ssrn.com/sol3/papers.cfm?abstract_id=1071670

Strategy in a nutshell
The investment universe consists of all non-financial stocks from NYSE, Amex and Nasdaq.
Big stocks are defined as the largest stocks that make up 90% of the total market cap within the region, while small stocks make up the remaining 10% of the market cap. Investor defines breakpoints by the 30th and 70th percentiles of the multiple “Earnings Quality” ratios between large caps and small caps.
The first “Earnings Quality” ratio is defined by cash flow relative to reported earnings. The high-quality earnings firms are characterized by high cash flows (relative to reported earnings) while the low-quality firms are characterized by high reported earnings (relative to cash flow).
The second factor is based on return on equity (ROE) to exploit the well-documented “profitability anomaly” by going long high-ROE firms (top 30%) and short low-ROE firms (bottom 30%).
The third ratio – CF/A (cash flow to assets) factor goes long firms with high cash flow to total assets.
The fourth ratio – D/A (debt to assets) factor goes long firms with low leverage and short firms with high leverage.
The investor builds a scored composite quality metric by computing the percentile score of each stock on each of the four quality metrics (where “good” quality has a high score, so ideally a stock has low accruals, low leverage, high ROE, and high cash flow) and then add up the percentiles to get a score for each stock from 0 to 400. He then forms the composite factor by going long the top 30% of small-cap stocks and also large-cap stocks and short the bottom 30% of the small-cap stocks and also large-cap stocks and cap-weighting individual stocks within the portfolios.
The final factor portfolio is formed at the end of each June and is rebalanced yearly.
Economic rationale
The effect is explained mainly by investors’ behavioural defects. The majority of investors usually overly fixate on actual earnings, and they do not investigate the quality of earnings scrutinizingly. The in-depth analysis, therefore, allows exploiting this inefficiency.