Skip to content

finlab.analysis

The strategy analysis module provides in-depth analysis tools to evaluate strategy quality from multiple angles: liquidity risk, volatility characteristics, period stability, and more.

Use Cases

  • Liquidity risk detection (Taiwan market): Large-capital strategies must check for insufficient volume, limit-up/limit-down issues, etc.
  • Optimize stop-loss/take-profit: Use MAE/MFE analysis to find optimal stop-loss and take-profit levels
  • Evaluate long-term stability: Analyze whether strategy performance is consistent across different years and months
  • Assess excess returns: Use Alpha/Beta analysis to measure whether the strategy outperforms the benchmark
  • Custom analysis logic: Inherit the Analysis class to develop proprietary analysis modules

Quick Examples

from finlab import data
from finlab.backtest import sim

# Complete backtest
data.set_market('us')
with data.us_universe(index='SP500'):
    close = data.get('price:adj_close')
position = close > close.average(20)
report = sim(position, resample='M')

# 1. Volatility analysis (MAE/MFE)
report.display_mae_mfe_analysis()

# 2. Period stability analysis
report.run_analysis('PeriodStatsAnalysis')

# 3. Alpha/Beta analysis
report.run_analysis('AlphaBetaAnalysis')

Built-in Analysis Module Comparison

Module Purpose Key Output
LiquidityAnalysis Liquidity risk detection (Taiwan market only) Limit-up/down, low volume, disposal stock ratios
MaeMfeAnalysis Volatility analysis 12 sub-charts (MAE/MFE/win rate/Edge Ratio)
PeriodStatsAnalysis Period stability Annual, monthly, and recent performance
InequalityAnalysis Factor threshold analysis Mean trade return above vs. below each factor value
AlphaBetaAnalysis Alpha/Beta Excess return, market sensitivity
DrawdownAnalysis Drawdown analysis Drawdown events, durations

Detailed Guide

See Strategy Analysis Module Guide for:

  • Detailed functionality and parameter descriptions for each module
  • How to interpret output and make decisions
  • How to inherit the Analysis class to develop custom analysis modules
  • Analysis priorities for different strategy types
  • Decision trees based on analysis results

API Reference

LiquidityAnalysis - Liquidity Risk Detection

Taiwan market only

is_market_supported() returns True only for the Taiwan stock market, whose price limits and alert, disposal and full-delivery stock rules this analysis checks.

class LiquidityAnalysis(required_volume=200000, required_turnover=1000000)

Measures how often a strategy's trades hit liquidity problems on the entry and exit dates.

Parameter Type Description
required_volume int Minimum shares traded on the entry/exit day. Default 200000.
required_turnover int Minimum traded value on the entry/exit day, so that cheap stocks with enough shares but little value traded are still flagged. Default 1000000.
# Shorthand
report.run_analysis('LiquidityAnalysis', required_volume=100000)

# Equivalent
from finlab.analysis.liquidityAnalysis import LiquidityAnalysis

report.run_analysis(LiquidityAnalysis(required_volume=100000))

The result is a table with an entry and an exit row. Columns give the share of trades that:

  • buy_high: bought within 5% of the daily price limit (long entries, short exits)
  • sell_low: sold within 5% of the daily price limit (long exits, short entries)
  • low_volume_stocks: traded fewer shares than required_volume
  • low_turnover_stocks: traded less value than required_turnover
  • plus the share of alert, disposal and full-delivery stocks on the signal dates

Risk Threshold Guidelines

  • buy_high or sell_low > 10%: Orders may not execute successfully
  • low_volume_stocks > 20%: Large capital may not be fully deployed
  • Disposal stocks > 5%: Strategy may be selecting high-risk targets

InequalityAnalysis - Inequality Factor Analysis

class InequalityAnalysis(name, df=None, date_type='entry_sig_date', target='return')

Analyzes how trade returns change when a condition factor < x or factor > x is added, for every threshold x. Trades are sorted by the factor value on date_type. The upper charts show the mean target of the trades kept by each threshold minus the mean of all trades (titled <name> < x and <name> > x); the lower charts show the factor value at each cut, by number of trades. target outliers beyond 3 standard deviations are clipped, and the first 50 cuts, which keep too few trades, are not plotted.

Parameter Type Description
name str Name of the factor; used as the trade column name (<name>@<date_type>) and chart label.
df pd.DataFrame or None Factor values (dates by symbols). If None, data.get(name) is fetched automatically, so name must then be a dataset key.
date_type str Date on which the factor is read: 'entry_date', 'entry_sig_date', 'exit_date' or 'exit_sig_date'.
target str Trade column to evaluate; any column of report.get_trades().
from finlab import data
from finlab.analysis.inequalityAnalysis import InequalityAnalysis
from finlab.backtest import sim

data.set_market('us')
with data.us_universe(index='SP500'):
    close = data.get('price:adj_close')
    market_value = data.get('etl:us_market_value')

position = close > close.average(20)
report = sim(position, resample='M')
report.run_analysis(InequalityAnalysis(name='market_value', df=market_value))

Reading the chart

  • A curve that rises steadily as the threshold moves means the factor separates good trades from bad ones
  • A flat curve near zero means filtering on this factor does not change returns
  • Thresholds that keep only a handful of trades are noisy; check the trade count in the lower charts

PeriodStatsAnalysis - Period Stability Analysis

class PeriodStatsAnalysis()

Compares the strategy with its benchmark (the S&P 500 for U.S. stocks) over different periods.

report.run_analysis('PeriodStatsAnalysis')

The result has one column for the benchmark and one for the strategy, with these metrics: calmar_ratio, sortino_ratio, sharpe_ratio, profit_factor (total gains / total losses), tail_ratio, return (CAGR) and volatility. They are computed on daily, monthly and yearly returns (overall_daily, overall_monthly, overall_yearly), followed by tables per calendar year and for the most recent month, quarter, half year, year and three years (M, Q, HY, Y, 3Y).

Evaluation Criteria

  • Strategy sharpe_ratio < benchmark: Strategy needs improvement
  • Some years perform particularly poorly: Check for specific market conditions
  • Recent performance significantly declining: Strategy may be losing effectiveness

AlphaBetaAnalysis - Alpha/Beta Analysis

finlab.analysis.alphaBetaAnalysis.AlphaBetaAnalysis

AlphaBetaAnalysis()

Ideal Metrics

  • Alpha > 0: Strategy generates excess returns
  • Beta 0.5-1.5: Moderate market correlation
  • Beta < 0: Strategy is negatively correlated with the market (suitable for hedging)

DrawdownAnalysis - Drawdown Analysis

finlab.analysis.drawdownAnalysis.DrawdownAnalysis

DrawdownAnalysis()

display

display()

Display drawdown analysis result.

Risk Control

  • Max drawdown > -50%: Risk is too high
  • Drawdown duration > 1 year: Strategy may be failing long-term

MaeMfeAnalysis - Volatility Analysis

finlab.analysis.maeMfeAnalysis.MaeMfeAnalysis

MaeMfeAnalysis(
    violinmode='group', mfe_scatter_x='mae', **kwargs
)

Stop-Loss/Take-Profit Optimization

  1. Stop-loss level = MAE 75th percentile x 1.2
  2. Take-profit level = GMFE 75th percentile x 0.8
  3. Missed Win-profits PCT < 20%: Suitable for trailing stop

Custom Analysis Modules

To develop a custom analysis system, inherit finlab.analysis.Analysis to implement your analysis.

class Analysis(ABC)

report.run_analysis(analysis) calls calculate_trade_info(), adds the returned columns to the trades, then calls analyze() and, unless display=False, returns display().

Method Description
is_market_supported(market) -> bool Whether the analysis supports the backtest's market. Default True.
calculate_trade_info(report) -> list Optional. Return extra trade information as [name, df, date_type] lists: df is a DataFrame (dates by symbols) whose value on each trade's date_type ('entry_sig_date', 'entry_date', ...) becomes the trade column <name>@<date_type>. Default [].
analyze(report) Required. Analyze the report; report.get_trades() already contains the columns from calculate_trade_info().
display() Required. Display the result; returning a Plotly figure is recommended.
from finlab import data
from finlab.analysis import Analysis


class MarketValueAnalysis(Analysis):
    def calculate_trade_info(self, report):
        return [['market_value', data.get('etl:us_market_value'), 'entry_sig_date']]

    def analyze(self, report):
        trades = report.get_trades()
        assert 'market_value@entry_sig_date' in trades.columns
        self.result = trades[['market_value@entry_sig_date', 'return']]
        return self.result

    def display(self):
        return self.result

Custom Example

Average trade return by industry, using the industry of each U.S. stock from the backtest's market:

from finlab.analysis import Analysis


class IndustryAnalysis(Analysis):
    """Average trade return by industry"""

    def analyze(self, report):
        trades = report.get_trades()
        industry = trades['stock_id'].map(report.market.get_industry())
        self.result = (
            trades.groupby(industry)['return']
            .agg(['count', 'mean'])
            .sort_values('mean', ascending=False)
        )
        return self.result.to_dict()

    def display(self):
        return self.result


# Usage
report.run_analysis(IndustryAnalysis())

Best Practices

Standard Analysis Workflow

# Step 1: Basic performance review
report.display()

# Step 2: Volatility analysis (mandatory)
report.display_mae_mfe_analysis()

# Step 3: Period stability
report.run_analysis('PeriodStatsAnalysis')

# Step 4: Alpha/Beta
report.run_analysis('AlphaBetaAnalysis')

# Taiwan stocks only: liquidity risk (mandatory for large capital)
# report.run_analysis('LiquidityAnalysis', required_volume=100000)

By Strategy Type

Strategy Type Key Analysis Module
Short-term trading (intraday, weekly) MaeMfeAnalysis
Long-term investing (monthly, quarterly) PeriodStatsAnalysis
Large capital strategies on Taiwan stocks LiquidityAnalysis
Market-neutral strategies AlphaBetaAnalysis
High-frequency trading DrawdownAnalysis

Resources