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: 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
close = data.get('price:收盤價')
position = close > close.average(20)
report = sim(position, resample='M')

# 1. Liquidity detection
report.run_analysis('LiquidityAnalysis', required_volume=100000)

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

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

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

Built-in Analysis Module Comparison

Module Purpose Key Output
LiquidityAnalysis Liquidity risk detection 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 Inequality factor Return concentration, Gini coefficient
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

finlab.analysis.liquidityAnalysis.LiquidityAnalysis

LiquidityAnalysis(required_volume=200000, required_turnover=1000000)

Bases: Analysis

分析台股策略流動性風險項目的機率

Note

參考VIP限定文章更了解流動性檢測內容細節。

Args: required_volume (int): 要求進出場時的單日成交股數至少要多少? required_turnover (int): 要求進出場時的單日成交金額至少要多少元?避免成交股數夠,但因低價股因素,造成胃納量仍無法符合資金需求。

Examples:

# better syntax
report.run_analysis('LiquidityAnalysis', required_volume=100000)

# original syntax
from finlab.analysis.liquidityAnalysis import LiquidityAnalysis
report.run_analysis(LiquidityAnalysis(required_volume=100000))

is_market_supported

is_market_supported(market)

Check if the market is supported for liquidity analysis.

Currently only Taiwan stock market is supported, as it has unique features like disposal stocks, warning stocks, full delivery stocks, and price limit regulations.

Strategy Liquidity Analysis

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

finlab.analysis.inequalityAnalysis.InequalityAnalysis

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

Bases: Analysis

Analyze return of trades with condition inequality

PARAMETER DESCRIPTION
name

name of the condition

TYPE: str

df

value used in condition. If df is None, data.get(name) will be automatically perform to fetch the values.

TYPE: DataFrame or None DEFAULT: None

date_type

can be either entry_date, entry_sig_date, exit_date, exit_sig_date.

TYPE: str DEFAULT: 'entry_sig_date'

target

the target to optimize. Any column name in report.get_trades()

TYPE: str DEFAULT: 'return'

Examples:

report.run_analysis('InequalityAnalysis', name='price_earning_ratio:股價淨值比')

Strategy Inequality Factor Analysis

Robustness Assessment

  • Gini coefficient > 0.7: Returns are overly concentrated, diversification needed
  • Top 5% of stocks contributing > 50% of returns: Strategy robustness is insufficient

PeriodStatsAnalysis - Period Stability Analysis

finlab.analysis.periodStatsAnalysis.PeriodStatsAnalysis

PeriodStatsAnalysis()

Bases: Analysis

分析台股策略的不同時期與大盤指標作比較

Examples:

可以執行以下程式碼來產生分析結果:

report.run_analysis('PeriodStatsAnalysis')

產生的結果:

benchmark strategy
('overall_daily', 'calmar_ratio') 0.149192 0.0655645
('overall_daily', 'sortino_ratio') 0.677986 0.447837
('overall_daily', 'sharpe_ratio') 0.532014 0.306351
('overall_daily', 'profit_factor') 1.20022 1.07741
('overall_daily', 'tail_ratio') 0.914881 0.987751
('overall_daily', 'return') 0.0835801 0.0478957
('overall_daily', 'volatility') 0.182167 0.312543
('overall_monthly', 'calmar_ratio') 0.155321 0.0731378
('overall_monthly', 'sortino_ratio') 0.697382 0.439003
('overall_monthly', 'sharpe_ratio') 0.524943 0.307292
('overall_monthly', 'profit_factor') 1.75714 1.27059
('overall_monthly', 'tail_ratio') 1.03322 0.903335
('overall_monthly', 'return') 0.0836545 0.0479377
('overall_monthly', 'volatility') 0.186989 0.316178
('overall_yearly', 'calmar_ratio') 0.436075 0.127784
('overall_yearly', 'sortino_ratio') 0.738327 0.694786
('overall_yearly', 'sharpe_ratio') 0.407324 0.350986
('overall_yearly', 'profit_factor') 2.2 1.66667
('overall_yearly', 'tail_ratio') 1.71647 1.359
('overall_yearly', 'return') 0.0814469 0.0663674
('overall_yearly', 'volatility') 0.284742 0.419087

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

Bases: Analysis

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

Bases: Analysis

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)

Bases: Analysis

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.

finlab.analysis.Analysis

Bases: ABC

analyze

analyze(report)

Analyze trading report.

One could assume self.caluclate_trade_info will be executed before self.analyze, so the report.get_trades() will contain the required trade info.

calculate_trade_info

calculate_trade_info(report)

Additional trade info can be calculated easily.

User could override this function if additional trade info is required for later anlaysis.

Examples:

from finlab.analysis import Analysis

class SomeAnalysis(Analysis):
  def calculate_trade_info(self, report):
    return [
      ['股價淨值比', data.get('price_earning_ratio:股價淨值比'), 'entry_sig_date']
    ]

report.run_analysis(SomeAnalysis())
trades = report.get_trades()

assert '股價淨值比@entry_sig_date' in trades.columns

print(trades)

display

display()

Display result

When implement this function, returning Plotly figure instance is recommended.

is_market_supported

is_market_supported(market)

Check if market info is supported

RETURNS DESCRIPTION
bool

True, support. False not support.

Custom Example

from finlab import data
from finlab.analysis import Analysis

class IndustryAnalysis(Analysis):
    """Industry Analysis"""

    def calculate_trade_info(self, report):
        industry = data.get('etl:industry')
        return [['產業', industry, 'entry_sig_date']]

    def analyze(self, report):
        trades = report.get_trades()
        industry_stats = trades.groupby('產業@entry_sig_date')['return'].agg(['count', 'mean'])
        self.result = industry_stats.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: Liquidity risk (mandatory for large capital)
if capital > 1000000:
    report.run_analysis('LiquidityAnalysis', required_volume=100000)

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

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

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

By Strategy Type

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

Resources