跳轉到

finlab.analysis

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))
Source code in finlab/analysis/liquidityAnalysis.py
def __init__(self, required_volume=200000, required_turnover=1000000):
  """分析台股策略流動性風險項目的機率

  !!! note
      參考[VIP限定文章](https://www.finlab.tw/customized_liquidityanalysis/)更了解流動性檢測內容細節。
  Args:
      required_volume (int): 要求進出場時的單日成交股數至少要多少?
      required_turnover (int): 要求進出場時的單日成交金額至少要多少元?避免成交股數夠,但因低價股因素,造成胃納量仍無法符合資金需求。

  Examples:
      ``` py

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

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

  self._required_volume = required_volume
  self._required_turnover = required_turnover
  self._result = None

策略流動性檢測

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:股價淨值比')
Source code in finlab/analysis/inequalityAnalysis.py
def __init__(self, name, df=None, date_type='entry_sig_date', target='return'):

  """Analyze return of trades with condition inequality

  Args:
      name (str): name of the condition
      df (pd.DataFrame or None): value used in condition. If df is None, `data.get(name)` will be automatically perform to fetch the values.
      date_type (str): can be either `entry_date`, `entry_sig_date`, `exit_date`, `exit_sig_date`.
      target (str): the target to optimize. Any column name in report.get_trades()

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

  self._name = name
  self._date_type = date_type
  self._target = target
  self._result = None
  self._min_samples = 50
  self._outlier_std = 3
  self._df = data.get(name) if df is None else df

  if isinstance(self._df, FinlabDataFrame):
      self._df = self._df.index_str_to_date()

  if not isinstance(self._df, pd.DataFrame) and not isinstance(self._df, FinlabDataFrame):
    raise Exception(f"InequalityAnalysis: df type is {type(df)} not supported!")

策略不等式因子分析

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
Source code in finlab/analysis/periodStatsAnalysis.py
def __init__(self):
    """分析台股策略的不同時期與大盤指標作比較

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

        ``` py
        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  |
    """
    self.results = None

    def safe_division(n, d):
        return n / d if d else 0

    calc_cagr = (
        lambda s: (s.add(1).prod()) ** safe_division(365.25, (s.index[-1] - s.index[0]).days) - 1 
        if len(s) > 1 else 0)

    def calc_calmar_ratio(pct):
        s = pct.add(1).cumprod().iloc[1:]
        return safe_division(calc_cagr(pct), abs(s.calc_max_drawdown()))

    self.metrics = [
            ("calmar_ratio", calc_calmar_ratio),
            ('sortino_ratio', lambda s: safe_division(s.mean(), s[s < 0].std())
                * (safe_division(len(s), (s.index[-1] - s.index[0]).days) * 365) ** 0.5),
            ('sharpe_ratio', lambda s: safe_division(s.mean(), s.std())
                * (safe_division(len(s), (s.index[-1] - s.index[0]).days) * 365) ** 0.5),
            ('profit_factor', lambda s: safe_division((s > 0).sum(), (s < 0).sum())),
            ('tail_ratio', lambda s: -safe_division(s.quantile(0.95), (s.quantile(0.05)))),
            ('return', lambda s: calc_cagr(s)),
            ('volatility', lambda s: s.std() * np.sqrt(safe_division(len(s), (s.index[-1] - s.index[0]).days) * 365)),
            ]

假如希望開發交易分析系統,可以繼承 finlab.analysis.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.

Source code in finlab/analysis/__init__.py
def analyze(self, 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.
    """
    pass

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)
Source code in finlab/analysis/__init__.py
def calculate_trade_info(self, report):
    """Additional trade info can be calculated easily.

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

    Examples:

      ``` py
      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)
      ```
    """
    return []

display

display()

Display result

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

Source code in finlab/analysis/__init__.py
def display(self):
    """Display result

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

is_market_info_supported

is_market_info_supported(market_info)

Check if market info is supported

RETURNS DESCRIPTION
bool

True, support. False not support.

Source code in finlab/analysis/__init__.py
def is_market_info_supported(self, market_info):
    """Check if market info is supported

    Returns:
      (bool): True, support. False not support.
    """
    return True