4. HistoryPanel Class

History Data Class HistoryPanel:

HistoryPanel Data Structure and Slicing

HistoryPanel is essentially a three-dimensional numpy.ndarray, with the three axes representing:

  • axis 0 / levels: instrument dimension; each level corresponds to a stock or an index, and the label list is shares;

  • axis 1 / rows: time dimension; each row corresponds to a point in time, and the label list is hdates;

  • axis 2 / columns: historical data type dimension; each column corresponds to a data type, and the label list is htypes.

With these three axis labels, you can flexibly slice a HistoryPanel using square brackets []. The basic rule is [htype_slicer, share_slicer, date_slicer]; when dimensions are omitted, the single-segment form (e.g., hp['close']) still returns a sub-HistoryPanel (with axis labels). For a raw matrix, use .values / .to_numpy().

The time axis (the third axis) also supports: a single pandas.Timestamp, a list of time labels, a 1D bool list of length L = len(hdates), or a 1D numpy bool array; the read-only property hp.loc[key] is equivalent to hp[:, :, key]. A grid-level (M, L, N) boolean mask is not part of the loc / third-axis indexing semantics; use where() instead.

Typical writing example:

hp['close']                       # 所有标的的收盘价
hp['close,open,high']            # 所有标的的多种价量数据
hp[:, '000300.SH']               # 单一标的的全部历史数据
hp['close:high', ['000300.SH', '000500.SH'], '20100101:20101231']
                                 # 多标的、数据类型与时间区间联合切片
hp.loc[0:5]                       # 与 hp[:, :, 0:5] 等价,按时间轴截取
class qteasy.HistoryPanel(values: Optional[ndarray] = None, levels=None, rows=None, columns=None)[source]

In qteasy, it is a three-dimensional data container used to centrally manage historical data across multiple instruments, multiple time points, and multiple data types.

HistoryPanel is essentially a three-dimensional numpy.ndarray, and the three axes represent the instrument (shares) and time

(hdates) and historical data types (htypes), supporting flexible slicing and relabeling along any axis, as well as mutual conversion with

pandas DataFrame, and serving as the data container for get_history_data and the visualization stack

the core bridge (e.g., between HistoryPanel.plot() and qt.candle).

Indexing and array export: __getitem__ always returns a sub-HistoryPanel with correct axis labels; when you need a raw ndarray, use .values or .to_numpy(copy=...). In-place assignment to a single column panel['column_name'] = value is implemented by __setitem__ (only for non-empty panels, and only for str keys). The value is broadcast to (number_of_shares, time_length) and stored as float64; it overwrites an existing column or appends a new one. For semantics when a sub-panel shares the buffer with its parent, see the docs for __getitem__ / subpanel / __setitem__.

Ergonomics-oriented API: column names that are valid Python identifiers and exist in htypes can be accessed read-only as attributes (e.g. panel.close, equivalent to panel['close']); comparison operations (e.g. panel.close > panel.open) return a numpy boolean array; panel.loc[key] is equivalent to panel[:, :, key], filtering only along the time axis (it does not accept a 3D mask like where). User docs: the Sphinx HistoryPanel page and the tutorial “Using HistoryPanel to manipulate and analyze historical data” (§6 and §6.1).

For a more detailed structural description (axis labels, slicing examples, label management, etc.), see the relevant section in the documentation “HistoryPanel class”.

__eq__(other: Any) Any[source]

Element-wise self == other; unsupported types return NotImplemented.

Parameters:

other (Any) – Right operand.

Returns:

A bool array when comparable; otherwise NotImplemented.

Return type:

numpy.ndarray or NotImplemented

__ge__(other: Any) ndarray[source]

Equivalent to elementwise comparison of self and other using ge from the operator module; returns a numpy.ndarray with dtype bool (not a sub-panel).

Parameters:

other (Any) – Right operand; semantics are the same as __lt__().

Returns:

Boolean result array.

Return type:

numpy.ndarray

__getattr__(name: str) Any[source]

Resolve a valid identifier column name as self[name] (read-only); for non-identifiers or unknown column names, use bracket indexing.

For column assignment, still use hp['col'] = ...; it does not align with pandas’ attribute-based write path.

Parameters:

name (str) – Attribute name; it must be a valid Python identifier to possibly correspond to an htypes column (non-empty panel).

Returns:

A sub-panel identical to self[name]; on an empty panel, delegates to __getitem__ and returns an empty sub-panel.

Return type:

HistoryPanel

Raises:

AttributeError – An invalid identifier, or a column name that does not exist in the current panel (in English, prompting the use of bracket indexing).

Notes

Existing method names / descriptors (e.g. where, values) take precedence over column names: columns with the same name must still be accessed as hp['where'] and the like. Non-identifier column names (e.g. close|b) cannot use dot access.

Examples

>>> import pandas as pd
>>> import numpy as np
>>> hp = HistoryPanel(
...     np.arange(24, dtype=float).reshape(2, 3, 4),
...     levels=['A', 'B'],
...     rows=pd.date_range('2020-01-01', periods=3),
...     columns=['a', 'b', 'c', 'd'],
... )
>>> np.allclose(hp.a.values, hp['a'].values)
True
__getitem__(keys=None) HistoryPanel[source]

Slice along the three axes htypes / shares / hdates, returning a sub-HistoryPanel with correct axis labels.

The first slice is the data type (htypes), the second is the instrument (shares), and the third is time (hdates); if omitted, that axis selects all. If you need a bare ndarray, use sub.values or sub.to_numpy(). A subpanel’s values may share memory with the parent panel (NumPy view rules); if you need an independent copy, use subpanel(..., copy=True) or sub.copy().

When appending a new column on the parent object via __setitem__, the entire values block of the parent panel will be replaced: by default, a subpanel with copy=False will not show the new column name, and its values may still point to the old array before the column expansion; the sub-object obtained by subpanel(copy=True) is not affected. When overwriting an existing column on the parent panel, the sliced data shared with the subview will be updated along with the parent buffer (as long as it is still a view on the same underlying block).

For an empty panel (is_empty), indexing with any key returns an empty HistoryPanel.

Notes

Time axis (the third segment ``hdates``) In addition to slice / integers / interval strings, it also supports: a single time label that can be found in the rows dict (e.g. pandas.Timestamp), a list of time labels, and a 1D bool list or 1D numpy.ndarray (boolean dtype) with length equal to row_count; consistent with the key accepted by loc. Grid-level (M, L, N) boolean arrays are not used as third-axis indices; please use where().

Parameters:

keys (list, tuple, slice, str, int or None) – Slice key; the 3-tuple (htypes, shares, hdates) is consistent with historical behavior.

Returns:

Sub-panel; to get the matrix, use its .values / .to_numpy().

Return type:

HistoryPanel

Examples

>>> hp = HistoryPanel(np.array([[[10, 20, 30, 40, 50]]*10]*3),
...                   levels=['000001', '000002', '000003'],
...                   rows=pd.date_range('2015-01-05', periods=10),
...                   columns=['open', 'high', 'low', 'close', 'volume'])
>>> sub = hp['close']
>>> isinstance(sub, HistoryPanel)
True
>>> sub.shape
(3, 10, 1)
>>> sub.htypes
['close']
>>> np.all(sub.values == 40)
True
__gt__(other: Any) ndarray[source]

Equivalent to elementwise comparison of self and other using gt from the operator module; returns a numpy.ndarray with dtype bool (not a sub-panel).

Parameters:

other (Any) – Right operand; semantics are the same as __lt__().

Returns:

Boolean result array.

Return type:

numpy.ndarray

__le__(other: Any) ndarray[source]

Equivalent to elementwise comparison of self and other using le from the operator module; returns a numpy.ndarray with dtype bool (not a subpanel).

Parameters:

other (Any) – Right operand; semantics are the same as __lt__().

Returns:

Boolean result array.

Return type:

numpy.ndarray

__lt__(other: Any) ndarray[source]

Equivalent to elementwise comparison of self and other using lt from the operator module; returns a numpy.ndarray with dtype bool (not a subpanel).

Parameters:

other (Any) – A scalar, a broadcastable ndarray, or another HistoryPanel (must satisfy the alignment rules).

Returns:

Boolean result array.

Return type:

numpy.ndarray

Raises:
  • TypeError – Unsupported operand type(s) (in English).

  • ValueError – Raised when the two panels cannot be aligned or broadcast according to the rules (in English).

__ne__(other: Any) Any[source]

Elementwise self != other; unsupported types return NotImplemented.

Parameters:

other (Any) – Right operand.

Returns:

A bool array when comparable; otherwise NotImplemented.

Return type:

numpy.ndarray or NotImplemented

__setitem__(key: Any, value: Any) None[source]

Append a column in place by column name, or overwrite an existing column (the third axis of htypes).

Only accepts a runtime non-empty string key; multi-column batch assignment is provided by later APIs such as assign. value will be broadcast to (share count, time length) and persisted as float64; existing column names are silently overwritten, with semantics aligned with pandas single-column assignment. Appending a new column on the parent panel will replace the entire values block: subviews from subpanel(copy=False) / __getitem__ usually cannot see the new column and may still point to the old buffer; subpanel(..., copy=True) and to_numpy(copy=True) are not affected. When the parent overwrites an existing column, subviews that share the underlying block with the parent will be updated along with the parent.

Parameters:
  • key (Any) – Column name (htype). Must be str; non-str raises TypeError, and an empty string raises ValueError (English message).

  • value (Any) – A numeric value that can be np.asarray’d and broadcast to (M, L) (scalar, (M, L), (M, L, 1), etc.).

Returns:

Modifies this object in place; returns nothing.

Return type:

None

Raises:
  • TypeError – Raised when key is not str (English message).

  • ValueError – Raised when the panel is empty, key is an empty string, or value cannot be broadcast to (M, L) (English message).

Examples

>>> hp = HistoryPanel(np.ones((2, 5, 2)), levels=['A', 'B'],
...                   rows=pd.date_range('2020-01-01', periods=5),
...                   columns=['open', 'close'])
>>> hp['twice_close'] = hp['close'].values * 2
>>> 'twice_close' in hp.htypes
True
>>> hp['const'] = 0.5
>>> np.all(hp.values[:, :, hp.htypes.index('const')] == 0.5)
True
as_type(dtype)[source]

Convert the data type of the HistoryPanel to dtype type, dtype can only be ‘float’ or ‘int’

Parameters:

dtype (str, {'float', 'int'}) – Data type to be converted to

Return type:

self

Raises:

AssertionError – If the input data type is incorrect or if other data types are input other than float/int

candle(*args, **kwargs)[source]

Plot a candlestick chart based on the current HistoryPanel data (already handled uniformly by plot()).

Notes

  • For the new visualization, it is recommended to call HistoryPanel.plot() directly, and use htypes / layout to control whether to output chart types such as candlesticks, volume, etc.

  • Internally, this method delegates to the unified entry point of the visualization submodule. Its behavior remains consistent with plot(), and it exists only as a semantic alias.

property column_count

Get the number of columns in the HistoryPanel or the number of historical data

property columns

Return a dict representing the historical data of HistoryPanel, mapping the historical data to column indices. This makes it easier for internal slicing of the data by stock code.

copy(deep: bool = True) HistoryPanel[source]

Copy and create a new HistoryPanel object.

Returns a deep copy by default, meaning the new object and the original object do not affect each other’s underlying values array; when you need to match NumPy’s view semantics and share underlying data in performance-sensitive scenarios, set deep=False.

Parameters:

deep (bool, default True) – Whether to deep-copy the underlying numeric array values: - True: deep copy; modifying the copy does not affect the original object; - False: shallow copy (shares the underlying array); modifying the copy will synchronously affect the original object.

Returns:

The new copied object; axis labels (shares/hdates/htypes) are the same as those of the original object.

Return type:

HistoryPanel

Examples

>>> import numpy as np
>>> import pandas as pd
>>> from qteasy import HistoryPanel
>>> hp = HistoryPanel(
...     np.arange(12, dtype=float).reshape(2, 3, 2),
...     levels=['A', 'B'],
...     rows=pd.date_range('2020-01-01', periods=3),
...     columns=['close', 'open'],
... )
>>> hp
share 0, label: A
            close  open
2020-01-01    0.0   1.0
2020-01-02    2.0   3.0
2020-01-03    4.0   5.0
share 1, label: B
            close  open
2020-01-01    6.0   7.0
2020-01-02    8.0   9.0
2020-01-03   10.0  11.0
>>> hp2 = hp.copy()  # deep=True
>>> hp2.values[0, 0, 0] = -1.0
>>> hp2
share 0, label: A
            close  open
2020-01-01   -1.0   1.0
2020-01-02    2.0   3.0
2020-01-03    4.0   5.0
share 1, label: B
            close  open
2020-01-01    6.0   7.0
2020-01-02    8.0   9.0
2020-01-03   10.0  11.0
>>> hp
share 0, label: A
            close  open
2020-01-01    0.0   1.0
2020-01-02    2.0   3.0
2020-01-03    4.0   5.0
share 1, label: B
            close  open
2020-01-01    6.0   7.0
2020-01-02    8.0   9.0
2020-01-03   10.0  11.0
>>> hp3 = hp.copy(deep=False)
>>> hp3.values[0, 0, 0] = -2.0
>>> hp3
share 0, label: A
            close  open
2020-01-01   -2.0   1.0
2020-01-02    2.0   3.0
2020-01-03    4.0   5.0
share 1, label: B
            close  open
2020-01-01    6.0   7.0
2020-01-02    8.0   9.0
2020-01-03   10.0  11.0
>>> hp
share 0, label: A
            close  open
2020-01-01   -2.0   1.0
2020-01-02    2.0   3.0
2020-01-03    4.0   5.0
share 1, label: B
            close  open
2020-01-01    6.0   7.0
2020-01-02    8.0   9.0
2020-01-03   10.0  11.0
ffill(init_val=nan)[source]

Fill in missing values forward, when there are missing values in historical data, use the most recent valid data before the missing value to fill in the missing value

Parameters:

init_val (float, 如果Nan值出现在第一行时,没有前序有效数据,则使用这个值来填充,默认为np.nan) –

Returns:

out

Return type:

HistoryPanel, 填充后的HistoryPanel对象

Examples

>>> hp = HistoryPanel(np.array([[[1, 2, 3], [4, np.nan, 6]], [[np.nan, 8, 9], [np.nan, np.nan, 12]]]),
...                   levels=['000001', '000002'], rows=['2015-01-01', '2015-01-02'],
...                   columns=['open', 'high', 'low'])
>>> hp
share 0, label: 000001
            open  high  low
2015-01-01   1.0   2.0  3.0
2015-01-02   4.0   NaN  6.0
share 1, label: 000002
            open  high   low
2015-01-01   NaN   8.0   9.0
2015-01-02   NaN   NaN  12.0
>>> hp.ffill()
share 0, label: 000001
            open  high  low
2015-01-01   1.0   2.0  3.0
2015-01-02   4.0   2.0  6.0
share 1, label: 000002
            open  high   low
2015-01-01   NaN   8.0   9.0
2015-01-02   NaN   8.0  12.0
>>> hp.ffill(init_val=3)
share 0, label: 000001
            open  high  low
2015-01-01   1.0   2.0  3.0
2015-01-02   4.0   2.0  6.0
share 1, label: 000002
            open  high   low
2015-01-01   3.0   8.0   9.0
2015-01-02   3.0   8.0  12.0
fillinf(with_val: Union[int, float])[source]

Use with_value to fill all inf values in the HistoryPanel

Parameters:

with_val (float or int) – Filling value

Returns:

out

Return type:

HistoryPanel, 填充后的HistoryPanel对象

fillna(with_val: Union[int, float])[source]

Nan values in the HistoryPanel are filled with with_value

Parameters:

with_val (float or int) – Filling value

Returns:

out

Return type:

HistoryPanel, 填充后的HistoryPanel对象

flatten(along=None)[source]

Same as HistoryPanel.flatten_to_dataframe()

Parameters:

along (str, {'col', 'row', 'column'} Default: 'row') – Flatten each layer of the HistoryPanel, along the row or column direction, ‘col’ or ‘column’ means flatten along the column direction, ‘row’ means flatten along the row direction

Return type:

pandas.DataFrame

Examples

>>> hp = HistoryPanel(np.array([[[12.3, 12.5, 1020010], [12.6, 13.2, 1020020]],
...                                    [[2.3, 2.5, 20010], [2.6, 3.2, 20020]]]),
...                          levels=['000300', '000001'],
...                          rows=['2020-01-01', '2020-01-02'],
...                          columns=['close', 'open', 'vol'])
>>> hp
share 0, label: 000300
            close  open        vol
2020-01-01   12.3  12.5  1020010.0
2020-01-02   12.6  13.2  1020020.0
share 1, label: 000001
            close  open      vol
2020-01-01    2.3   2.5  20010.0
2020-01-02    2.6   3.2  20020.0
>>> hp.flatten(along='col')
           000300                  000001
            close  open        vol  close open      vol
2020-01-01   12.3  12.5  1020010.0    2.3  2.5  20010.0
2020-01-02   12.6  13.2  1020020.0    2.6  3.2  20020.0
>>> hp.flatten(along='row')
                   close  open        vol
000300 2020-01-01   12.3  12.5  1020010.0
       2020-01-02   12.6  13.2  1020020.0
000001 2020-01-01    2.3   2.5    20010.0
       2020-01-02    2.6   3.2    20020.0
flatten_to_dataframe(along='row')[source]

Flatten a HistoryPanel into a DataFrame

The multi-layer data of the HistoryPanel will be “flattened” to the columns of the DataFrame, becoming a MultiIndex, or the multi-layer data will be flattened to the rows of the DataFrame, also becoming a MultiIndex. Whether it is flattened to rows or columns depends on the along parameter

Parameters:

along (str, {'col', 'row', 'column'} Default: 'row') – Flatten each layer of the HistoryPanel, along the row or column direction, ‘col’ or ‘column’ means flatten along the column direction, ‘row’ means flatten along the row direction

Return type:

pandas.DataFrame

Examples

>>> hp = HistoryPanel(np.array([[[12.3, 12.5, 1020010], [12.6, 13.2, 1020020]],
...                                    [[2.3, 2.5, 20010], [2.6, 3.2, 20020]]]),
...                          levels=['000300', '000001'],
...                          rows=['2020-01-01', '2020-01-02'],
...                          columns=['close', 'open', 'vol'])
>>> hp
share 0, label: 000300
            close  open        vol
2020-01-01   12.3  12.5  1020010.0
2020-01-02   12.6  13.2  1020020.0
share 1, label: 000001
            close  open      vol
2020-01-01    2.3   2.5  20010.0
2020-01-02    2.6   3.2  20020.0
>>> hp.flatten_to_dataframe(along='col')
           000300                  000001
            close  open        vol  close open      vol
2020-01-01   12.3  12.5  1020010.0    2.3  2.5  20010.0
2020-01-02   12.6  13.2  1020020.0    2.6  3.2  20020.0
>>> hp.flatten_to_dataframe(along='row')
                   close  open        vol
000300 2020-01-01   12.3  12.5  1020010.0
       2020-01-02   12.6  13.2  1020020.0
000001 2020-01-01    2.3   2.5    20010.0
       2020-01-02    2.6   3.2    20020.0
flattened_head(row_count=5)[source]

Return the first few rows of the HistoryPanel in the form of a multi-index DataFrame, defaulting to five rows

Parameters:

row_count (int, default 5) – Number of rows to print

Returns:

dataframe, multi-indexed by share and htype as columns, with only first row_count rows * , A dataframe with a multi-index of share and htype as columns, containing only the first row_count rows

Examples

>>> data = np.array([[[12.3, 12.5, 1020010], [12.6, 13.2, 1020020], [12.9, 13.0, 1020030],
...                   [12.3, 12.5, 1020040], [12.6, 13.2, 1020050], [12.9, 13.0, 1020060]],
...                  [[2.3, 2.5, 20010], [2.6, 2.8, 20020], [2.9, 3.0, 20030],
...                   [2.3, 2.5, 20040], [2.6, 2.8, 20050], [2.9, 3.0, 20060]]])
>>> hp = HistoryPanel(values=data,
...                          levels=['000300', '000001'],
...                          rows=pd.date_range('2020-01-01', periods=6),
...                          columns=['close', 'open', 'vol'])
>>> hp
share 0, label: 000300
            close,  open,   vol
2020-01-01  12.3,   12.5,   1020010
2020-01-02  12.6,   13.2,   1020020
2020-01-03  12.9,   13.0,   1020030
2020-01-04  12.3,   12.5,   1020040
2020-01-05  12.6,   13.2,   1020050
2020-01-06  12.9,   13.0,   1020060
share 1, label: 000001:
            close,  open,   vol
2020-01-01  2.3,    2.5,    20010
2020-01-02  2.6,    3.2,    20020
2020-01-03  2.9,    3.0,    20030
2020-01-04  2.3,    2.5,    20040
2020-01-05  2.6,    3.2,    20050
2020-01-06  2.9,    3.0,    20060
>>> hp.flattened_head(3)
            000300                  000001
            close,  open,   vol,    close,  open,   vol
2020-01-01  12.3,   12.5,   1020010 2.3,    2.5,    20010
2020-01-02  12.6,   13.2,   1020020 2.6,    3.2,    20020
2020-01-03  12.9,   13.0,   1020030 2.9,    3.0,    20030
flattened_tail(row_count=5)[source]

Return the last few rows of the HistoryPanel in the form of a multi-index DataFrame, defaulting to five rows

Parameters:

row_count (int, default 5) – Number of rows to print

Returns:

  • dataframe, multi-indexed by share and htype as columns, with only last row_count rows

  • 一个dataframe,以share和htype为列的多重索引,只包含后row_count行

Examples

>>> data = np.array([[[12.3, 12.5, 1020010], [12.6, 13.2, 1020020], [12.9, 13.0, 1020030],
...                   [12.3, 12.5, 1020040], [12.6, 13.2, 1020050], [12.9, 13.0, 1020060]],
...                  [[2.3, 2.5, 20010], [2.6, 2.8, 20020], [2.9, 3.0, 20030],
...                   [2.3, 2.5, 20040], [2.6, 2.8, 20050], [2.9, 3.0, 20060]]])
>>> hp = HistoryPanel(values=data,
...                          levels=['000300', '000001'],
...                          rows=pd.date_range('2020-01-01', periods=6),
...                          columns=['close', 'open', 'vol'])
>>> hp
share 0, label: 000300
            close,  open,   vol
2020-01-01  12.3,   12.5,   1020010
2020-01-02  12.6,   13.2,   1020020
2020-01-03  12.9,   13.0,   1020030
2020-01-04  12.3,   12.5,   1020040
2020-01-05  12.6,   13.2,   1020050
2020-01-06  12.9,   13.0,   1020060
share 1, label: 000001:
            close,  open,   vol
2020-01-01  2.3,    2.5,    20010
2020-01-02  2.6,    3.2,    20020
2020-01-03  2.9,    3.0,    20030
2020-01-04  2.3,    2.5,    20040
2020-01-05  2.6,    3.2,    20050
2020-01-06  2.9,    3.0,    20060
>>> hp.flattened_tail(3)
            000300                  000001
            close,  open,   vol,    close,  open,   vol
2020-01-04  12.3,   12.5,   1020040 2.3,    2.5,    20040
2020-01-05  12.6,   13.2,   1020050 2.6,    3.2,    20050
2020-01-06  12.9,   13.0,   1020060 2.9,    3.0,    20060
property hdate_count

Get the number of historical data types in the HistoryPanel

property hdates

Get the list of historical date timestamps in the HistoryPanel

head(row_count=5)[source]

Return the first few rows of the HistoryPanel, defaulting to five rows

Parameters:

row_count (int, default 5) – Number of rows to print

Returns:

dataframe, multi-indexed by share and htype as columns, with only first row_count rows * , A dataframe with a multi-index of share and htype as columns, containing only the first row_count rows

Examples

>>> data = np.array([[[12.3, 12.5, 1020010], [12.6, 13.2, 1020020], [12.9, 13.0, 1020030],
...                   [12.3, 12.5, 1020040], [12.6, 13.2, 1020050], [12.9, 13.0, 1020060]],
...                  [[2.3, 2.5, 20010], [2.6, 2.8, 20020], [2.9, 3.0, 20030],
...                   [2.3, 2.5, 20040], [2.6, 2.8, 20050], [2.9, 3.0, 20060]]])
>>> hp = HistoryPanel(values=data,
...                          levels=['000300', '000001'],
...                          rows=pd.date_range('2020-01-01', periods=6),
...                          columns=['close', 'open', 'vol'])
>>> hp
share 0, label: 000300
            close,  open,   vol
2020-01-01  12.3,   12.5,   1020010
2020-01-02  12.6,   13.2,   1020020
2020-01-03  12.9,   13.0,   1020030
2020-01-04  12.3,   12.5,   1020040
2020-01-05  12.6,   13.2,   1020050
2020-01-06  12.9,   13.0,   1020060
share 1, label: 000001:
            close,  open,   vol
2020-01-01  2.3,    2.5,    20010
2020-01-02  2.6,    3.2,    20020
2020-01-03  2.9,    3.0,    20030
2020-01-04  2.3,    2.5,    20040
2020-01-05  2.6,    3.2,    20050
2020-01-06  2.9,    3.0,    20060
>>> hp.head(3)
share 0, label: 000300
            close,  open,   vol,
2020-01-01  12.3,   12.5,   1020010
2020-01-02  12.6,   13.2,   1020020
2020-01-03  12.9,   13.0,   1020030
share 1, label: 000001
            close,  open,   vol
2020-01-01  2.3,    2.5,    20010
2020-01-02  2.6,    3.2,    20020
2020-01-03  2.9,    3.0,    20030
property htype_count

Get the number of historical data types in the HistoryPanel

property htypes

Get the list of historical data types in the HistoryPanel

info()[source]

Print the information of this HistoryPanel object

Return type:

None

Examples

>>> hp = HistoryPanel(np.array([[[10, 20, 30, 40, 50]]*10]*3),
...                          levels=['000001', '000002', '000003'],
...                          rows=pd.date_range('2015-01-05', periods=10),
...                          columns=['open', 'high', 'low', 'close', 'volume'])
>>> hp.info()
<class 'qteasy.history.HistoryPanel'>
History Panel at 0x12215a850
Datetime Range: 10 entries, 2015-01-05 00:00:00 to 2015-01-14 00:00:00
Historical Data Types (total 5 data types):
['open', 'high', 'low', 'close', 'volume']
Shares (total 3 shares):
['000001', '000002', '000003']
non-null values for each share and data type:
        open  high  low  close  volume
000001    10    10   10     10      10
000002    10    10   10     10      10
000003    10    10   10     10      10
memory usage: 1344 bytes
property is_empty

Check if the HistoryPanel is empty

isegment(start_index=None, end_index=None)[source]
Get a segment of the HistoryPanel, start_index and end_index are both int numbers, representing the date sequence number, return

Returns all data between the two sequence numbers, the type returned is a HistoryPanel containing all share and htypes data

Parameters:
  • start_index (pd.TimeStamp) – Start date index

  • end_index (pd.TimeStamp) – End date index

Returns:

out – A HistoryPanel containing all share and htypes data between start_date and end_date

Return type:

HistoryPanel

Examples

>>> hp = HistoryPanel(np.array([[[10, 20, 30, 40, 50]]*10]*3),
...                          levels=['000001', '000002', '000003'],
...                          rows=pd.date_range('2015-01-05', periods=10),
...                          columns=['open', 'high', 'low', 'close', 'volume'])
>>> hp.isegment(2, 5)
share 0, label: 000100
            open  high  low  close  volume
2015-01-07    10    20   30     40      50
2015-01-08    10    20   30     40      50
2015-01-09    10    20   30     40      50
share 1, label: 000200
            open  high  low  close  volume
2015-01-07    10    20   30     40      50
2015-01-08    10    20   30     40      50
2015-01-09    10    20   30     40      50
share 2, label: 000300
            open  high  low  close  volume
2015-01-07    10    20   30     40      50
2015-01-08    10    20   30     40      50
2015-01-09    10    20   30     40      50
join(other, same_shares: bool = False, same_htypes: bool = False, same_hdates: bool = False, fill_value: float = nan)[source]

Connect one HistoryPanel object with another HistoryPanel object to generate a new HistoryPanel:

The row, column, and layer labels of the new HistoryPanel are the union of the row, column, and layer labels of the two original HistoryPanels. In other words, the row, column, and layer labels of the new HistoryPanel completely contain the corresponding labels of the two HistoryPanel objects.

Parameters:
  • other (HistoryPanel) – The other HistoryPanel to be merged

  • same_shares (bool, Default False) – If the shares of the two HPs are the same, the label merging of the shares dimension can be omitted to save time. Default is False,

  • same_htypes (bool, Default False) – If the htypes of the two HPs are the same, the label merging of the htypes dimension can be omitted to save time. Default is False,

  • same_hdates (bool, Default False) – If the hdates of the two HPs are the same, the label merging of the hdates dimension can be omitted to save time. Default is False,

  • fill_value (float, Default np.nan) – Filling value for empty data, when the combined HP has empty data, what value should be used to fill it, default is np.nan

Return type:

HistoryPanel, 一个新的History Panel对象

Examples

>>> # 如果两个HistoryPanel中包含标签相同的数据,那么新的HistoryPanel中将包含调用join方法的HistoryPanel对象的相应数据。例如:
>>> hp1 = HistoryPanel(np.array([[[8, 9, 9], [7, 5, 5], [4, 8, 4], [1, 0, 7], [8, 7, 9]],
...                                     [[2, 3, 3], [5, 4, 6], [2, 8, 7], [3, 3, 4], [8, 8, 7]]]),
...                           levels=['000200', '000300'],
...                           rows=pd.date_range('2020-01-01', periods=5),
...                           columns=['close', 'open', 'high'])
>>> hp2 = HistoryPanel(np.array([[[8, 9, 9], [7, 5, 5], [4, 8, 4], [1, 0, 7], [8, 7, 9]],
...                                     [[2, 3, 3], [5, 4, 6], [2, 8, 7], [3, 3, 4], [8, 8, 7]]]),
...                           levels=['000400', '000500'],
...                           rows=pd.date_range('2020-01-01', periods=5),
...                           columns=['close', 'open', 'high'])
>>> hp1
share 0, label: 000200
            close  open  high
2020-01-01      8     9     9
2020-01-02      7     5     5
2020-01-03      4     8     4
2020-01-04      1     0     7
2020-01-05      8     7     9
share 1, label: 000300
            close  open  high
2020-01-01      2     3     3
2020-01-02      5     4     6
2020-01-03      2     8     7
2020-01-04      3     3     4
2020-01-05      8     8     7
>>> hp2
share 0, label: 000400
            close  open  high
2020-01-01      8     9     9
2020-01-02      7     5     5
2020-01-03      4     8     4
2020-01-04      1     0     7
2020-01-05      8     7     9
share 1, label: 000500
            close  open  high
2020-01-01      2     3     3
2020-01-02      5     4     6
2020-01-03      2     8     7
2020-01-04      3     3     4
2020-01-05      8     8     7
>>> hp1.join(hp2)
share 0, label: 000200
len()[source]

Length of the HistoryPanel object, i.e. number of dates

Returns:

Number of dates

Return type:

int

Examples

>>> hp = HistoryPanel(np.array([[[10, 20, 30, 40, 50]]*10]*3),
...                          levels=['000001', '000002', '000003'],
...                          rows=pd.date_range('2015-01-05', periods=10),
...                          columns=['open', 'high', 'low', 'close', 'volume'])
>>> hp.len()
10
property level_count

Number of stocks or asset varieties in the HistoryPanel

property levels

Return the layer-label dict of HistoryPanel (a mapping from stock code to layer index).

Within the library, it can be combined with values for layer-wise indexing; externally, prefer using square-bracket slicing to access data for each layer.

plot(shares: Optional[Union[str, Iterable[str]]] = None, layout: str = 'auto', interactive: bool = False, highlight: Optional[Any] = None, plotly_backend_app: str = 'auto', group_titles: Optional[Sequence[str]] = None, max_shares_per_figure: int = 5, page: int = 1, **kwargs)[source]

Automatically select the chart type based on the existing htypes and shares in HistoryPanel and plot the chart.

This method only consumes existing data and performs no new computations. The chart type is determined by an internal registry based on htypes (e.g., OHLC→K-line, vol→volume, three MACD columns→MACD chart, otherwise→line chart). It supports single-instrument and multi-instrument overlay/stack layouts, as well as matplotlib-based static plots and Plotly-based interactive charts.

Parameters:
  • shares (str or sequence of str, optional) – The subset of tickers to include in the plot; by default, all shares in HistoryPanel are used.

  • layout ({'overlay', 'stack', 'auto'}, default 'auto') – Multi-instrument layout mode; ‘overlay’ overlays within the same group, ‘stack’ shows multiple groups in separate rows, and when ‘auto’, HP_OVERLAY_GROUP_SHARE_COUNT uses overlay only for that many instruments, and uses stack for the rest.

  • interactive (bool, default False) – When True, use the Plotly interactive backend (requires installing plotly and anywidget/ipywidgets); when False, use the matplotlib static backend.

  • highlight (dict or str, optional) – Highlight configuration: can be {'condition': 'max'|'min' or a boolean array, 'style': {...}}, or shorthand as ‘max’ / ‘min’.

  • plotly_backend_app ({'auto', 'FigureWidget', 'html'}, default 'auto') – Only effective when interactive=True. In a Notebook, choose the Plotly rendering mode: 'auto' prefers FigureWidget and falls back to an HTML wrapper on failure; 'FigureWidget' forces the Widget and raises on failure; 'html' forces the HTML wrapper and raises on failure. In non-Notebook script environments, 'auto' may still return the raw Figure.

  • max_shares_per_figure (int, default 5) – The maximum number of shares to display in a single chart. When the requested number of shares exceeds this value, it will be split into pages; you can use the page parameter to choose which page to display.

  • page (int, default 1) – The page number to display (1-based). When the number of shares exceeds max_shares_per_figure, page=1 is page 1, page=2 is page 2, and so on.

  • **kwargs – Reserved extension parameters; not used in the current version.

Returns:

When interactive=False, returns a matplotlib Figure; when interactive=True, returns a FigureWidget, an HTML wrapper, or the raw Figure depending on plotly_backend_app.

Return type:

matplotlib.figure.Figure or plotly.graph_objs.FigureWidget or _PlotlyFigureWrapper

Notes

When the registry outputs a full OHLC candlestick main chart, the top OHLC summary area is shown: for static charts it is fixed to the summary of the last bar on the timeline; for interactive charts it initially matches that, and updates to the clicked bar after you click a bar (the user-facing summary text is in English). If there is no candlestick main chart (e.g., only a close line), this summary area is not shown.

Examples

>>> import qteasy as qt
>>> hp = qt.get_history_data(htype_names='open, high, low, close, vol',
...                          shares='000300.SH', rows=200)
>>> fig = hp.plot()
>>> fig_interactive = hp.plot(interactive=True, highlight='max')

See also

qt.get_kline

Fetch K-line data and optionally set as_panel=True to get a HistoryPanel.

re_label(shares: Optional[Union[str, list]] = None, htypes: Optional[Union[str, list]] = None, hdates: Optional[Union[str, list]] = None) None[source]

Reassign layer, row, and column labels to the HistoryPanel object

Parameters:
  • shares (str or list of str) – Stock list

  • htypes (str or list of str) – Data type list

  • hdates (str or list of str) – Date list

Return type:

None

Examples

>>> hp = HistoryPanel(np.array([[[10, 20, 30, 40, 50]]*10]*3),
...                          levels=['000001', '000002', '000003'],
...                          rows=pd.date_range('2015-01-05', periods=10),
...                          columns=['open', 'high', 'low', 'close', 'volume'])
>>> hp.re_label(shares=['000100', '000200', '000300'], htypes=['typeA', 'typeB', 'typeC', 'typeD', 'typeE'])
>>> hp
share 0, label: 000100
            typeA  typeB  typeC  typeD  typeE
2015-01-05     10     20     30     40     50
2015-01-06     10     20     30     40     50
2015-01-07     10     20     30     40     50
2015-01-08     10     20     30     40     50
2015-01-09     10     20     30     40     50
2015-01-10     10     20     30     40     50
2015-01-11     10     20     30     40     50
2015-01-12     10     20     30     40     50
2015-01-13     10     20     30     40     50
2015-01-14     10     20     30     40     50
share 1, label: 000200
            typeA  typeB  typeC  typeD  typeE
2015-01-05     10     20     30     40     50
2015-01-06     10     20     30     40     50
2015-01-07     10     20     30     40     50
2015-01-08     10     20     30     40     50
2015-01-09     10     20     30     40     50
2015-01-10     10     20     30     40     50
2015-01-11     10     20     30     40     50
2015-01-12     10     20     30     40     50
2015-01-13     10     20     30     40     50
2015-01-14     10     20     30     40     50
share 2, label: 000300
            typeA  typeB  typeC  typeD  typeE
2015-01-05     10     20     30     40     50
2015-01-06     10     20     30     40     50
2015-01-07     10     20     30     40     50
2015-01-08     10     20     30     40     50
2015-01-09     10     20     30     40     50
2015-01-10     10     20     30     40     50
2015-01-11     10     20     30     40     50
2015-01-12     10     20     30     40     50
2015-01-13     10     20     30     40     50
2015-01-14     10     20     30     40     50
property row_count

Get the number of rows in the HistoryPanel

property rows

Return the date dictionary of the HistoryPanel. This dictionary links dates to row indices, so internally it can slice or access data faster.

Returns:

Date dictionary

Return type:

dict

segment(start_date=None, end_date=None)[source]
Get a date segment of the HistoryPanel, start_date and end_date are both date-type data, return

This returns all data between the two dates, the type returned is a HistoryPanel containing all share and htypes data

Parameters:
  • start_date (开始日期) –

  • end_date (结束日期) –

Returns:

out – A HistoryPanel containing all share and htypes data between start_date and end_date

Return type:

HistoryPanel

Examples

>>> hp = HistoryPanel(np.array([[[10, 20, 30, 40, 50]]*10]*3),
...                          levels=['000001', '000002', '000003'],
...                          rows=pd.date_range('2015-01-05', periods=10),
...                          columns=['open', 'high', 'low', 'close', 'volume'])
>>> hp.segment('2015-01-07', '2015-01-10')
share 0, label: 000100
            open  high  low  close  volume
2015-01-07    10    20   30     40      50
2015-01-08    10    20   30     40      50
2015-01-09    10    20   30     40      50
2015-01-10    10    20   30     40      50
share 1, label: 000200
            open  high  low  close  volume
2015-01-07    10    20   30     40      50
2015-01-08    10    20   30     40      50
2015-01-09    10    20   30     40      50
2015-01-10    10    20   30     40      50
share 2, label: 000300
            open  high  low  close  volume
2015-01-07    10    20   30     40      50
2015-01-08    10    20   30     40      50
2015-01-09    10    20   30     40      50
2015-01-10    10    20   30     40      50
property shape

Get the size of each dimension of the HistoryPanel

property share_count

Get the number of stocks or asset varieties in the HistoryPanel

property shares

Return the layer label of the HistoryPanel - stock list

slice(shares=None, htypes=None)[source]
Get a segment of the HistoryPanel for a stock or data type, shares and htypes can be a list or a comma-separated character

, indicating the type of stock or data to be obtained.

Parameters:
  • shares (str or list of str) – List of required stocks

  • htypes (str or list of str) – List of required data types

Returns:

out – A HistoryPanel containing the data of the stocks and data types specified in shares and htypes

Return type:

HistoryPanel

Examples

>>> hp = HistoryPanel(np.array([[[10, 20, 30, 40, 50]]*10]*3),
...                   levels=['000001', '000002', '000003'],
...                   rows=pd.date_range('2015-01-05', periods=10),
...                   columns=['open', 'high', 'low', 'close', 'volume'])
>>> hp.slice(shares='000001,000003', htypes='close, open')
share 0, label: 000001
            close  open
2015-01-05     40    10
2015-01-06     40    10
2015-01-07     40    10
2015-01-08     40    10
2015-01-09     40    10
2015-01-10     40    10
2015-01-11     40    10
2015-01-12     40    10
2015-01-13     40    10
2015-01-14     40    10
share 2, label: 000003
            close  open
2015-01-05     40    10
2015-01-06     40    10
2015-01-07     40    10
2015-01-08     40    10
2015-01-09     40    10
2015-01-10     40    10
2015-01-11     40    10
2015-01-12     40    10
2015-01-13     40    10
2015-01-14     40    10
slice_to_dataframe(htype: Optional[Union[str, int]] = None, share: Optional[Union[str, int]] = None, dropna: bool = False, inf_as_na: bool = False) DataFrame[source]

Convert the specified segment in the HistoryPanel object to a DataFrame

Specify htype or share, and convert the data slice corresponding to this htype or share into a DataFrame. Since the HistoryPanel object contains three-dimensional data, one of the htype or share parameters must be specified during conversion

Parameters:
  • htype (str or int,) – Indicates the data type slice that needs to generate a DataFrame. If this parameter is given, after locating the slice corresponding to the htype, all data of all stocks and dates corresponding to the htype will be converted into a DataFrame. If the type is str, it indicates the name of the htype, and if the type is int, it represents the column number where the htype is located

  • share (str or int,) – Indicates the stock code slice that needs to generate a DataFrame. If this parameter is given, after locating the slice corresponding to the share, all data of all data types and dates corresponding to the share will be converted into a DataFrame. If the type is str, it indicates the stock code, and if the type is int, it represents the layer number where the share is located

  • dropna (bool, Default False) – If True, remove NaN values

  • inf_as_na (bool, Default False) – If True, treat inf values as NaN values and remove them together. Invalid when dropna is False

Return type:

pandas.DataFrame

Examples

>>> hp = HistoryPanel(values=np.array([[[1, 2, np.nan], [4, 5, 6]],
...                                    [[7, 8, np.nan], [np.inf, 11, 12]]]),
...                   levels=['000001', '000002'],
...                   rows=['2019-01-01', '2019-01-02'],
...                   columns=['open', 'high', 'low']))
>>> hp
share 0, label: 000001
            open  high  low
2019-01-01   1.0   2.0  NaN
2019-01-02   4.0   5.0  NaN
share 1, label: 000002
            open  high   low
2019-01-01   7.0   8.0   9.0
2019-01-02   inf  11.0  12.0
>>> hp.slice_to_dataframe(htype='open')
000001  000002
2019-01-01  1.0  7.0
2019-01-02  4.0  inf
>>> hp.slice_to_dataframe(share='000001')
open  high  low
2019-01-01  1.0  2.0  NaN
2019-01-02  4.0  5.0  6.0
>>> hp.slice_to_dataframe(htype='low', dropna=True)
            000001  000002
2019-01-02     6.0    12.0
subpanel(htypes: Optional[Union[str, Sequence[str], slice, int, list]] = None, shares: Optional[Union[str, Sequence[str], slice, int, list]] = None, hdates: Optional[Union[str, slice, Sequence[Any], int, list]] = None, *, copy: bool = True) HistoryPanel[source]

Select a sub-panel along htypes / shares / hdates via keyword arguments to avoid confusion about the axis order of the triple.

None means select all on that axis. By default copy=True, producing a copy detached from the parent object’s data buffer; set copy=False for zero-copy (the sub-panel values may share memory with the parent panel). When the parent object’s __setitem__ appends a new column, it will replace the entire parent panel values block; a copy=False sub-panel usually will not automatically include the new column, and may still reference the buffer from before the column was added.

Parameters:
  • htypes (str, sequence, slice or int, optional) – Column (data type) selection; semantics are the same as the first segment of panel[htypes, ...].

  • shares (str, sequence, slice or int, optional) – Instrument-level selection; semantics are the same as the second segment of panel[:, shares, ...].

  • hdates (str, sequence, slice or int, optional) – Time-axis selection; semantics are the same as the third segment of panel[..., hdates].

  • copy (bool, default True) – When True, makes an array copy of the slicing result.

Returns:

A sub-panel formed by the selected axis subsets; empty input corresponds to an empty panel.

Return type:

HistoryPanel

Notes

Similar to slicing with copy=False in __getitem__: after the parent __setitem__ appends columns, a copy=False child object usually does not include the new columns; for a stable snapshot, keep copy=True (default).

tail(row_count=5)[source]

Return the last few rows of the HistoryPanel, defaulting to five rows

Parameters:

row_count (int, default 5) – Number of rows to print

Returns:

dataframe, multi-indexed by share and htype as columns, with only last row_count rows * , A dataframe with a multi-index of share and htype as columns, containing only the last row_count rows

Examples

>>> data = np.array([[[12.3, 12.5, 1020010], [12.6, 13.2, 1020020], [12.9, 13.0, 1020030],
...                   [12.3, 12.5, 1020040], [12.6, 13.2, 1020050], [12.9, 13.0, 1020060]],
...                  [[2.3, 2.5, 20010], [2.6, 2.8, 20020], [2.9, 3.0, 20030],
...                   [2.3, 2.5, 20040], [2.6, 2.8, 20050], [2.9, 3.0, 20060]]])
>>> hp = HistoryPanel(values=data,
...                          levels=['000300', '000001'],
...                          rows=pd.date_range('2020-01-01', periods=6),
...                          columns=['close', 'open', 'vol'])
>>> hp
share 0, label: 000300
            close,  open,   vol
2020-01-01  12.3,   12.5,   1020010
2020-01-02  12.6,   13.2,   1020020
2020-01-03  12.9,   13.0,   1020030
2020-01-04  12.3,   12.5,   1020040
2020-01-05  12.6,   13.2,   1020050
2020-01-06  12.9,   13.0,   1020060
share 1, label: 000001:
            close,  open,   vol
2020-01-01  2.3,    2.5,    20010
2020-01-02  2.6,    3.2,    20020
2020-01-03  2.9,    3.0,    20030
2020-01-04  2.3,    2.5,    20040
2020-01-05  2.6,    3.2,    20050
2020-01-06  2.9,    3.0,    20060
>>> hp.tail(3)
share 0, label: 000300
            close,  open,   vol
2020-01-04  12.3,   12.5,   1020040
2020-01-05  12.6,   13.2,   1020050
2020-01-06  12.9,   13.0,   1020060
share 1, label: 000001:
            close,  open,   vol
2020-01-04  2.3,    2.5,    20040
2020-01-05  2.6,    3.2,    20050
2020-01-06  2.9,    3.0,    20060
to_df_dict(by: str = 'share') dict[source]

Convert a HistoryPanel to a dict: keys are share or htype, and values are the corresponding pandas.DataFrame.

Parameters:

by (str, default 'share') – When set to 'share' / 'shares', split along the share axis: dict keys are stock tickers and values are the corresponding DataFrame; when set to 'htype' / 'htypes', split along the data-type axis: dict keys are historical data type names and values are the corresponding DataFrame.

Returns:

df_dict

Return type:

dict, {str: pandas.DataFrame}

Examples

>>> hp = HistoryPanel(np.random.randn(2, 3, 4),
...                   rows=['2020-01-01', '2020-01-02', '2020-01-03'],
...                   levels=['000001', '000002', '000003'],
...                   columns=['close', 'open', 'high', 'low'])
>>> hp
share 0, label: 000001
            close,  open,   high,   low
2020-01-01  0.1,    0.2,    0.3,    0.4
2020-01-02  0.5,    0.6,    0.7,    0.8
2020-01-03  0.9,    1.0,    1.1,    1.2
share 1, label: 000002
            close,  open,   high,   low
2020-01-01  1.1,    1.2,    1.3,    1.4
2020-01-02  1.5,    1.6,    1.7,    1.8
2020-01-03  1.9,    2.0,    2.1,    2.2
share 2, label: 000003
            close,  open,   high,   low
2020-01-01  2.1,    2.2,    2.3,    2.4
2020-01-02  2.5,    2.6,    2.7,    2.8
2020-01-03  2.9,    3.0,    3.1,    3.2
>>> hp.to_df_dict(by='share')
{'000001':
            close,  open,   high,   low
2020-01-01  0.1,    0.2,    0.3,    0.4
2020-01-02  0.5,    0.6,    0.7,    0.8
2020-01-03  0.9,    1.0,    1.1,    1.2
, '000002':
            close,  open,   high,   low
2020-01-01  1.1,    1.2,    1.3,    1.4
2020-01-02  1.5,    1.6,    1.7,    1.8
2020-01-03  1.9,    2.0,    2.1,    2.2
, '000003':
            close,  open,   high,   low
2020-01-01  2.1,    2.2,    2.3,    2.4
2020-01-02  2.5,    2.6,    2.7,    2.8
2020-01-03  2.9,    3.0,    3.1,    3.2
}
>>> hp.to_df_dict(by='htype')
{'close':
            000001,  000002,  000003
2020-01-01  0.1,     1.1,     2.1
2020-01-02  0.5,     1.5,     2.5
2020-01-03  0.9,     1.9,     2.9
, 'open':
            000001,  000002,  000003
2020-01-01  0.2,     1.2,     2.2
2020-01-02  0.6,     1.6,     2.6
2020-01-03  1.0,     2.0,     3.0
, 'high':
            000001,  000002,  000003
2020-01-01  0.3,     1.3,     2.3
2020-01-02  0.7,     1.7,     2.7
2020-01-03  1.1,     2.1,     3.1
, 'low':
            000001,  000002,  000003
2020-01-01  0.4,     1.4,     2.4
2020-01-02  0.8,     1.8,     2.8
2020-01-03  1.2,     2.2,     3.2
}
to_multi_index_dataframe(along=None)[source]

Same as HistoryPanel.flatten_to_dataframe()

Parameters:

along (str, {'col', 'row', 'column'} Default: 'row') – Flatten each layer of the HistoryPanel, along the row or column direction, ‘col’ or ‘column’ means flatten along the column direction, ‘row’ means flatten along the row direction

Return type:

pandas.DataFrame

Examples

>>> hp = HistoryPanel(np.array([[[12.3, 12.5, 1020010], [12.6, 13.2, 1020020]],
...                                    [[2.3, 2.5, 20010], [2.6, 3.2, 20020]]]),
...                          levels=['000300', '000001'],
...                          rows=['2020-01-01', '2020-01-02'],
...                          columns=['close', 'open', 'vol'])
>>> hp
share 0, label: 000300
            close  open        vol
2020-01-01   12.3  12.5  1020010.0
2020-01-02   12.6  13.2  1020020.0
share 1, label: 000001
            close  open      vol
2020-01-01    2.3   2.5  20010.0
2020-01-02    2.6   3.2  20020.0
>>> hp.to_multi_index_dataframe(along='col')
           000300                  000001
            close  open        vol  close open      vol
2020-01-01   12.3  12.5  1020010.0    2.3  2.5  20010.0
2020-01-02   12.6  13.2  1020020.0    2.6  3.2  20020.0
>>> hp.to_multi_index_dataframe(along='row')
                   close  open        vol
000300 2020-01-01   12.3  12.5  1020010.0
       2020-01-02   12.6  13.2  1020020.0
000001 2020-01-01    2.3   2.5    20010.0
       2020-01-02    2.6   3.2    20020.0
to_numpy(copy: bool = False) ndarray[source]

Return an ndarray with the same shape as values; use copy=True when you need an independent copy.

An empty panel returns a float array with shape (0, 0, 0). When non-empty, copy=False has the same semantics as numpy.asarray(self.values) and can share memory with the internal buffer. If you later append new columns to the parent object via __setitem__, the parent object will replace the entire underlying buffer; the array previously obtained with copy=False will not automatically include the new columns, and should no longer be regarded as an authoritative snapshot of the current panel.

Parameters:

copy (bool, default False) – If True, return a copy of the array; modifying the return value will not affect this object’s data.

Returns:

A 3D array with the same shape as values; (0, 0, 0) for an empty panel.

Return type:

numpy.ndarray

Examples

>>> import numpy as np
>>> import pandas as pd
>>> from qteasy.history import HistoryPanel
>>> hp = HistoryPanel(
...     np.arange(12, dtype=float).reshape(2, 3, 2),
...     levels=['A', 'B'],
...     rows=pd.date_range('2020-01-01', periods=3),
...     columns=['close', 'open'],
... )
>>> hp.to_numpy(copy=True)
array([[[ 0.,  1.],
        [ 2.,  3.],
        [ 4.,  5.]],

       [[ 6.,  7.],
        [ 8.,  9.],
        [10., 11.]]])
to_share_frame(share: Union[str, int]) DataFrame[source]

Slice all data types of a single stock in the HistoryPanel into a DataFrame.

This method is syntactic sugar for slice_to_dataframe(share=...). The returned DataFrame uses time as the index and all htypes as columns, making it suitable for single-stock, full-indicator analysis.

Parameters:

share (str or int) – Stock ticker or level index; the semantics are the same as the share parameter in slice_to_dataframe(share=...).

Returns:

Row index is hdates, columns are htypes, containing all historical data for this stock across all time points.

Return type:

pandas.DataFrame

unstack(by: str = 'share') dict[source]

Equivalent to method self.to_df_dict(), which is an alias of method self.to_df_dict().

Parameters:

by (str, {'share', 'htype'}, default 'share') – Specify whether to unstack by share or htype, default is share.

Returns:

The result after unstacking, is a dictionary with key as share or htype and value as the corresponding DataFrame

Return type:

dict

Examples

>>> hp = HistoryPanel(np.random.randn(2, 3, 4),
...                   rows=['2020-01-01', '2020-01-02', '2020-01-03'],
...                   levels=['000001', '000002', '000003'],
...                   columns=['close', 'open', 'high', 'low'])
>>> hp
share 0, label: 000001
            close,  open,   high,   low
2020-01-01  0.1,    0.2,    0.3,    0.4
2020-01-02  0.5,    0.6,    0.7,    0.8
2020-01-03  0.9,    1.0,    1.1,    1.2
share 1, label: 000002
            close,  open,   high,   low
2020-01-01  1.1,    1.2,    1.3,    1.4
2020-01-02  1.5,    1.6,    1.7,    1.8
2020-01-03  1.9,    2.0,    2.1,    2.2
share 2, label: 000003
            close,  open,   high,   low
2020-01-01  2.1,    2.2,    2.3,    2.4
2020-01-02  2.5,    2.6,    2.7,    2.8
2020-01-03  2.9,    3.0,    3.1,    3.2
>>> hp.unstack(by='share')
{'000001':
            close,  open,   high,   low
2020-01-01  0.1,    0.2,    0.3,    0.4
2020-01-02  0.5,    0.6,    0.7,    0.8
2020-01-03  0.9,    1.0,    1.1,    1.2
, '000002':
            close,  open,   high,   low
2020-01-01  1.1,    1.2,    1.3,    1.4
2020-01-02  1.5,    1.6,    1.7,    1.8
2020-01-03  1.9,    2.0,    2.1,    2.2
, '000003':
            close,  open,   high,   low
2020-01-01  2.1,    2.2,    2.3,    2.4
2020-01-02  2.5,    2.6,    2.7,    2.8
2020-01-03  2.9,    3.0,    3.1,    3.2
}
>>> hp.unstack(by='htype')
{'close':
            000001,  000002,  000003
2020-01-01  0.1,     1.1,     2.1
2020-01-02  0.5,     1.5,     2.5
2020-01-03  0.9,     1.9,     2.9
, 'open':
            000001,  000002,  000003
2020-01-01  0.2,     1.2,     2.2
2020-01-02  0.6,     1.6,     2.6
2020-01-03  1.0,     2.0,     3.0
, 'high':
            000001,  000002,  000003
2020-01-01  0.3,     1.3,     2.3
2020-01-02  0.7,     1.7,     2.7
2020-01-03  1.1,     2.1,     3.1
, 'low':
            000001,  000002,  000003
2020-01-01  0.4,     1.4,     2.4
2020-01-02  0.8,     1.8,     2.8
2020-01-03  1.2,     2.2,     3.2
}
property values

Return the internal 3D data buffer of the current object (the same reference as _values).

When non-empty, it points to the same memory as to_numpy(copy=False); modifying the return value will directly modify this object’s data. When appending new columns via __setitem__, the internals may replace the entire array; the values held by subviews (__getitem__ / subpanel(copy=False)) may still point to the old buffer from before the column expansion, and new columns will not appear automatically. For a stable snapshot, use subpanel(..., copy=True) or to_numpy(copy=True). When writing columns in place, if the original array is not float64, it will be upgraded to float64 internally before storing.

Returns:

Shape (level_count, row_count, column_count); None for an empty panel.

Return type:

numpy.ndarray or None

The HistoryPanel object provides commonly used financial data statistics and aggregation methods, including descriptive statistics, rolling window calculations, return and risk metric calculations, as well as candlestick (K-line) and technical indicator calculations. Details are as follows:

Basic statistics and aggregation

The following methods provide pandas-like statistical functionality on the HistoryPanel’s 3D data:

HistoryPanel.describe(by: Optional[str] = 'share', percentiles: tuple = (0.25, 0.5, 0.75), include: str = 'numeric', ddof: int = 1) DataFrame[source]

Compute basic descriptive statistics for a HistoryPanel, similar to pandas.DataFrame.describe.

You can compute descriptive statistics such as count, mean, std, min, max, and specified quantiles for numeric data by share, historical data type (htype), or from a global perspective.

Parameters:
  • by ({'share', 'htype', None}, default 'share') – Statistics perspective: - ‘share’: one describe result per stock, concatenated into a MultiIndex with columns (htype, stat); - ‘htype’: the distribution of each htype across all stocks and times; - None: treat all numeric values as a single overall sample pool.

  • percentiles (tuple of float, default (0.25, 0.5, 0.75)) – List of quantiles to compute; values should be in the (0, 1) interval.

  • include ({'numeric', None}, default 'numeric') – Currently only numeric statistics are supported; non-numeric columns will be ignored automatically.

  • ddof (int, default 1) – The degrees-of-freedom parameter when computing the standard deviation; only takes effect when by is None.

Returns:

A descriptive statistics results table whose index/columns structure depends on the value of by.

Return type:

pandas.DataFrame

Examples

>>> hp = HistoryPanel(np.random.rand(2, 10, 2),
...                   levels=['000001.SZ', '000002.SZ'],
...                   rows=pd.date_range('2020-01-01', periods=10),
...                   columns=['open', 'close'])
>>> desc_share = hp.describe(by='share')
>>> desc_share
share 0, label: 000001.SZ
            open      close
count  10.000000  10.000000
mean    0.456789   0.567890
std     0.129099   0.086603
min     0.123456   0.234567
25%     0.234567   0.345678
50%     0.345678   0.456789
75%     0.567890   0.678901
share 1, label: 000002.SZ
            open      close
count  10.000000  10.000000
mean    0.345678   0.456789
std     0.149361   0.110769
min     0.012345   0.123456
25%     0.123456   0.234567
50%     0.234567   0.345678
75%     0.456789   0.567890
>>> sorted(desc_share.columns.get_level_values('stat').unique().tolist())
['25%', '50%', '75%', 'count', 'max', 'mean', 'min', 'std']
>>> desc_htype = hp.describe(by='htype')
>>> 'open' in desc_htype.index
True
HistoryPanel.mean(by: str = 'share', skipna: bool = True) DataFrame[source]

Compute mean statistics for a HistoryPanel by share or data type.

Parameters:
  • by ({'share', 'htype'}, default 'share') – Aggregation dimension: - ‘share’: compute the mean over the time axis for each stock, returning a DataFrame with index as shares and columns as htypes; - ‘htype’: compute the mean over all stocks for each htype, returning the transposed DataFrame.

  • skipna (bool, default True) – Whether to ignore NaN when computing the mean.

Returns:

A mean results table after aggregating along the specified dimension.

Return type:

pandas.DataFrame

Examples

>>> hp = HistoryPanel(np.random.rand(2, 3, 2),
...                   levels=['000001.SZ', '000002.SZ'],
...                   rows=pd.date_range('2020-01-01', periods=3),
...                   columns=['open', 'close'])
>>> hp.mean()
            open     close
000001.SZ  0.456789  0.567890
000002.SZ  0.345678  0.456789
HistoryPanel.std(by: str = 'share', skipna: bool = True) DataFrame[source]

Compute standard deviation statistics for a HistoryPanel by share or data type (ddof=1).

Parameters:
  • by ({'share', 'htype'}, default 'share') – The aggregation dimension; same semantics as mean().

  • skipna (bool, default True) – Whether to ignore NaN when computing the standard deviation.

Returns:

A standard deviation results table after aggregating along the specified dimension.

Return type:

pandas.DataFrame

Examples

>>> hp = HistoryPanel(np.random.rand(2, 4, 2),
...                   levels=['000001.SZ', '000002.SZ'],
...                   rows=pd.date_range('2020-01-01', periods=4),
...                   columns=['open', 'close'])
>>> hp.std()
            open     close
000001.SZ  0.129099  0.086603
000002.SZ  0.149361  0.110769
HistoryPanel.min(by: str = 'share', skipna: bool = True) DataFrame[source]

Compute minimum statistics for a HistoryPanel by share or data type.

Parameters:
  • by ({'share', 'htype'}, default 'share') – The aggregation dimension; same semantics as mean().

  • skipna (bool, default True) – Whether to ignore NaN when computing the minimum.

Returns:

A minimum results table after aggregating along the specified dimension.

Return type:

pandas.DataFrame

Examples

>>> data = np.array([[[1., 2.], [3., 4.]],
...                  [[5., 6.], [7., 8.]]])
>>> hp = HistoryPanel(values=data,
...                   levels=['000001.SZ', '000002.SZ'],
...                   rows=pd.date_range('2020-01-01', periods=2),
...                   columns=['open', 'close'])
>>> hp.min()
            open  close
000001.SZ   1.0    2.0
000002.SZ   5.0    6.0
HistoryPanel.max(by: str = 'share', skipna: bool = True) DataFrame[source]

Compute maximum statistics for HistoryPanel by symbol or data type.

Parameters:
  • by ({'share', 'htype'}, default 'share') – The aggregation dimension; same semantics as mean().

  • skipna (bool, default True) – Whether to ignore NaN when computing the maximum.

Returns:

Result table of maximum values after aggregating along the specified dimensions.

Return type:

pandas.DataFrame

Examples

>>> data = np.array([[[1., 2.], [3., 4.]],
...                  [[5., 6.], [7., 8.]]])
>>> hp = HistoryPanel(values=data,
...                   levels=['000001.SZ', '000002.SZ'],
...                   rows=pd.date_range('2020-01-01', periods=2),
...                   columns=['open', 'close'])
>>> hp.max()
            open  close
000001.SZ   3.0    4.0
000002.SZ   7.0    8.0

Research and masks (where)

Normalize any broadcastable condition into a bool array with the same shape as values, for use with the mask= parameter of subsequent research APIs (e.g., cumulative return, normalization, portfolio aggregation, etc.). A 2D (M, L) condition will be replicated along the htype axis to (M, L, N); see the method docstring and the tutorial “Using HistoryPanel to manipulate and analyze historical data” for details.

HistoryPanel.where(condition: Union[ndarray, Callable[[HistoryPanel], ndarray]]) ndarray[source]

Broadcast the condition to a bool mask with the same shape as values, for use by parameters such as mask= in the research API.

Does not modify this object. The returned array has dtype=bool and shape (number of shares, time length, number of htypes), consistent with panel.values. The condition can be an array (broadcastable to the above shape) or a callable(panel) that returns an array-like object.

Research masks are unrelated to NaN price handling in Backtester. Integers such as 0/1 will be converted to bool according to NumPy rules.

An array whose shape is exactly (M, L) is treated as “each (share, time) uses the same boolean value for all htype”. Internally it is first converted to (M, L, 1) and then broadcast to (M, L, N) (because standard NumPy cannot broadcast a 2D (M,L) directly to 3D). A 1D (M,) array and a 2D (M, 1) array are treated as varying only by instrument; they are expanded to (M, 1, 1) and then broadcast.

Parameters:

condition (numpy.ndarray or callable) – Array-like: first np.asarray(..., dtype=bool), then broadcast to self.shape. If it is a callable, call condition(self) to get an array and then process it. A bare str is not accepted and will raise TypeError (in English).

Returns:

A 3D bool array with the same shape as self.shape (a copy; does not share the write buffer with internal values).

Return type:

numpy.ndarray

Raises:
  • TypeError – Raised when condition is str (in English).

  • ValueError – Raised when the return value cannot be converted to a bool array or cannot be broadcast to self.shape (in English).

Notes

condition can be the direct result of rich comparisons (since 2.2.8): for example, panel.where(panel.close > 100.0) or panel.where(panel['close'] > panel['open']). Operators such as > on a HistoryPanel and a scalar / broadcastable array / another panel (must satisfy alignment rules) return a numpy.ndarray (dtype=bool), which is then broadcast by this method to the same shape as panel.values.

The mask= parameters of cum_return, normalize, and portfolio can directly use the return value of this method, or any array of the same shape with dtype=bool. For more scenarios, see the tutorial “Using HistoryPanel to manipulate and analyze historical data” and the “Research and masking (where)” subsection in the Sphinx HistoryPanel API.

Examples

An empty panel yields a bool array of shape (0,0,0):

>>> empty = HistoryPanel()
>>> empty.where(True).shape
(0, 0, 0)

Comparison results with the same shape as values can be passed in directly:

>>> import pandas as pd
>>> hp = HistoryPanel(
...     np.arange(24, dtype=float).reshape(2, 3, 4),
...     levels=['A', 'B'],
...     rows=pd.date_range('2020-01-01', periods=3),
...     columns=['a', 'b', 'c', 'd'],
... )
>>> m = hp.where(hp.values > 10)
>>> m.shape == hp.shape
True
>>> not bool(m[0, 0, 0]) and bool(m[-1, -1, -1])
True

Scalar True / False fills the entire block:

>>> import numpy as np
>>> hp.where(True).all() and not hp.where(False).any()
True

A (M, L) condition is broadcast along the htype axis (e.g., event days):

>>> ev = np.zeros((2, 3), dtype=bool)
>>> ev[:, 1] = True
>>> m2 = hp.where(ev)
>>> bool(m2[0, 1, 0]) and bool(m2[0, 1, 3])
True

(M, L, 1) is semantically equivalent to (M, L), replicated along the htype dimension:

>>> c_ml1 = (hp.values[:, :, :1] > 10)
>>> m2b = hp.where(c_ml1)
>>> m2b.shape == hp.shape
True

Use lambda to construct conditions based on panel data:

>>> m3 = hp.where(lambda p: p.values[:, :, 0] >= 3)
>>> m3.shape == hp.shape
True

Composite boolean conditions:

>>> m4 = hp.where(lambda p: (p.values >= 5) & (p.values <= 18))
>>> m4.dtype == bool
True

Below is a slightly longer example that complements the tutorial (no network required; can be cross-checked against the doctest in the docstring):

import numpy as np
import pandas as pd
from qteasy import HistoryPanel

# 最小面板:M=2, L=3, N=4
hp = HistoryPanel(
    np.arange(24, dtype=float).reshape(2, 3, 4),
    levels=['A', 'B'],
    rows=pd.date_range('2020-01-01', periods=3),
    columns=['a', 'b', 'c', 'd'],
)
# Event window on time axis: last row True for all shares and htypes
M, L, N = hp.shape
event_ml = np.zeros((M, L), dtype=bool)
event_ml[:, -1] = True
mask_event = hp.where(event_ml)
assert mask_event[:, -1, :].all() and not mask_event[:, 0, :].any()

You can pass mask = hp.where(...) directly to the mask= parameter of cum_return() and normalize() (broadcasting rules are the same as where).

Column attribute access, comparisons, and loc (differences from pandas)

  • Attribute access: for column names that are valid identifiers, you can use hp.close (read-only), equivalent to hp['close']. Column names containing invalid identifier characters such as |, as well as unknown names, must still use hp['...']. For assignment, always use hp['col'] = .... If an existing method/descriptor (e.g., where, values) conflicts with a column of the same name, dot access still resolves to the API; use brackets for the column.

  • Comparison: hp > 0, hp['close'] > hp['open'], etc. return a numpy.ndarray (boolean dtype), not a HistoryPanel; they can be chained with hp.where(...). When both sides are panels, shares and hdates must match; htypes must match as well, or both sides must be single-column slices (e.g., comparing two columns).

  • loc indexing: hp.loc[k] is equivalent to hp[:, :, k], filtering only along the time axis (hdates); it does not accept the where-style (M, L, N) boolean cube. For grid masks, use where + mask=.

  • Arithmetic and copying:

    • Arithmetic operations such as hp + 1 and hp * arr return a new HistoryPanel and do not modify the original object.

    • In-place operators such as hp += 1 and hp *= arr explicitly modify the original object.

    • hp.copy(deep=True) (default) returns a deep copy; modifying the copy does not affect the original object. hp.copy(deep=False) shares the underlying array; modifying the copy will synchronously affect the original object.

Integration with plot: highlight using an (M,L) mask

In research scenarios, event days/signals/tradable universes commonly output a 2D boolean matrix mask_ml with shape (M, L) (number of instruments × time length). HistoryPanel.plot()’s highlight supports mapping this 2D mask to highlighted points in the current figure:

  • Subset mask: if mask_ml.shape == (M_plot, L), where M_plot is the number of shares selected by this plot(shares=...), it is matched in the plotting share order;

  • Full mask: if mask_ml.shape == (M_all, L) (M_all == len(hp.shares)), extract the current plotting subset by share name (silent truncation by position is forbidden);

  • overlay: when layout='overlay' and two instruments are overlaid, by default only the primary is highlighted (consistent with Plotly’s existing highlight semantics).

Example:

import numpy as np
hp = ...  # 已构造好的 HistoryPanel
M, L, N = hp.shape
mask_ml = np.zeros((M, L), dtype=bool)
mask_ml[:, -1] = True
fig = hp.plot(highlight={'condition': mask_ml})
HistoryPanel.loc

A read-only indexer for selecting a sub-panel along hdates (the time axis).

hp.loc[key] is equivalent to hp[:, :, key] and is used for slicing, time labels, label lists, :, or a 1D boolean mask of length equal to row_count. For grid-level (M,L,N) boolean conditions, use where() and the subsequent mask=; do not pass grid-level conditions into loc.

Returns:

A lightweight proxy; using [...] on it selects a sub-panel along the time axis.

Return type:

_HistoryPanelLocIndexer

Examples

>>> import pandas as pd
>>> import numpy as np
>>> hp = HistoryPanel(
...     np.arange(8, dtype=float).reshape(2, 4, 1),
...     levels=['A', 'B'],
...     rows=pd.date_range('2020-01-01', periods=4),
...     columns=['close'],
... )
>>> hp.loc[0:2]
share 0, label: A
            close
2020-01-01    0.0
2020-01-02    1.0
share 1, label: B
            close
2020-01-01    4.0
2020-01-02    5.0

Column-level DSL: assign

assign provides a pandas-like column-level DSL that can derive or update multiple columns at once. It supports constructing new factors in a single call based on existing columns or newly added columns, and supports returning a new panel or expanding columns in place on the original panel.

HistoryPanel.assign(*, inplace: bool = False, **kwargs: Any) HistoryPanel[source]

Derive or update columns (htypes) in batch, supporting appending or overwriting multiple columns at once.

assign() provides a pandas-like column-level DSL: you can name multiple new columns at once, and derive them in a single call via callables or arrays/scalars; within the same call, columns defined later can depend on columns newly added earlier. This method supports both returning a new panel and expanding/overwriting columns in-place on the original panel.

Parameters:
  • inplace (bool, default False) – When True, append/overwrite columns in place on the current HistoryPanel and return itself; when False, append/overwrite columns on a copy of the current data and return a new HistoryPanel.

  • **kwargs – For each keyword argument, the key is the new column name (htype) and must be a non-empty string; the value can be Callable[[HistoryPanel], np.ndarray], or an array/scalar that can be np.asarray-ed and broadcast to (M, L).

Returns:

When inplace=False, return a new panel with the added columns; when inplace=True, return the original panel.

Return type:

HistoryPanel

Raises:
  • ValueError – Raise (English message) when the panel is empty, the column name is an empty string, or the result returned by the callable/array cannot be broadcast to (M, L).

  • TypeError – Raise if the column name is not a string (English message).

A short example (can be used together with where()):

# 假设 hp 已含 'close' 列
# mask = hp.where(hp.close > 100.0)           # 比较结果为 bool ndarray,再规整为 (M,L,N)
# sub = hp.loc[0:20]                          # 等价 hp[:, :, 0:20],按时间轴截取
# L = len(hp.hdates)
# sub2 = hp.loc[[True]*3 + [False]*(L - 3)]   # 一维 bool 长度须等于 L

Cross-section and normalization: rank / zscore

rank and zscore are used for “daily cross-sectional ranking/standardization” and “per-share time-series rolling standardization” in lightweight factor research. zscore explicitly distinguishes two semantics via method:

  • method='cs': fix the date and perform cross-sectional standardization along the share dimension;

  • method='ts': fix the share and perform rolling standardization along the time axis (requires window).

HistoryPanel.rank(by: str, *, axis: str = 'share', method: str = 'average', new_htype: Optional[str] = None) HistoryPanel[source]

Rank the cross section (share dimension) day by day over time, append one column, and return a new panel.

Parameters:
  • by (str) – Column name (htype) to participate in ranking. Will be parsed first by _resolve_price_htype(), supporting adjusted-suffix columns such as close|b.

  • axis ({'share'}, default 'share') – Currently only cross-sectional ranking along the share dimension is supported.

  • method ({'average', 'min', 'max', 'first', 'dense'}, default 'average') – How to handle ranks for tied values (ties); the semantics are consistent with pandas Series.rank(method=...).

  • new_htype (str, optional) – Output column name; when None, defaults to rank_{by}.

Returns:

The new panel after appending the ranking column; does not modify the original object. An empty panel returns an empty panel.

Return type:

HistoryPanel

Raises:

ValueError – Raise (English message) when parameters are invalid, columns do not exist, or the output column name conflicts.

Examples

>>> import numpy as np
>>> import pandas as pd
>>> from qteasy import HistoryPanel
>>> hp = HistoryPanel(
...     np.array([[[1.0], [2.0]], [[2.0], [1.0]]]),
...     levels=['s1', 's2'],
...     rows=pd.date_range('2023-01-01', periods=2),
...     columns=['close'],
... )
>>> hp2 = hp.rank(by='close')
>>> 'rank_close' in hp2.htypes
True
HistoryPanel.zscore(by: str, *, method: str = 'cs', window: Optional[int] = None, new_htype: Optional[str] = None) HistoryPanel[source]

Compute standardized scores (zscore) for the specified column and append one column, returning a new panel.

This method explicitly distinguishes two common semantics via the method parameter:

  • method='cs' (cross-sectional): fix each time point and perform cross-sectional normalization along the share dimension;

  • method='ts' (time-series rolling): fix each share and perform rolling normalization along the time axis.

Parameters:
  • by (str) – Column name (htype) to participate in normalization. Will be parsed first by _resolve_price_htype(), supporting adjusted-suffix columns such as close|b.

  • method ({'cs', 'ts'}, default 'cs') – Normalization semantics: cross-sectional (cs) or time-series rolling (ts).

  • window (int, optional) – Rolling window length (number of bars) when method='ts'; must be a positive integer; must be None when method='cs'.

  • new_htype (str, optional) – Output column name; when None, defaults to cs_z_{by} or ts_z_{by}_{window}.

Returns:

A new panel with the zscore column appended; does not modify the original object. An empty panel returns an empty panel.

Return type:

HistoryPanel

Raises:

ValueError – Raise (English message) when parameters are invalid, columns do not exist, or the output column name conflicts.

Examples

>>> import numpy as np
>>> import pandas as pd
>>> from qteasy import HistoryPanel
>>> hp = HistoryPanel(
...     np.array([[[1.0], [2.0]], [[3.0], [4.0]]]),
...     levels=['s1', 's2'],
...     rows=pd.date_range('2023-01-01', periods=2),
...     columns=['x'],
... )
>>> hp_cs = hp.zscore(by='x', method='cs')
>>> hp_ts = hp.zscore(by='x', method='ts', window=2)

Alignment and resampling: align_to / resample

When you need to perform element-wise operations on two HistoryPanel objects (e.g., division, subtraction, correlation, etc.), if their shares or hdates do not match, NumPy broadcasting may cause silent misalignment. Therefore, this project provides an explicit alignment entry point:

  • align_to(): align shares and hdates by labels, supports join='inner'|'outer', and fills missing values with fill_value;

  • resample(): resample along the time axis; you must explicitly provide agg= (covering all htypes) to avoid “apparently successful but uninterpretable results” caused by ambiguous aggregation semantics.

HistoryPanel.align_to(other: HistoryPanel, *, join: str = 'inner', fill_value: float = nan) Tuple[HistoryPanel, HistoryPanel][source]

Align two HistoryPanels by labels along the shares and hdates axes to avoid silent misalignment.

This method does not align by iloc/position; it only performs explicit alignment using axis labels. After alignment, it returns two new panels with exactly the same shares, hdates, and htypes; missing grid points are filled with fill_value.

Parameters:
  • other (HistoryPanel) – Another panel to align to.

  • join ({'inner', 'outer'}, default 'inner') – Alignment method: - inner: take the intersection of both shares and hdates; - outer: take the union of both shares and hdates. The output order is stable: for the intersection, follow the order of self; for the union, put self first, then append elements that appear in other but not in self.

  • fill_value (float, default np.nan) – Fill value for missing positions after alignment.

Returns:

Aligned (self_aligned, other_aligned).

Return type:

(HistoryPanel, HistoryPanel)

Raises:
  • TypeError – Raised when other is not a HistoryPanel (English message).

  • ValueError – Raised when join is invalid, or when the two htypes are not exactly identical (English message).

Examples

>>> import numpy as np
>>> import pandas as pd
>>> from qteasy import HistoryPanel
>>> hp1 = HistoryPanel(np.array([[[1.0],[2.0]]]), levels=['s1'],
...                   rows=pd.date_range('2023-01-01', periods=2), columns=['x'])
>>> hp2 = HistoryPanel(np.array([[[10.0],[11.0]]]), levels=['s2'],
...                   rows=pd.date_range('2023-01-02', periods=2), columns=['x'])
>>> a1, a2 = hp1.align_to(hp2, join='outer', fill_value=np.nan)
>>> a1.shares
['s1', 's2']
HistoryPanel.resample(rule: str, *, agg: Optional[dict] = None) HistoryPanel[source]

Resample along the time axis (hdates) according to the rule and return a new panel.

To avoid silent misalignment caused by ambiguous aggregation semantics, this method requires agg to be provided explicitly, and it must cover all htypes in the current panel.

Parameters:
  • rule (str) – A pandas-compatible resampling rule string, such as 'W', 'M', '5D', etc.

  • agg (dict, required) – Aggregation rule dict: {htype_name: agg_name}, where agg_name supports 'first'|'last'|'min'|'max'|'sum'|'mean'. Must cover all htypes.

Returns:

The new panel after resampling; the original object is not modified. An empty panel returns an empty panel.

Return type:

HistoryPanel

Raises:

ValueError – Raised (with an English message) when agg is missing, does not cover all columns, contains unknown column names, the aggregation method is invalid, or rule is invalid.

Examples

>>> import numpy as np
>>> import pandas as pd
>>> from qteasy import HistoryPanel
>>> idx = pd.date_range('2023-01-01', periods=10, freq='D')
>>> hp = HistoryPanel(np.arange(10, dtype=float).reshape(1, 10, 1),
...                   levels=['s1'], rows=idx, columns=['x'])
>>> out = hp.resample('W', agg={'x': 'last'})
>>> out.hdates
[Timestamp('2023-01-01 00:00:00'), Timestamp('2023-01-08 00:00:00')]

Rolling window

Using rolling-window methods enables sliding computations along the time dimension of HistoryPanel, supporting common operations such as rolling mean and rolling standard deviation:

HistoryPanel.rolling(window: int, min_periods: Optional[int] = None, center: bool = False, by: str = 'share') HistoryPanelRolling[source]

Construct a rolling-window statistics object based on HistoryPanel.

Rolling is performed only along the time axis (rows / hdates); window is an integer number of bars.

Parameters:
  • window (int) – Rolling window length.

  • min_periods (int, optional) – Minimum number of valid observations; if fewer than this, the result is NaN. Defaults to the same as window.

  • center (bool, default False) – Whether to use a centered window; semantics are consistent with pandas.Series.rolling.

  • by ({'share', 'htype'}, default 'share') – Specify the grouping mode for rolling: - ‘share’: roll independently for each htype of each stock (most common); - ‘htype’: roll independently for each htype across all stocks.

Returns:

A rolling-window statistics object; supports calling mean(), std(), min(), max(), etc.

Return type:

HistoryPanelRolling

Examples

>>> hp = HistoryPanel(np.array([[[12.3, 12.5, 1020010], [12.6, 13.2, 1020020]],
...                                    [[2.3, 2.5, 20010], [2.6, 3.2, 20020]]]),
...                          levels=['000300', '000001'],
...                          rows=['2020-01-01', '2020-01-02'],
...                          columns=['close', 'open', 'vol'])
>>> hp.rolling(window=2, by='share').mean()
share 0, label: 000300
            close  open        vol
2020-01-01    NaN   NaN        NaN
2020-01-02   12.45  12.85  1020015.0
share 1, label: 000001
            close  open        vol
2020-01-01    NaN   NaN        NaN
2020-01-02    2.45   2.85  20015.0
class qteasy.history.HistoryPanelRolling(hp: HistoryPanel, window: int, min_periods: int, center: bool, by: str)[source]

The rolling-window statistics object for HistoryPanel.

This object is typically created by HistoryPanel.rolling(), corresponds to a fixed combination of window parameters, and provides methods such as mean/std/sum/min/max/apply that return a new HistoryPanel.

apply(func: Callable[[ndarray], float], raw: bool = False, **kwargs) HistoryPanel[source]

Apply a custom function over the rolling window.

Parameters:
  • func (callable) – A custom function that takes a window vector and returns a scalar.

  • raw (bool, default False) – If True, pass an ndarray to func; otherwise pass a Series.

  • **kwargs – Other parameters passed through to func.

Returns:

Rolling result panel after applying a custom function; the shares/hdates/htypes labels remain unchanged.

Return type:

HistoryPanel

Notes

  • Same as pandas: when the number of valid samples in the window is less than min_periods, the result is NaN.

  • func should return a scalar numeric value; returning an array or a non-numeric type may cause pandas to raise an error or produce unexpected results.

Examples

>>> hp = qt.get_history_data(htype_names='close', shares='000001.SZ', rows=30, as_data_frame=False)
>>> roller = hp.rolling(window=5, min_periods=5)
>>> hp_mean = roller.mean()
>>> hp_mean
share 0, label: 000001
            close
2020-01-01  NaN
2020-01-02  NaN
2020-01-03  NaN
2020-01-04  NaN
2020-01-05  10.0
2020-01-06  10.5
...
2020-01-30  11.2
>>> hp_mad = roller.apply(lambda x: float(np.mean(np.abs(x - np.mean(x)))), raw=True)
>>> hp_mad
share 0, label: 000001
            close
2020-01-01  NaN
2020-01-02  NaN
2020-01-03  NaN
2020-01-04  NaN
2020-01-05  0.0
2020-01-06  0.5
...
2020-01-30  0.4
max() HistoryPanel[source]

Compute the rolling-window maximum and return a new panel.

Returns:

Rolling maximum result panel, with labels consistent with the original panel.

Return type:

HistoryPanel

mean() HistoryPanel[source]

Compute the rolling-window mean and return a new panel.

Returns:

Rolling mean result panel, with labels consistent with the original panel.

Return type:

HistoryPanel

min() HistoryPanel[source]

Compute the rolling-window minimum and return a new panel.

Returns:

Rolling minimum result panel, with labels consistent with the original panel.

Return type:

HistoryPanel

std() HistoryPanel[source]

Compute the rolling-window standard deviation and return a new panel.

Returns:

Rolling standard deviation result panel, with labels consistent with the original panel.

Return type:

HistoryPanel

sum() HistoryPanel[source]

Compute the rolling-window sum and return a new panel.

Returns:

Rolling sum result panel, with labels consistent with the original panel.

Return type:

HistoryPanel

Return and risk metrics

HistoryPanel.returns(price_htype: str = 'close', method: str = 'simple', periods: int = 1, as_panel: bool = False, dropna: bool = False)[source]

Compute returns based on the specified price series.

Parameters:
  • price_htype (str, default 'close') – The price type used to compute returns must exist in htypes.

  • method ({'simple', 'log'}, default 'simple') –

    • simple: r_t = p_t / p_{t-periods} - 1

    • log: r_t = log(p_t) - log(p_{t-periods})

  • periods (int, default 1) – Number of bars in the return interval.

  • as_panel (bool, default False) – When False, return a DataFrame (index=time, columns=shares); when True, return a HistoryPanel (htypes contains only ret_{price_htype}).

  • dropna (bool, default False) – When True, drop leading rows that are all NaN.

Return type:

pandas.DataFrame or HistoryPanel

HistoryPanel.cum_return(htypes: Optional[Union[str, Sequence[str]]] = None, *, method: str = 'simple', mask: Optional[ndarray] = None) HistoryPanel[source]

Compute cumulative returns per share along the time dimension (research-oriented) and return a new panel.

By default, computes on the close column (resolved via _resolve_price_htype(), supporting close|b etc.). The output column name is cumret_<user-provided column name>, consistent with returns() using the ret_<price_htype> naming strategy. If NaN or non-positive prices appear along the time path, all subsequent results from that point onward are NaN (path broken).

Parameters:
  • htypes (str, sequence of str, optional) – Column names to participate in the computation; when None, only process close (after parsing).

  • method ({'simple', 'log'}, default 'simple') – simple: from the first valid positive price t0, p_t/p_{t0}-1; log: log(p_t)-log(p_{t0}).

  • mask (numpy.ndarray, optional) – Same broadcasting rules as where(); positions that are False are treated as missing (NaN) before computation.

Returns:

shares / hdates are the same as the original panel; contains only the cumulative return column.

Return type:

HistoryPanel

Raises:

ValueError – Raised (in English) when method is invalid, columns cannot be parsed, mask cannot be broadcast, or the output column name conflicts with existing htypes.

Examples

>>> import numpy as np
>>> import pandas as pd
>>> from qteasy.history import HistoryPanel
>>> hp = HistoryPanel(
...     np.array([[[10.0], [11.0], [12.0]]]),
...     levels=['S'],
...     rows=pd.date_range('2023-01-01', periods=3),
...     columns=['close'],
... )
>>> cr = hp.cum_return(method='simple')
>>> cr
share 0, label: S
            cumret_close
2023-01-01          0.0
2023-01-02          0.1
2023-01-03          0.2
HistoryPanel.normalize(htypes: Optional[Union[str, Sequence[str]]] = None, *, base_index: int = 0, mask: Optional[ndarray] = None) HistoryPanel[source]

Scale the specified columns to be relative to 1.0 at the base time point (research-oriented) and return a new panel.

By default, uses the valid price at base_index as the denominator; if that time point is excluded by mask, is NaN, or is 0, then the entire time series output for that (share, column) will be NaN. The output column name is norm_<user-provided column name>.

Parameters:
  • htypes (str, sequence of str, optional) – Columns to participate in the computation; when None, only close (after parsing).

  • base_index (int, default 0) – Base index on the time axis (starting from 0); raise ValueError (in English) if out of bounds.

  • mask (numpy.ndarray, optional) – Same broadcasting rules as where().

Returns:

Same shares / hdates as the original panel; contains only the normalized columns.

Return type:

HistoryPanel

Raises:

ValueError – Raised when columns cannot be resolved, mask cannot be broadcast, base_index is out of bounds, or output column names conflict (in English).

Examples

>>> import numpy as np
>>> import pandas as pd
>>> from qteasy.history import HistoryPanel
>>> hp = HistoryPanel(
...     np.array([[[10.0], [20.0], [40.0]]]),
...     levels=['S'],
...     rows=pd.date_range('2023-01-01', periods=3),
...     columns=['close'],
... )
>>> nm = hp.normalize(base_index=0)
>>> nm
share 0, label: S
            norm_close
2023-01-01        1.0
2023-01-02        2.0
2023-01-03        4.0
HistoryPanel.portfolio(htypes: Union[str, Sequence[str]] = 'close', *, mode: str = 'equal', weights: Optional[ndarray] = None, mask: Optional[ndarray] = None, groups: Optional[Dict[str, Sequence[str]]] = None, benchmark: Optional[str] = None, benchmark_output: str = 'none', new_share_name: str = 'PORTFOLIO', normalize_weights: bool = True, allow_ungrouped: str = 'error') HistoryPanel[source]

Aggregate multiple shares into a portfolio series along the share dimension (research-oriented) and return a new panel.

Defaults to benchmark_output='none'; if benchmark is set, you can attach benchmark rows with tag_along, or keep only excess-prefixed columns with excess_only (portfolio minus benchmark, with column names prefixed by excess).

When groups is None, aggregate the entire panel into one row named new_share_name. When groups is not empty, the keys are output share labels (in insertion order) and the values are lists of original shares within each group; shares must not overlap across groups. When allow_ungrouped='error', each panel share must belong to exactly one group.

When groups is None and benchmark is specified, the benchmark share does not participate in portfolio aggregation (to avoid mixing index and individual-stock weights), and is only used for tag_along or excess_only; if no share is available after exclusion (e.g., the panel contains only the benchmark), raise ValueError.

The broadcast rules for mask are consistent with where(); invalid grid points do not participate in the aggregation.

Parameters:
  • htypes (str or sequence of str, default 'close') – Column names participating in the aggregation; resolved via _resolve_price_htype().

  • mode ({'equal', 'weighted'}, default 'equal') – Equal-weight average, or a weighted average used together with weights.

  • weights (numpy.ndarray, optional) – Shape (M,) or (M, L), aligned with the order of self.shares; used only when mode='weighted'.

  • mask (numpy.ndarray, optional) – Same broadcasting rules as where().

  • groups (dict, optional) – Output group name → list of share tags within the group.

  • benchmark (str, optional) – Benchmark share; must be in self.shares.

  • benchmark_output ({'none', 'tag_along', 'excess_only'}, default 'none') – Benchmark output form; when there is no benchmark, only 'none' is allowed.

  • new_share_name (str, default 'PORTFOLIO') – Share name for the synthesized row when there is no groups.

  • normalize_weights (bool, default True) – When weighting, normalize the weights over the members participating in the aggregation before computing the weighted sum (numerically equivalent to sum(w*x)/sum(w)).

  • allow_ungrouped ({'error', 'exclude'}, default 'error') – When groups is non-empty, whether to require covering all shares.

Returns:

A new object; hdates and the time length are consistent with the original panel.

Return type:

HistoryPanel

Raises:

ValueError – Invalid parameters, share not in panel, overlapping groups, mask cannot be broadcast, etc. (in English).

HistoryPanel.volatility(window: int = 20, price_htype: str = 'close', method: str = 'simple', annualize: bool = True, periods_per_year: Optional[int] = None, as_panel: bool = False)[source]

Compute rolling volatility (standard deviation) based on the return series.

Parameters:
  • window (int, default 20) – Rolling window length (number of bars).

  • price_htype (str, default 'close') – Price type used to compute returns.

  • method ({'simple', 'log'}, default 'simple') – The return calculation method is consistent with returns().

  • annualize (bool, default True) – Whether to annualize (multiply by sqrt(periods_per_year)).

  • periods_per_year (int, optional) – Bars per year when annualizing; if not specified and annualize=True, try to infer from the time interval, and raise an error if it cannot be inferred.

  • as_panel (bool, default False) – The return format is the same as returns().

Return type:

pandas.DataFrame or HistoryPanel

HistoryPanel.alpha_beta(benchmark: Union[Series, DataFrame], price_htype: str = 'close', method: str = 'simple', freq: Optional[str] = None, annualize: bool = True) DataFrame[source]

Compute metrics such as alpha/beta for each stock relative to the given benchmark return series.

Parameters:
  • benchmark (Series or DataFrame) – Baseline price time series; the index should align with HistoryPanel.hdates or at least overlap. If a DataFrame is provided, only the first column is used as the baseline price.

  • price_htype (str, default 'close') – Price type used to compute returns.

  • method ({'simple', 'log'}, default 'simple') – The return calculation method is consistent with returns().

  • freq (str, optional) – Return frequency string, used to infer the number of bars per year when annualizing alpha, such as ‘D’, ‘W’, ‘M’.

  • annualize (bool, default True) – Whether to annualize alpha.

Returns:

Index is shares; columns are [‘alpha’, ‘beta’, ‘r2’, ‘n_obs’].

Return type:

pandas.DataFrame

Candlesticks and technical indicators

Primary entry point: research_preset

research_preset is used to quickly assemble a “commonly used column set that can be plotted directly” (e.g., OHLCV + MACD + MA), avoiding implicit indicator computation during plotting. If input columns are missing, it raises an English ValueError and indicates which columns are missing.

HistoryPanel.research_preset(name: str, *, inplace: bool = False) HistoryPanel[source]

Quickly generate a commonly used column set for research based on a preset, and return the result panel.

This method is intended to serve as the “first entry point” of HistoryPanel: without introducing backtesting semantics, quickly assemble OHLCV + commonly used technical indicator columns (such as MACD and moving averages) for direct plotting or further research.

Parameters:
  • name (str) – Preset name. Currently supported: - 'ohlcv_macd_ma': requires the panel to contain at least open/high/low/close/vol, and generates macd_12_26_9, macd_signal_12_26_9, macd_hist_12_26_9, and sma_20.

  • inplace (bool, default False) – If True, append preset columns to the original panel in place and return the original panel; if False, return a new panel with the added columns.

Returns:

The HistoryPanel after appending preset columns. When inplace=True, returns the original object.

Return type:

HistoryPanel

Raises:

ValueError – Raised when the preset name is invalid, or when required input columns for the preset are missing (error message is in English).

HistoryPanel.kline

A candlestick technical indicator accessor, providing methods such as sma, ema, bbands, macd, kdj, etc.

HistoryPanel.apply_ta(func_name: str, htype: str = 'close', shares: Optional[Iterable[str]] = None, as_panel: bool = True, **kwargs)[source]

Call technical indicator functions in qteasy.tafuncs and broadcast the computation across multiple stocks.

Parameters:
  • func_name (str) – Function names in qteasy.tafuncs, such as ‘sma’, ‘ema’, etc.

  • htype (str, default 'close') – The data type of the one-dimensional time series used as input.

  • shares (list of str, optional) – List of stocks to compute; by default, all shares are used.

  • as_panel (bool, default True) – When True, returns a new HistoryPanel with output columns appended to the end of htypes; when False, returns a DataFrame (time × [share, output_name]) with MultiIndex columns.

HistoryPanel.candle_pattern(name: str, price_htypes: tuple[str, str, str, str] = ('open', 'high', 'low', 'close'), as_panel: bool = False, **kwargs)[source]

Compute candlestick pattern signals based on ta-lib pattern functions.

Parameters:
  • name (str) – Pattern function name, such as ‘cdlhammer’.

  • price_htypes (tuple of str, default ('open','high','low','close')) – The htypes names corresponding to OHLC.

  • as_panel (bool, default False) – False returns a DataFrame (time × stocks); True returns a HistoryPanel of a single htype.

qteasy-level historical data processing functions

qteasy also provides several functions independent of the HistoryPanel class, supporting more flexible historical data processing and analysis:

qteasy.get_history_data(htypes=None, *, htype_names=None, data_types=None, data_source=None, shares=None, symbols=None, start=None, end=None, freq=None, rows=None, asset_type=None, adj=None, as_data_frame=None, group_by=None, **kwargs)[source]

Given the specified instruments, data types, and frequency, fetch historical data from the local data source and assemble it into a structure that can be used directly by the strategy.

You can specify the required data types via htype_names or data_types, and combine them with shares / symbols, a time range, and freq to control the retrieval scope; depending on the settings of as_data_frame and group_by, the function returns a HistoryPanel or a dict of DataFrames grouped by instrument/data type. For advanced usage such as data type inference, frequency conversion, and trade_time_only, see the relevant sections in the documentation “Historical Data Retrieval get_history_data”.

Parameters:
  • htype_names (str or list of str, optional) – Collection of historical data names to retrieve; can be a comma-separated string (e.g., 'open, high, low, close') or a list (e.g., ['open', 'high', 'low', 'close']). If empty, the system will infer available htypes based on parameters such as freq / asset_type.

  • htypes (list of DataType, optional, deprecated) – List of historical data type objects; semantics are similar to htype_names. Prefer the new htype_names / data_types interface.

  • data_types (list of DataType, optional) – A collection of historical datatypes to be fetched, which must be legal datatype objects. If this argument is given, htype_names is ignored, otherwise possible htypes are created based on the htype_names argument

  • data_source (DataSource, optional) – Data sources that require access to historical data

  • shares (str or list of str, optional) – Collection of security codes; can be a comma-separated string (e.g., '000001.SZ, 000002.SZ') or a list (e.g., ['000001.SZ', '000002.SZ']).

  • symbols (str or list of str, optional) – Collection of security codes; can be a comma-separated string (e.g., '000001, 000002') or a list (e.g., ['000001', '000002']).

  • start (str, optional) – YYYYMMDD HH:MM:SS format date/time of the start date/time of the acquired historical data (if available)

  • end (str, optional) – YYYYMMDD HH:MM:SS format date/time, end date/time of historical data acquired (if available)

  • rows (int, default 10) – The number of rows of historical data to be fetched, if start and end are specified, this parameter is ignored, and the time range of the fetched data is [start, end] If start and end are not specified, the most recent rows in the table will be fetched, and the speed of using rows to fetch the data is much slower than that of using date.

  • freq (str, optional) – Frequency; supports minute intervals such as 1min/5min/15min/30min, as well as hourly/daily/weekly/monthly intervals such as H/D/W/M (e.g., candlesticks).

  • asset_type (str or list of str, optional) – Asset type filter; can be a comma-separated string (e.g. 'E, IDX') or a list (e.g. ['E', 'IDX']). Common values include any, E, IDX, FT, FD, etc.

  • adj (str, optional, deprecated) – Deprecated adjustment options (none/n, back/b, forward/fw/f). For new code, explicitly use the adjusted column name in htype (e.g. close|b).

  • as_data_frame (bool, default True) – Returns HistoryPanel when True; returns a dictionary of DataFrame when False.

  • group_by (str, default 'shares') – Grouping key when returning a dict of DataFrames; commonly 'shares'/'share'/'s' or 'htypes'/'htype'/'h'.

  • **kwargs – Additional parameters passed through to the underlying data retrieval / frequency conversion (e.g. drop_nan, resample_method, etc.). For detailed available values and semantics, see the documentation “Historical Data Retrieval get_history_data” and the infer_data_types notes.

Returns:

  • HistoryPanel – When as_data_frame is False, returns a HistoryPanel object containing all requested data.

  • dict of pandas.DataFrame – When as_data_frame is True, returns a dict of DataFrames grouped by group_by.

Examples

>>> import qteasy as qt
# 给出历史数据类型和证券代码,起止时间,可以获取该时间段内该股票的历史数据
>>> qt.get_history_data(htype_names='open, high, low, close, vol', shares='000001.SZ', start='20191225', end='20200110')
{'000001.SZ':
             open   high    low  close         vol
2019-12-25  16.45  16.56  16.24  16.30   414917.98
2019-12-26  16.34  16.48  16.32  16.47   372033.86
2019-12-27  16.53  16.93  16.43  16.63  1042574.72
2019-12-30  16.46  16.63  16.10  16.57   976970.31
2019-12-31  16.57  16.63  16.31  16.45   704442.25
2020-01-02  16.65  16.95  16.55  16.87  1530231.87
2020-01-03  16.94  17.31  16.92  17.18  1116194.81
2020-01-06  17.01  17.34  16.91  17.07   862083.50
2020-01-07  17.13  17.28  16.95  17.15   728607.56
2020-01-08  17.00  17.05  16.63  16.66   847824.12
2020-01-09  16.81  16.93  16.53  16.79  1031636.65
2020-01-10  16.79  16.81  16.52  16.69   585548.45
}
>>> # 除了股票的价格数据以外,也可以获取基金、指数的价格数据,如下面的代码获取000300.SH的指数价格
>>> qt.get_history_data(htype_names='close', shares='000300.SH', start='20191225', end='20200105')
{'000300.SH':
              close
2019-12-25  3990.87
2019-12-26  4025.99
2019-12-27  4022.03
2019-12-30  4081.63
2019-12-31  4096.58
2020-01-02  4152.24
2020-01-03  4144.96
}
>>> # 以及基金的净值数据
>>> qt.get_history_data(htype_names='unit_nav, accum_nav', shares='000001.OF', start='20191225', end='20200105')
{'000001.OF':
            unit_nav  accum_nav
2019-12-25     1.086      3.547
2019-12-26     1.096      3.557
2019-12-27     1.091      3.552
2019-12-30     1.100      3.561
2019-12-31     1.105      3.566
2020-01-02     1.123      3.584
2020-01-03     1.127      3.588
}
>>> # 不光价格数据,其他类型的数据也可以同时获取:
>>> qt.get_history_data(htype_names='close, pe, pb', shares='000001.SZ', start='20191225', end='20200105')
{'000001.SZ':
            close       pe      pb
2019-12-25  16.30  12.7454  1.1798
2019-12-26  16.47  12.8784  1.1921
2019-12-27  16.63  13.0035  1.2036
2019-12-30  16.57  12.9566  1.1993
2019-12-31  16.45  12.8627  1.1906
2020-01-02  16.87  13.1911  1.2210
2020-01-03  17.18  13.4335  1.2434
}
>>> # 可以同时混合获取多只股票、指数、多种数据类型的数据,如果某些数据类型缺失,会用NaN填充,注意000001.SZ是股票平安银行,000001.SH是上证指数
>>> qt.get_history_data(htype_names='close, pe, pb, total_mv, eps', shares='000001.SZ, 000001.SH', start='20191225', end='20200105')
{'000001.SZ':
            close       pe      pb      total_mv   eps
2019-12-25  16.30  12.7454  1.1798  3.163165e+07   NaN
2019-12-26  16.47  12.8784  1.1921  3.196155e+07   NaN
2019-12-27  16.63  13.0035  1.2036  3.227204e+07   NaN
2019-12-30  16.57  12.9566  1.1993  3.215561e+07   NaN
2019-12-31  16.45  12.8627  1.1906  3.192274e+07  1.54
2020-01-02  16.87  13.1911  1.2210  3.273778e+07  1.54
2020-01-03  17.18  13.4335  1.2434  3.333937e+07  1.54,
'000001.SH':
              close     pe    pb      total_mv  eps
2019-12-25  2981.88  13.74  1.38  3.987686e+13  NaN
2019-12-26  3007.35  13.85  1.39  4.020871e+13  NaN
2019-12-27  3005.04  13.85  1.39  4.019086e+13  NaN
2019-12-30  3040.02  14.00  1.40  4.064796e+13  NaN
2019-12-31  3050.12  14.05  1.41  4.079249e+13  NaN
2020-01-02  3085.20  14.22  1.42  4.128453e+13  NaN
2020-01-03  3083.79  14.22  1.42  4.127933e+13  NaN
}
>>> # 通过设置freq参数,可以获取不同频率的K线数据,如设置freq='H'可以获取1小时频率的数据
>>> qt.get_history_data(htype_names='open:b, high:b, low:b, close:b', shares='000001.SZ', start='20191229', end='20200106', freq='H', asset_type='E')
 {'000001.SZ':
                           open        high         low       close
2019-12-30 10:00:00  1796.92174  1796.92174  1796.92174  1796.92174
2019-12-30 11:00:00  1790.37160  1800.19681  1758.71259  1786.00484
2019-12-30 14:00:00  1811.11371  1813.29709  1795.83005  1806.74695
2019-12-30 15:00:00  1805.65526  1808.93033  1793.64667  1808.93033
2019-12-31 10:00:00  1808.93033  1808.93033  1808.93033  1808.93033
2019-12-31 11:00:00  1806.74695  1806.74695  1780.54639  1788.18822
2019-12-31 14:00:00  1786.00484  1788.18822  1781.63808  1786.00484
2019-12-31 15:00:00  1786.00484  1796.92174  1783.82146  1795.83005
2020-01-02 10:00:00  1817.66385  1817.66385  1817.66385  1817.66385
2020-01-02 11:00:00  1819.84723  1848.23117  1807.83864  1840.58934
2020-01-02 14:00:00  1842.77272  1847.13948  1828.58075  1843.86441
2020-01-02 15:00:00  1843.86441  1844.95610  1836.22258  1841.68103
2020-01-03 10:00:00  1849.32286  1849.32286  1849.32286  1849.32286
2020-01-03 11:00:00  1849.32286  1879.89018  1849.32286  1877.70680
2020-01-03 14:00:00  1863.51483  1889.71539  1863.51483  1884.25694
2020-01-03 15:00:00  1884.25694  1884.25694  1872.24835  1875.52342
}
>>> # 可以设置b_days_only参数来将价格填充到非交易日,形成完整的日期序列
>>> qt.get_history_data(htype_names='open, high, low, close, vol', shares='000001.SZ', start='20191225', end='20200105', b_days_only=False)
{'000001.SZ':
              open   high    low  close         vol
 2019-12-25  16.45  16.56  16.24  16.30   414917.98
 2019-12-26  16.34  16.48  16.32  16.47   372033.86
 2019-12-27  16.53  16.93  16.43  16.63  1042574.72
 2019-12-28  16.53  16.93  16.43  16.63  1042574.72
 2019-12-29  16.53  16.93  16.43  16.63  1042574.72
 2019-12-30  16.46  16.63  16.10  16.57   976970.31
 2019-12-31  16.57  16.63  16.31  16.45   704442.25
 2020-01-01  16.57  16.63  16.31  16.45   704442.25
 2020-01-02  16.65  16.95  16.55  16.87  1530231.87
 2020-01-03  16.94  17.31  16.92  17.18  1116194.81
 2020-01-04  16.94  17.31  16.92  17.18  1116194.81
 2020-01-05  16.94  17.31  16.92  17.18  1116194.81
 }
>>> # 使用特殊的htypes,可以获取特定的数据,如指数权重数据,下面的代码获取000001.SZ在HS300指数重的权重数据,单位为百分比
>>> qt.get_history_data(htype_names='wt_id:000300.SH', shares='000001.SZ, 000002.SZ', start='20191225', end='20200105')
{'000001.SZ':
            wt_idx:000300.SH
2020-01-02        1.1714
2020-01-03        1.1714,
'000002.SZ':
            wt_idx:000300.SH
2020-01-02        1.3595
2020-01-03        1.3595
}
qteasy.stack_dataframes(dfs: Union[list, dict], dataframe_as: str = 'shares', shares: Optional[Iterable] = None, htypes: Optional[Iterable] = None, fill_value: Optional[Any] = None)[source]

Combine multiple DataFrame objects into a single HistoryPanel.

Parameters:
  • dfs (list of pandas.DataFrame or dict of pandas.DataFrame) – The tables to be stacked; when a list, you usually need to explicitly provide axis labels with shares/htypes; when a dict, its keys can be used as the default label source.

  • dataframe_as ({'shares', 'htypes'}, default 'shares') – 'shares' means each DataFrame corresponds to one instrument (columns are htypes); 'htypes' means each DataFrame corresponds to one data type (columns are shares).

  • shares (str or list of str, optional) – Level labels of the output panel when dataframe_as='shares'; can be a comma-separated string or a list.

  • htypes (str or list of str, optional) – Column labels of the output panel when dataframe_as='htypes'; can be a comma-separated string or a list.

  • fill_value (int or float, optional) – Fill value used when aligning missing positions; default NaN.

Returns:

A HistoryPanel object consisting of multiple single-index data boxes.

Return type:

HistoryPanel

Examples

>>> df1 = pd.DataFrame([[1, 2, 3], [4, 5, 6]], index=['20210101', '20210102'], columns=['open', 'close', 'low'])
>>> df2 = pd.DataFrame([[7, 8, 9], [10, 11, 12]], index=['20210101', '20210102'], columns=['open', 'close', 'low'])
>>> df3 = pd.DataFrame([[13, 14, 15], [16, 17, 18]], index=['20210101', '20210102'], columns=['open', 'close', 'low'])
>>> dataframes = [df1, df2, df3]
>>> hp = stack_dataframes(dataframes, dataframe_as='shares', shares='000001.SZ, 000002.SZ, 000003.SZ')
>>> hp
share 0, label: 000001.SZ
         open  close   low
20210101  1.0    2.0   3.0
20210102  4.0    5.0   6.0
share 1, label: 000002.SZ
          open  close   low
20210101   7.0    8.0   9.0
20210102  10.0   11.0  12.0
share 2, label: 000003.SZ
          open  close   low
20210101  13.0   14.0  15.0
20210102  16.0   17.0  18.0

The boundary between research and formal backtesting (further reading)

On HistoryPanel, cum_return, portfolio, plot, etc. are geared toward exploration and quick checks; formal backtesting (settlement, fees, signal types, data windows that avoid look-ahead functions, etc.) is still handled by Strategy / Operator / Backtester. Readers are recommended to read, alongside this API page: