跳轉到

finlab.plot

finlab.plot.plot_tw_stock_candles

plot_tw_stock_candles(stock_id, recent_days=400, adjust_price=False, resample='D', overlay_func=None, technical_func=None)

繪製台股技術線圖圖組 Args: stock_id (str): 台股股號,ex:'2330'。 recent_days (int):取近n個交易日資料。 adjust_price (bool):是否使用還原股價計算。 resample (str): 技術指標價格週期,ex: D 代表日線, W 代表週線, M 代表月線。 overlay_func (dict): K線圖輔助線,預設使用布林通道。

from finlab.data import indicator

overlay_func={
             'ema_5':indicator('EMA',timeperiod=5),
             'ema_10':indicator('EMA',timeperiod=10),
             'ema_20':indicator('EMA',timeperiod=20),
             'ema_60':indicator('EMA',timeperiod=60),
            }
technical_func (list): 技術指標子圖,預設使用KD技術指標單組子圖。

    設定多組技術指標:
    ```py
    from finlab.data import indicator

    k,d = indicator('STOCH')
    rsi = indicator('RSI')
    technical_func = [{'K':k,'D':d},{'RSI':rsi}]
    ```
RETURNS DESCRIPTION
Figure

技術線圖

Examples:

from finlab.plot import plot_tw_stock_candles
from finlab.data import indicator

overlay_func={
              'ema_5':indicator('EMA',timeperiod=5),
              'ema_10':indicator('EMA',timeperiod=10),
              'ema_20':indicator('EMA',timeperiod=20),
              'ema_60':indicator('EMA',timeperiod=60),
             }
k,d = indicator('STOCH')
rsi = indicator('RSI')
technical_func = [{'K':k,'D':d},{'RSI':rsi}]
plot_tw_stock_candles(stock_id='2330',recent_days=600,adjust_price=False,overlay_func=overlay_func,technical_func=technical_func)
Source code in finlab/plot.py
def plot_tw_stock_candles(stock_id, recent_days=400, adjust_price=False, resample='D', overlay_func=None,
                          technical_func=None):
    """繪製台股技術線圖圖組
    Args:
        stock_id (str): 台股股號,ex:`'2330'`。
        recent_days (int):取近n個交易日資料。
        adjust_price (bool):是否使用還原股價計算。
        resample (str): 技術指標價格週期,ex: `D` 代表日線, `W` 代表週線, `M` 代表月線。
        overlay_func (dict):
            K線圖輔助線,預設使用布林通道。
             ```py
             from finlab.data import indicator

             overlay_func={
                          'ema_5':indicator('EMA',timeperiod=5),
                          'ema_10':indicator('EMA',timeperiod=10),
                          'ema_20':indicator('EMA',timeperiod=20),
                          'ema_60':indicator('EMA',timeperiod=60),
                         }
             ```
        technical_func (list):
            技術指標子圖,預設使用KD技術指標單組子圖。

            設定多組技術指標:
            ```py
            from finlab.data import indicator

            k,d = indicator('STOCH')
            rsi = indicator('RSI')
            technical_func = [{'K':k,'D':d},{'RSI':rsi}]
            ```

    Returns:
        (plotly.graph_objects.Figure): 技術線圖

    Examples:
        ```py
        from finlab.plot import plot_tw_stock_candles
        from finlab.data import indicator

        overlay_func={
                      'ema_5':indicator('EMA',timeperiod=5),
                      'ema_10':indicator('EMA',timeperiod=10),
                      'ema_20':indicator('EMA',timeperiod=20),
                      'ema_60':indicator('EMA',timeperiod=60),
                     }
        k,d = indicator('STOCH')
        rsi = indicator('RSI')
        technical_func = [{'K':k,'D':d},{'RSI':rsi}]
        plot_tw_stock_candles(stock_id='2330',recent_days=600,adjust_price=False,overlay_func=overlay_func,technical_func=technical_func)
        ```
    """
    if adjust_price:
        close = data.get('etl:adj_close')[stock_id]
        open_ = data.get('etl:adj_open')[stock_id]
        high = data.get('etl:adj_high')[stock_id]
        low = data.get('etl:adj_low')[stock_id]
    else:
        close = data.get('price:收盤價')[stock_id]
        open_ = data.get('price:開盤價')[stock_id]
        high = data.get('price:最高價')[stock_id]
        low = data.get('price:最低價')[stock_id]

    volume = data.get('price:成交股數')[stock_id]

    return plot_candles(stock_id, close, open_, high, low, volume, recent_days=recent_days, resample=resample,
                        overlay_func=overlay_func, technical_func=technical_func)

finlab.plot.create_treemap_data

create_treemap_data(start, end, item='return_ratio', clip=None)

產生台股板塊圖資料

產生繪製樹狀圖所用的資料,可再外加FinLab資料庫以外的指標製作客製化DataFrame, 並傳入plot_tw_stock_treemap(treemap_data=treemap_data)。

PARAMETER DESCRIPTION
start

資料開始日,ex:"2021-01-02"

TYPE: str

end

資料結束日,ex:"2021-01-05"

TYPE: str

item

決定板塊顏色深淺的指標。 除了可選擇依照 start 與 end 計算的"return_ratio"(報酬率), 亦可選擇FinLab資料庫內的指標顯示近一期資料。 example:

  • 'price_earning_ratio:本益比' - 顯示近日產業的本益比高低。
  • 'monthly_revenue:去年同月增減(%)' - 顯示近月的單月營收年增率。

TYPE: str DEFAULT: 'return_ratio'

clip

將item邊界外的值分配給邊界值,防止資料上限值過大或過小,造成顏色深淺變化不明顯。 ex:(0,100),將數值低高界線,設為0~100,超過的數值。

Note

參考pandas文件更了解pd.clip細節。

TYPE: tuple DEFAULT: None

RETURNS DESCRIPTION
DataFrame

台股個股指標

Examples:

欲下載所有上市上櫃之價量歷史資料與產業分類,只需執行此函式:

``` py
from finlab.plot import create_treemap_data
create_treemap_data(start= '2021-07-01',end = '2021-07-02')
```

| stock_id   |  close |turnover|category|market|market_value|return_ratio|country|
|:-----------|-------:|-------:|-------:|-------:|-------:|-------:|-------:|
| 1101       |   20 |  57.85 |  水泥工業 |  sii   |    111  |    0.1  |  TW-Stock|
| 1102       |  20 |  58.1  |  水泥工業 |  sii    |    111  |    -0.1 |  TW-Stock|
Source code in finlab/plot.py
def create_treemap_data(start, end, item='return_ratio', clip=None):
    """產生台股板塊圖資料

    產生繪製樹狀圖所用的資料,可再外加FinLab資料庫以外的指標製作客製化DataFrame,
    並傳入`plot_tw_stock_treemap(treemap_data=treemap_data)。`

    Args:
      start (str): 資料開始日,ex:`"2021-01-02"`。
      end (str):資料結束日,ex:`"2021-01-05"`。
      item (str): 決定板塊顏色深淺的指標。
                  除了可選擇依照 start 與 end 計算的`"return_ratio"`(報酬率),
                  亦可選擇[FinLab資料庫](https://ai.finlab.tw/database)內的指標顯示近一期資料。
          example:

          * `'price_earning_ratio:本益比'` - 顯示近日產業的本益比高低。
          * `'monthly_revenue:去年同月增減(%)'` - 顯示近月的單月營收年增率。

      clip (tuple): 將item邊界外的值分配給邊界值,防止資料上限值過大或過小,造成顏色深淺變化不明顯。
                    ex:(0,100),將數值低高界線,設為0~100,超過的數值。
        !!! note

            參考[pandas文件](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.clip.html)更了解`pd.clip`細節。

    Returns:
        (pd.DataFrame): 台股個股指標
    Examples:

        欲下載所有上市上櫃之價量歷史資料與產業分類,只需執行此函式:

        ``` py
        from finlab.plot import create_treemap_data
        create_treemap_data(start= '2021-07-01',end = '2021-07-02')
        ```

        | stock_id   |  close |turnover|category|market|market_value|return_ratio|country|
        |:-----------|-------:|-------:|-------:|-------:|-------:|-------:|-------:|
        | 1101       |   20 |  57.85 |  水泥工業 |  sii   |    111  |    0.1  |  TW-Stock|
        | 1102       |  20 |  58.1  |  水泥工業 |  sii    |    111  |    -0.1 |  TW-Stock|


    """
    close = data.get('price:收盤價')
    basic_info = data.get('company_basic_info')
    turnover = data.get('price:成交金額')
    close_data = df_date_filter(close, start, end)
    turnover_data = df_date_filter(
        turnover, start, end).iloc[1:].sum() / 100000000
    return_ratio = (
        close_data.loc[end] / close_data.loc[start]).dropna().replace(np.inf, 0)
    return_ratio = round((return_ratio - 1) * 100, 2)

    concat_list = [close_data.iloc[-1], turnover_data, return_ratio]
    col_names = ['stock_id', 'close', 'turnover', 'return_ratio']
    if item not in ["return_ratio", "turnover_ratio"]:
        try:
            custom_item = df_date_filter(
                data.get(item), start, end).iloc[-1].fillna(0)
        except Exception as e:
            logger.error(
                'data error, check the data is existed between start and end.')
            logger.error(e)
            return None
        if clip:
            custom_item = custom_item.clip(*clip)
        concat_list.append(custom_item)
        col_names.append(item)

    df = pd.concat(concat_list, axis=1).dropna()
    df = df.reset_index()
    df.columns = col_names

    basic_info_df = basic_info.copy().reset_index()
    basic_info_df['stock_id_name'] = basic_info_df['stock_id'].astype(
        str) + basic_info_df['公司簡稱']

    df = df.merge(basic_info_df[['stock_id', 'stock_id_name', '產業類別', '市場別', '實收資本額(元)']], how='left',
                  on='stock_id')
    df = df.rename(columns={'產業類別': 'category',
                   '市場別': 'market', '實收資本額(元)': 'base'})
    df = df.dropna(thresh=5)
    df['market_value'] = round(df['base'] / 10 * df['close'] / 100000000, 2)
    df['country'] = 'TW-Stock'
    return df

finlab.plot.plot_tw_stock_treemap

plot_tw_stock_treemap(start=None, end=None, area_ind='market_value', item='return_ratio', clip=None, color_continuous_scale='Temps', treemap_data=None)

繪製台股板塊圖資料

巢狀樹狀圖可以顯示多維度資料,將依照產業分類的台股資料絢麗顯示。

PARAMETER DESCRIPTION
start

資料開始日,ex:'2021-01-02'

TYPE: str DEFAULT: None

end

資料結束日,ex:'2021-01-05'

TYPE: str DEFAULT: None

area_ind

決定板塊面積數值的指標。 可選擇["market_value","turnover"],數值代表含義分別為市值、成交金額。

TYPE: str DEFAULT: 'market_value'

item

決定板塊顏色深淺的指標。 除了可選擇依照 start 與 end 計算的"return_ratio"(報酬率), 亦可選擇FinLab資料庫內的指標顯示近一期資料。 example:

  • 'price_earning_ratio:本益比' - 顯示近日產業的本益比高低。
  • 'monthly_revenue:去年同月增減(%)' - 顯示近月的單月營收年增率。

TYPE: str DEFAULT: 'return_ratio'

clip

將 item 邊界外的值分配給邊界值,防止資料上限值過大或過小,造成顏色深淺變化不明顯。 ex:(0,100),將數值低高界線,設為 0~100,超過的數值。

Note

參考pandas文件更了解pd.clip細節。

TYPE: tuple DEFAULT: None

color_continuous_scale

TYPE: str DEFAULT: 'Temps'

treemap_data

客製化資料,格式參照 create_treemap_data() 返回值。

TYPE: DataFrame DEFAULT: None

Returns: (plotly.graph_objects.Figure): 樹狀板塊圖 Examples: ex1: 板塊面積顯示成交金額,顏色顯示'2021-07-01'~'2021-07-02'的報酬率變化,可以觀察市場資金集中的產業與漲跌強弱。

from finlab.plot import plot_tw_stock_treemap
plot_tw_stock_treemap(start= '2021-07-01',end = '2021-07-02',area_ind="turnover",item="return_ratio")
成交佔比/報酬率板塊圖 ex2: 板塊面積顯示市值(股本*收盤價),顏色顯示近期本益比,可以觀察全市場哪些是權值股?哪些產業本益比評價高?限制數值範圍在(0,50), 將過高本益比的數值壓在50,不讓顏色變化突兀,能分出高低階層即可。
from finlab.plot import plot_tw_stock_treemap
plot_tw_stock_treemap(area_ind="market_value",item="price_earning_ratio:本益比",clip=(0,50), color_continuous_scale='RdBu_r')
市值/本益比板塊圖

Source code in finlab/plot.py
def plot_tw_stock_treemap(start=None, end=None, area_ind='market_value', item='return_ratio', clip=None,
                          color_continuous_scale='Temps', treemap_data=None):
    """繪製台股板塊圖資料

    巢狀樹狀圖可以顯示多維度資料,將依照產業分類的台股資料絢麗顯示。

    Args:
      start (str): 資料開始日,ex:`'2021-01-02'`。
      end (str): 資料結束日,ex:`'2021-01-05'`。
      area_ind (str): 決定板塊面積數值的指標。
                      可選擇`["market_value","turnover"]`,數值代表含義分別為市值、成交金額。
      item (str): 決定板塊顏色深淺的指標。
                  除了可選擇依照 start 與 end 計算的`"return_ratio"`(報酬率),
                  亦可選擇[FinLab資料庫](https://ai.finlab.tw/database)內的指標顯示近一期資料。
          example:

          * `'price_earning_ratio:本益比'` - 顯示近日產業的本益比高低。
          * `'monthly_revenue:去年同月增減(%)'` - 顯示近月的單月營收年增率。

      clip (tuple): 將 item 邊界外的值分配給邊界值,防止資料上限值過大或過小,造成顏色深淺變化不明顯。
                    ex:(0,100),將數值低高界線,設為 0~100,超過的數值。
        !!!note

            參考[pandas文件](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.clip.html)更了解`pd.clip`細節。
      color_continuous_scale (str):[顏色變化序列的樣式名稱](https://plotly.com/python/builtin-colorscales/)
      treemap_data (pd.DataFrame): 客製化資料,格式參照 `create_treemap_data()` 返回值。
    Returns:
        (plotly.graph_objects.Figure): 樹狀板塊圖
    Examples:
        ex1:
        板塊面積顯示成交金額,顏色顯示'2021-07-01'~'2021-07-02'的報酬率變化,可以觀察市場資金集中的產業與漲跌強弱。
        ```py
        from finlab.plot import plot_tw_stock_treemap
        plot_tw_stock_treemap(start= '2021-07-01',end = '2021-07-02',area_ind="turnover",item="return_ratio")
        ```
        ![成交佔比/報酬率板塊圖](img/plot/treemap_return.png)
        ex2:
        板塊面積顯示市值(股本*收盤價),顏色顯示近期本益比,可以觀察全市場哪些是權值股?哪些產業本益比評價高?限制數值範圍在(0,50),
        將過高本益比的數值壓在50,不讓顏色變化突兀,能分出高低階層即可。
        ```py
        from finlab.plot import plot_tw_stock_treemap
        plot_tw_stock_treemap(area_ind="market_value",item="price_earning_ratio:本益比",clip=(0,50), color_continuous_scale='RdBu_r')
        ```
        ![市值/本益比板塊圖](img/plot/treemap_pe.png)
    """
    if treemap_data is None:
        df = create_treemap_data(start, end, item, clip)
    else:
        df = treemap_data.copy()

    if df is None:
        return None
    df['custom_item_label'] = round(df[item], 2).astype(str)
    df.dropna(how='any', inplace=True)

    if area_ind not in df.columns:
        return None

    if item in ['return_ratio']:
        color_continuous_midpoint = 0
    else:
        color_continuous_midpoint = np.average(df[item], weights=df[area_ind])

    fig = px.treemap(df,
                     path=['country', 'market', 'category', 'stock_id_name'],
                     values=area_ind,
                     color=item,
                     color_continuous_scale=color_continuous_scale,
                     color_continuous_midpoint=color_continuous_midpoint,
                     custom_data=['custom_item_label', 'close', 'turnover'],
                     title=f'TW-Stock Market TreeMap({start}~{end})'
                           f'---area_ind:{area_ind}---item:{item}',
                     width=1600,
                     height=800)

    fig.update_traces(textposition='middle center',
                      textfont_size=24,
                      texttemplate="%{label}<br>(%{customdata[1]})<br>%{customdata[0]}",
                      )
    return fig

finlab.plot.plot_tw_stock_radar

plot_tw_stock_radar(portfolio, feats=None, mode='line_polar', line_polar_fill=None, period=None, cut_bins=10, title=None, custom_data=None)

繪製台股雷達圖

比較持股組合的指標分級特性。若數值為nan,則不顯示分級。

PARAMETER DESCRIPTION
portfolio

持股組合,ex:['1101','1102']

TYPE: list

feats

選定FinLab資料庫內的指標組成資料集。預設為18項財務指標。 ex:['fundamental_features:營業毛利率','fundamental_features:營業利益率']

TYPE: list DEFAULT: None

mode

雷達圖模式 ,ex:'bar_polar','scatter_polar','line_polar'`。

TYPE: str DEFAULT: 'line_polar'

line_polar_fill

將區域設置為用純色填充 。ex:None,'toself','tonext' 'toself'將跡線的端點(或跡線的每一段,如果它有間隙)連接成一個封閉的形狀。 如果一條完全包圍另一條(例如連續的等高線),則'tonext'填充兩條跡線之間的空間,如果之前沒有跡線, 則其行為類似於'toself'。如果一條跡線不包含另一條跡線,則不應使用'tonext'。 欲使用 line_polar,請將pandas版本降至 1.4.4。

TYPE: str DEFAULT: None

period

選擇第幾期的特徵資料,預設為近一季。 ex: 設定數值為'2020-Q2,取得2020年第二季資料比較。

TYPE: str DEFAULT: None

cut_bins

特徵分級級距。

TYPE: int DEFAULT: 10

title

圖片標題名稱。

TYPE: str DEFAULT: None

custom_data

客製化指標分級,欄名為特徵 格式範例:

stock_id 營業毛利率 營業利益率 稅後淨利率
1101 2 5 3
1102 1 8 4

TYPE: DataFrame DEFAULT: None

Returns: (plotly.graph_objects.Figure): 雷達圖 Examples: ex1:比較持股組合累計分數,看持股組合偏重哪像特徵。

from finlab.plot import plot_tw_stock_radar
plot_tw_stock_radar(portfolio=["1101", "2330", "8942", "6263"], mode="bar_polar", line_polar_fill='None')
持股組合雷達圖 ex2:看單一個股特徵分級落點。
from finlab.plot import plot_tw_stock_radar
feats = ['fundamental_features:營業毛利率', 'fundamental_features:營業利益率', 'fundamental_features:稅後淨利率',
         'fundamental_features:現金流量比率', 'fundamental_features:負債比率']
plot_tw_stock_radar(portfolio=["9939"], feats=feats, mode="line_polar", line_polar_fill='toself', cut_bins=8)
單檔標的子選指標雷達圖

Source code in finlab/plot.py
def plot_tw_stock_radar(portfolio, feats=None, mode='line_polar', line_polar_fill=None,
                        period=None, cut_bins=10, title=None, custom_data=None):
    """繪製台股雷達圖

    比較持股組合的指標分級特性。若數值為nan,則不顯示分級。

    Args:
      portfolio (list):持股組合,ex:`['1101','1102']`。
      feats (list): 選定FinLab資料庫內的指標組成資料集。預設為18項財務指標。
                    ex:['fundamental_features:營業毛利率','fundamental_features:營業利益率']
      mode (str): 雷達圖模式 ,ex:'bar_polar','scatter_polar','line_polar'`。
        !!!note

            參考[不同模式的差異](https://plotly.com/python-api-reference/generated/plotly.express.html)
      line_polar_fill (str):將區域設置為用純色填充 。ex:`None,'toself','tonext'`
                           `'toself'`將跡線的端點(或跡線的每一段,如果它有間隙)連接成一個封閉的形狀。
                           如果一條完全包圍另一條(例如連續的等高線),則`'tonext'`填充兩條跡線之間的空間,如果之前沒有跡線,
                           則其行為類似於`'toself'`。如果一條跡線不包含另一條跡線,則不應使用`'tonext'`。
        欲使用 line_polar,請將pandas版本降至 1.4.4。
        !!!note

            參考[plotly.graph_objects.Scatterpolar.fill](https://plotly.github.io/plotly.py-docs/generated/plotly.graph_objects.Scatterpolar.html)

      period (str): 選擇第幾期的特徵資料,預設為近一季。
                    ex: 設定數值為'2020-Q2,取得2020年第二季資料比較。
      cut_bins (int):特徵分級級距。
      title (str):圖片標題名稱。
      custom_data (pd.DataFrame): 客製化指標分級,欄名為特徵
                    格式範例:

        | stock_id   |  營業毛利率 |營業利益率|稅後淨利率|
        |:-----------|-------:|-------:|-------:|
        | 1101       |   2    |    5   |      3|
        | 1102       |   1    |    8   |      4|
    Returns:
        (plotly.graph_objects.Figure): 雷達圖
    Examples:
        ex1:比較持股組合累計分數,看持股組合偏重哪像特徵。
        ```py
        from finlab.plot import plot_tw_stock_radar
        plot_tw_stock_radar(portfolio=["1101", "2330", "8942", "6263"], mode="bar_polar", line_polar_fill='None')
        ```
        ![持股組合雷達圖](img/plot/radar_many.png)
        ex2:看單一個股特徵分級落點。
        ```py
        from finlab.plot import plot_tw_stock_radar
        feats = ['fundamental_features:營業毛利率', 'fundamental_features:營業利益率', 'fundamental_features:稅後淨利率',
                 'fundamental_features:現金流量比率', 'fundamental_features:負債比率']
        plot_tw_stock_radar(portfolio=["9939"], feats=feats, mode="line_polar", line_polar_fill='toself', cut_bins=8)
        ```
        ![單檔標的子選指標雷達圖](img/plot/radar_single.png)
    """
    if custom_data is None:
        if feats is None:
            feats = ['fundamental_features:營業毛利率', 'fundamental_features:營業利益率',
                     'fundamental_features:稅後淨利率',
                     'fundamental_features:ROA綜合損益', 'fundamental_features:ROE綜合損益',
                     'fundamental_features:業外收支營收率',
                     'fundamental_features:現金流量比率', 'fundamental_features:負債比率',
                     'fundamental_features:流動比率', 'fundamental_features:速動比率',
                     'fundamental_features:存貨週轉率',
                     'fundamental_features:營收成長率', 'fundamental_features:營業毛利成長率',
                     'fundamental_features:營業利益成長率', 'fundamental_features:稅前淨利成長率',
                     'fundamental_features:稅後淨利成長率',
                     'fundamental_features:資產總額成長率', 'fundamental_features:淨值成長率'
                     ]
        df = get_rank_df(feats, period=period, cut_bins=cut_bins)
    else:
        df = custom_data.copy()

    col_name = df.columns
    portfolio = df.index.intersection(portfolio)
    if len(portfolio) < 1:
        logger.error('data is not existed.')
        return
    df = df.loc[portfolio]
    df = df.reset_index()
    df = pd.melt(df, id_vars=['stock_id'], value_vars=col_name)
    polar_range = cut_bins * len(portfolio)
    fig = plot_radar(df=df, mode=mode, line_polar_fill=line_polar_fill,
                     title=title, polar_range=polar_range)
    return fig

finlab.plot.plot_tw_stock_river

plot_tw_stock_river(stock_id='2330', start=None, end=None, mode='pe', split_range=8)

繪製台股河流圖

使用 PE or PB 的最高與最低值繪製河流圖,判斷指標所處位階。

PARAMETER DESCRIPTION
stock_id

台股股號,ex:'2330'

TYPE: str DEFAULT: '2330'

start

資料開始日,ex:'2020-01-02'

TYPE: str DEFAULT: None

end

資料結束日,ex:'2022-01-05'

TYPE: str DEFAULT: None

mode

'pe' or 'pb' (本益比或股價淨值比)。

TYPE: str DEFAULT: 'pe'

split_range

河流階層數。

TYPE: int DEFAULT: 8

Returns: (plotly.graph_objects.Figure): 河流圖 Examples:

from finlab.plot import plot_tw_stock_river
plot_tw_stock_river(stock_id='2330', start='2015-1-1', end='2022-7-1', mode='pe', split_range=10)
單檔標的子選指標雷達圖

Source code in finlab/plot.py
def plot_tw_stock_river(stock_id='2330', start=None, end=None, mode='pe', split_range=8):
    """繪製台股河流圖

    使用 PE or PB 的最高與最低值繪製河流圖,判斷指標所處位階。

    Args:
      stock_id (str): 台股股號,ex:`'2330'`。
      start (str): 資料開始日,ex:`'2020-01-02'`。
      end (str): 資料結束日,ex:`'2022-01-05'`。
      mode (str): `'pe'` or `'pb'` (本益比或股價淨值比)。
      split_range (int): 河流階層數。
    Returns:
        (plotly.graph_objects.Figure): 河流圖
    Examples:
      ```py
      from finlab.plot import plot_tw_stock_river
      plot_tw_stock_river(stock_id='2330', start='2015-1-1', end='2022-7-1', mode='pe', split_range=10)
      ```
      ![單檔標的子選指標雷達圖](img/plot/pe_river.png)
    """
    df = get_pe_river_data(start, end, stock_id, mode, split_range)
    if df is None:
        logger.error('data error')
        return None
    col_name_set = [i for i in df.columns if any(map(str.isdigit, i))]

    fig = go.Figure()
    for n, c in enumerate(col_name_set):
        if n == 0:
            fill_mode = None
        else:
            fill_mode = 'tonexty'
        fig.add_trace(
            go.Scatter(x=df.index, y=df[c], fill=fill_mode, line=dict(width=0, color=px.colors.qualitative.Prism[n]),
                       name=c))
    customdata = [(c, p) for c, p in zip(df['close'], df[mode])]
    hovertemplate = "<br>date:%{x|%Y/%m/%d}<br>close:%{customdata[0]}" + \
        f"<br>{mode}" + ":%{customdata[1]}"
    fig.add_trace(go.Scatter(x=df.index, y=df['close'], line=dict(width=2.5, color='#2e4391'), customdata=customdata,
                             hovertemplate=hovertemplate, name='close'))

    security_categories = data.get('security_categories').set_index('stock_id')
    stock_name = security_categories.loc[stock_id]['name']
    fig.update_layout(title=f"{stock_id} {stock_name} {mode.upper()} River Chart",
                      template="ggplot2",
                      yaxis=dict(
                          title='price',
                      ),
                      # hovermode='x unified',
                      )
    fig.update_xaxes(showspikes=True)
    fig.update_yaxes(showspikes=True)
    return fig

finlab.plot.StrategySunburst

StrategySunburst()

繪製策略部位旭日圖

監控多策略。

Source code in finlab/plot.py
def __init__(self):
    """繪製策略部位旭日圖

    監控多策略。
    """
    d = data.get_strategies()
    for k, v in d.items():
        if 'position' in d[k]['positions']:
            d[k]['positions'] = d[k]['positions']['position']
    self.s_data = d

get_strategy_df

get_strategy_df(select_strategy=None)

獲取策略部位與分配權重後計算的資料

PARAMETER DESCRIPTION
select_strategy

選擇策略名稱並設定權重,預設是抓取權策略並平分資金比例到各策略。 ex:{'低波動本益成長比':0.5,'研發魔人':0.2, '現金':0.2}

TYPE: dict DEFAULT: None

Returns: (pd.DataFrame): strategies data

Source code in finlab/plot.py
def get_strategy_df(self, select_strategy=None):
    """獲取策略部位與分配權重後計算的資料

    Args:
      select_strategy (dict): 選擇策略名稱並設定權重,預設是抓取權策略並平分資金比例到各策略。
                             ex:`{'低波動本益成長比':0.5,'研發魔人':0.2, '現金':0.2}`
    Returns:
        (pd.DataFrame): strategies data
    """
    if select_strategy is None:
        s_name = self.s_data.keys()
        s_num = len(s_name)
        if s_num == 0:
            return None
        s_weight = [1 / s_num] * len(s_name)
    else:
        s_name = select_strategy.keys()
        s_weight = select_strategy.values()

    all_position = pd.concat([self.process_position(
        name, weight) for name, weight in zip(s_name, s_weight)])
    all_position['weight'] *= all_position['s_weight']
    all_position['return'] = round(all_position['return'].astype(float), 2)
    all_position['color'] = round(
        all_position['return'].clip(all_position['return'].min() / 2, all_position['return'].max() / 2), 2)
    all_position = all_position[all_position['weight'] > 0]
    all_position = all_position.reset_index()
    all_position = all_position[all_position['s_name'] != 'playground']
    all_position['category'] = all_position['category'].fillna(
        'other_securities')
    return all_position

plot

plot(select_strategy=None, path=None, color_continuous_scale='RdBu_r')

繪圖

PARAMETER DESCRIPTION
select_strategy

選擇策略名稱並設定權重,預設是抓取權策略並平分資金比例到各策略。 ex:{'低波動本益成長比':0.5,'研發魔人':0.2, '現金':0.2}

TYPE: dict DEFAULT: None

path

旭日圖由裡到外的顯示路徑,預設為['s_name', 'market', 'category', 'stock_id']['market', 'category','stock_id','s_name']也是常用選項。

TYPE: list DEFAULT: None

color_continuous_scale

TYPE: str DEFAULT: 'RdBu_r'

RETURNS DESCRIPTION
Figure

策略部位旭日圖

Examples:

from finlab.plot import StrategySunburst

# 實例化物件
strategies = StrategySunburst()
strategies.plot().show()
strategies.plot(select_strategy={'高殖利率烏龜':0.4,'營收強勢動能瘋狗':0.25,'低波動本益成長比':0.2,'現金':0.15},path =  ['market', 'category','stock_id','s_name']).show()
ex1:策略選到哪些標的? 市值/本益比板塊圖

ex2:部位被哪些策略選到,標的若被不同策略選到,可能有獨特之處喔! 市值/本益比板塊圖

Source code in finlab/plot.py
def plot(self, select_strategy=None, path=None, color_continuous_scale='RdBu_r'):
    """繪圖

    Args:
      select_strategy (dict): 選擇策略名稱並設定權重,預設是抓取權策略並平分資金比例到各策略。
                             ex:`{'低波動本益成長比':0.5,'研發魔人':0.2, '現金':0.2}`
      path (list): 旭日圖由裡到外的顯示路徑,預設為`['s_name', 'market', 'category', 'stock_id']`。
                   `['market', 'category','stock_id','s_name']`也是常用選項。
      color_continuous_scale (str):[顏色變化序列的樣式名稱](https://plotly.com/python/builtin-colorscales/)

    Returns:
        (plotly.graph_objects.Figure): 策略部位旭日圖
    Examples:
        ```py
        from finlab.plot import StrategySunburst

        # 實例化物件
        strategies = StrategySunburst()
        strategies.plot().show()
        strategies.plot(select_strategy={'高殖利率烏龜':0.4,'營收強勢動能瘋狗':0.25,'低波動本益成長比':0.2,'現金':0.15},path =  ['market', 'category','stock_id','s_name']).show()
        ```
    ex1:策略選到哪些標的?
    ![市值/本益比板塊圖](img/plot/sunburst1.png)

    ex2:部位被哪些策略選到,標的若被不同策略選到,可能有獨特之處喔!
    ![市值/本益比板塊圖](img/plot/sunburst2.png)
    """
    position = self.get_strategy_df(select_strategy)
    if position is None:
        return
    position = position[(position['return'] != np.inf)
                        | (position['weight'] != np.inf)]
    if path is None:
        path = ['s_name', 'market', 'category', 'stock_id']
    fig = px.sunburst(position, path=path, values='weight',
                      color='color', hover_data=['return'],
                      color_continuous_scale=color_continuous_scale,
                      color_continuous_midpoint=0,
                      width=1000, height=800)
    return fig

finlab.plot.StrategyReturnStats

StrategyReturnStats(start_date, end_date, strategy_names=[], benchmark_return=None)

繪製策略報酬率統計比較圖

監控策略群體相對對標指數的表現。

PARAMETER DESCRIPTION
start_date

報酬率計算開始日

TYPE: str

end_date

報酬率計算結束日

TYPE: str

strategy_names

用戶本人的策略集設定,填入欲納入統計的策略名稱,只限定自己的策略。ex:['膽小貓','三頻率RSI策略', '二次創高股票',...],預設為全部已上傳的策略。

TYPE: list DEFAULT: []

benchmark_return

策略比對基準序列,預設為台股加權報酬指數。

TYPE: Series DEFAULT: None

Examples:

統計2022-12-31~2023-07-31的報酬率數據
``` py
# 回測起始時間
start_date = '2022-12-31'
end_date  = '2023-07-31'

# 選定策略範圍
strategy_names = ['膽小貓','三頻率RSI策略', '二次創高股票', '低波動本益成長比', '合約負債建築工', '多產業價投', '小蝦米跟大鯨魚', '小資族資優生策略', '本益成長比', '營收股價雙渦輪', '現金流價值成長', '研發魔人', '股價淨值比策略', '藏獒', '高殖利率烏龜','監獄兔', '財報指標20大']

report = StrategyReturnStats(start_date ,end_date, strategy_names)
# 繪製策略報酬率近期報酬率長條圖
report.plot_strategy_last_return().show()
# 繪製策略累積報酬率時間序列
report.plot_strategy_creturn().show()
```
Source code in finlab/plot.py
def __init__(self, start_date: str, end_date: str, strategy_names=[], benchmark_return=None):
    """繪製策略報酬率統計比較圖

    監控策略群體相對對標指數的表現。

    Args:
        start_date (str): 報酬率計算開始日
        end_date (str): 報酬率計算結束日
        strategy_names (list): 用戶本人的策略集設定,填入欲納入統計的策略名稱,只限定自己的策略。ex:`['膽小貓','三頻率RSI策略', '二次創高股票',...]`,預設為全部已上傳的策略。
        benchmark_return (pandas.Series): 策略比對基準序列,預設為台股加權報酬指數。


    Examples:

        統計2022-12-31~2023-07-31的報酬率數據
        ``` py
        # 回測起始時間
        start_date = '2022-12-31'
        end_date  = '2023-07-31'

        # 選定策略範圍
        strategy_names = ['膽小貓','三頻率RSI策略', '二次創高股票', '低波動本益成長比', '合約負債建築工', '多產業價投', '小蝦米跟大鯨魚', '小資族資優生策略', '本益成長比', '營收股價雙渦輪', '現金流價值成長', '研發魔人', '股價淨值比策略', '藏獒', '高殖利率烏龜','監獄兔', '財報指標20大']

        report = StrategyReturnStats(start_date ,end_date, strategy_names)
        # 繪製策略報酬率近期報酬率長條圖
        report.plot_strategy_last_return().show()
        # 繪製策略累積報酬率時間序列
        report.plot_strategy_creturn().show()
        ```

    """
    # 回測起始時間
    self.start_date = start_date
    self.end_date = end_date

    # 選定策略範圍
    self.s_data = data.get_strategies()
    self.strategy_names = strategy_names
    self.benchmark_return = data.get('benchmark_return:發行量加權股價報酬指數')[
        '發行量加權股價報酬指數'] if benchmark_return is None else benchmark_return
    self.returns_set = self._get_returns_set()

get_benchmark_return

get_benchmark_return()

設定對標指數 Returns: (pandas.Series): 對標指數時間序列

Source code in finlab/plot.py
def get_benchmark_return(self):
    """設定對標指數
    Returns:
        (pandas.Series): 對標指數時間序列
    """
    benchmark_return = self.benchmark_return
    benchmark_return = benchmark_return[
        (benchmark_return.index >= self.start_date) & (benchmark_return.index <= self.end_date)]
    return benchmark_return

plot_strategy_creturn

plot_strategy_creturn()

繪製策略累積報酬率時間序列 Returns: (plotly.graph_objects.Figure): 圖表物件 繪製策略累積報酬率時間序列

Source code in finlab/plot.py
def plot_strategy_creturn(self):
    """繪製策略累積報酬率時間序列
    Returns:
        (plotly.graph_objects.Figure): 圖表物件
    ![繪製策略累積報酬率時間序列](img/plot/finlab_strategy_creturn.png)
    """

    returns_set = self.returns_set
    benchmark_return = self.get_benchmark_return()

    sorted_s_names = list(returns_set.keys())[::-1]

    returns_set2 = {}
    for s_name in sorted_s_names:
        s_df = self.s_data[s_name]
        returns = pd.Series(s_df['returns']['value'],
                            index=s_df['returns']['time'])
        if self.start_date:
            returns = returns[returns.index >= self.start_date]
        if self.end_date:
            returns = returns[returns.index <= self.end_date]
        returns_set2[s_name] = round(
            ((returns / returns.iloc[0]) - 1) * 100, 2)

    returns_df = pd.DataFrame(
        returns_set2).unstack().to_frame().reset_index()
    returns_df.columns = ['strategy', 'date', 'creturns']
    benchmark_creturn = round(
        ((benchmark_return / benchmark_return.iloc[0]) - 1) * 100, 2)

    fig = px.line(returns_df, x="date", y="creturns", color="strategy")
    fig.add_trace(
        go.Scatter(x=benchmark_creturn.index, y=benchmark_creturn.values, fill='tonexty', name='benchmark',
                   opacity=0.2,
                   marker=dict(
                       color='LightSkyBlue',
                       opacity=0.2,
                       size=20,
                       line=dict(
                           color='MediumPurple',
                           width=2
                       )
                   ), ))

    fig.update_layout(
        title=f'FinLab Strategy Creturn ({self.start_date}~{self.end_date})',
        margin=dict(l=100, r=20, t=70, b=70),
        paper_bgcolor='rgb(248, 248, 255)',
        plot_bgcolor='rgb(248, 248, 255)',
        yaxis_title="creturn (%)",
    )

    fig.update_layout(yaxis_range=(
        returns_df["creturns"].min() - 0.1, returns_df["creturns"].max() + 0.1))

    return fig

plot_strategy_last_return

plot_strategy_last_return()

繪製策略報酬率近期報酬率長條圖 Returns: (plotly.graph_objects.Figure): 圖表物件 繪製策略報酬率近期報酬率長條圖

Source code in finlab/plot.py
def plot_strategy_last_return(self):
    """繪製策略報酬率近期報酬率長條圖
    Returns:
        (plotly.graph_objects.Figure): 圖表物件
    ![繪製策略報酬率近期報酬率長條圖](img/plot/finlab_strategy_performance.png)
    """
    returns_set = self.returns_set
    benchmark_return = self.get_benchmark_return()
    benchmark_last_return = round(
        ((benchmark_return.iloc[-1] / benchmark_return.iloc[0]) - 1) * 100, 2)

    fig = go.Figure(go.Bar(
        x=list(returns_set.values()),
        y=list(returns_set.keys()),
        marker=dict(
            color='rgba(50, 171, 96, 0.6)',
            line=dict(color='rgba(50, 171, 96, 1)', width=3)
        ),
        orientation='h'))

    fig.add_vline(x=benchmark_last_return, line_width=3, line_dash="dash", line_color="#4a6dce",
                  annotation_text=f"benchmark:{benchmark_last_return}",
                  annotation_position="top left")

    returns_mean = round(sum((returns_set.values())) / len(returns_set), 2)

    fig.add_vline(x=returns_mean, line_width=3, line_dash="dash", line_color="#aa00ff",
                  annotation_font_color="#aa00ff", annotation_text=f"strategy_mean:{returns_mean}",
                  annotation_position="bottom right")

    fig.update_layout(
        title=f'FinLab Strategy Performance ({self.start_date}~{self.end_date})',
        legend=dict(x=0.029, y=1.038, font_size=12),
        margin=dict(l=100, r=20, t=70, b=70),
        paper_bgcolor='rgb(248, 248, 255)',
        plot_bgcolor='rgb(248, 248, 255)',
        xaxis_title="return(%)",
    )

    return fig