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()andqt.candle).
Indexing and array export:
__getitem__always returns a sub-HistoryPanelwith correct axis labels; when you need a rawndarray, use.valuesor.to_numpy(copy=...). In-place assignment to a single columnpanel['column_name'] = valueis implemented by__setitem__(only for non-empty panels, and only forstrkeys). The value is broadcast to(number_of_shares, time_length)and stored asfloat64; 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
htypescan be accessed read-only as attributes (e.g.panel.close, equivalent topanel['close']); comparison operations (e.g.panel.close > panel.open) return anumpyboolean array;panel.loc[key]is equivalent topanel[:, :, key], filtering only along the time axis (it does not accept a 3D mask likewhere). 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 returnNotImplemented.- Parameters:
other (Any) – Right operand.
- Returns:
A
boolarray when comparable; otherwiseNotImplemented.- Return type:
numpy.ndarray or NotImplemented
- __ge__(other: Any) ndarray[source]
Equivalent to elementwise comparison of
selfandotherusinggefrom theoperatormodule; returns anumpy.ndarraywith dtypebool(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
htypescolumn (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:
- 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 ashp['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-
HistoryPanelwith 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, usesub.valuesorsub.to_numpy(). A subpanel’svaluesmay share memory with the parent panel (NumPy view rules); if you need an independent copy, usesubpanel(..., copy=True)orsub.copy().When appending a new column on the parent object via
__setitem__, the entirevaluesblock of the parent panel will be replaced: by default, a subpanel withcopy=Falsewill not show the new column name, and itsvaluesmay still point to the old array before the column expansion; the sub-object obtained bysubpanel(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 emptyHistoryPanel.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 therowsdict (e.g.pandas.Timestamp), a list of time labels, and a 1Dboollist or 1Dnumpy.ndarray(boolean dtype) with length equal torow_count; consistent with thekeyaccepted byloc. Grid-level(M, L, N)boolean arrays are not used as third-axis indices; please usewhere().- 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:
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
selfandotherusinggtfrom theoperatormodule; returns anumpy.ndarraywith dtypebool(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
selfandotherusinglefrom theoperatormodule; returns anumpy.ndarraywith dtypebool(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
selfandotherusingltfrom theoperatormodule; returns anumpy.ndarraywith dtypebool(not a subpanel).- Parameters:
other (Any) – A scalar, a broadcastable
ndarray, or anotherHistoryPanel(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 returnNotImplemented.- Parameters:
other (Any) – Right operand.
- Returns:
A
boolarray when comparable; otherwiseNotImplemented.- 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 asassign.valuewill be broadcast to(share count, time length)and persisted asfloat64; 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 entirevaluesblock: subviews fromsubpanel(copy=False)/__getitem__usually cannot see the new column and may still point to the old buffer;subpanel(..., copy=True)andto_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-strraisesTypeError, and an empty string raisesValueError(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
keyis notstr(English message).ValueError – Raised when the panel is empty,
keyis an empty string, orvaluecannot 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
HistoryPaneldata (already handled uniformly byplot()).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
valuesarray; when you need to match NumPy’s view semantics and share underlying data in performance-sensitive scenarios, setdeep=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:
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:
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
valuesfor 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_COUNTuses 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'prefersFigureWidgetand 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 rawFigure.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
pageparameter 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=1is page 1,page=2is 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_klineFetch K-line data and optionally set
as_panel=Trueto 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:
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
Get the number of stocks or asset varieties in the HistoryPanel
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:
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.
Nonemeans select all on that axis. By defaultcopy=True, producing a copy detached from the parent object’s data buffer; setcopy=Falsefor zero-copy (the sub-panelvaluesmay share memory with the parent panel). When the parent object’s__setitem__appends a new column, it will replace the entire parent panelvaluesblock; acopy=Falsesub-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:
Notes
Similar to slicing with
copy=Falsein__getitem__: after the parent__setitem__appends columns, acopy=Falsechild object usually does not include the new columns; for a stable snapshot, keepcopy=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 correspondingDataFrame; when set to'htype'/'htypes', split along the data-type axis: dict keys are historical data type names and values are the correspondingDataFrame.- 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; usecopy=Truewhen you need an independent copy.An empty panel returns a float array with shape
(0, 0, 0). When non-empty,copy=Falsehas the same semantics asnumpy.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 withcopy=Falsewill 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.]]])
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 allhtypesas 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
shareparameter inslice_to_dataframe(share=...).- Returns:
Row index is
hdates, columns arehtypes, 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; thevaluesheld 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, usesubpanel(..., copy=True)orto_numpy(copy=True). When writing columns in place, if the original array is notfloat64, it will be upgraded tofloat64internally before storing.- Returns:
Shape
(level_count, row_count, column_count);Nonefor an empty panel.- Return type:
numpy.ndarray or None
- HistoryPanel is essentially a three-dimensional
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 asmask=in the research API.Does not modify this object. The returned array has
dtype=booland shape(number of shares, time length, number of htypes), consistent withpanel.values. The condition can be an array (broadcastable to the above shape) or acallable(panel)that returns an array-like object.Research masks are unrelated to NaN price handling in Backtester. Integers such as
0/1will 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 allhtype”. 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 toself.shape. If it is acallable, callcondition(self)to get an array and then process it. A barestris not accepted and will raiseTypeError(in English).- Returns:
A 3D bool array with the same shape as
self.shape(a copy; does not share the write buffer with internalvalues).- Return type:
numpy.ndarray
- Raises:
TypeError – Raised when
conditionisstr(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
conditioncan be the direct result of rich comparisons (since 2.2.8): for example,panel.where(panel.close > 100.0)orpanel.where(panel['close'] > panel['open']). Operators such as>on aHistoryPaneland a scalar / broadcastable array / another panel (must satisfy alignment rules) return anumpy.ndarray(dtype=bool), which is then broadcast by this method to the same shape aspanel.values.The
mask=parameters ofcum_return,normalize, andportfoliocan directly use the return value of this method, or any array of the same shape withdtype=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
valuescan 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/Falsefills 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
lambdato 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 tohp['close']. Column names containing invalid identifier characters such as|, as well as unknown names, must still usehp['...']. For assignment, always usehp['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 anumpy.ndarray(boolean dtype), not aHistoryPanel; they can be chained withhp.where(...). When both sides are panels,sharesandhdatesmust match;htypesmust match as well, or both sides must be single-column slices (e.g., comparing two columns).loc indexing:
hp.loc[k]is equivalent tohp[:, :, k], filtering only along the time axis (hdates); it does not accept thewhere-style(M, L, N)boolean cube. For grid masks, usewhere+mask=.Arithmetic and copying:
Arithmetic operations such as
hp + 1andhp * arrreturn a newHistoryPaneland do not modify the original object.In-place operators such as
hp += 1andhp *= arrexplicitly 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), whereM_plotis the number of shares selected by thisplot(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 tohp[:, :, key]and is used for slicing, time labels, label lists,:, or a 1D boolean mask of length equal torow_count. For grid-level(M,L,N)boolean conditions, usewhere()and the subsequentmask=; do not pass grid-level conditions intoloc.- 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 currentHistoryPaneland return itself; whenFalse, append/overwrite columns on a copy of the current data and return a newHistoryPanel.**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 benp.asarray-ed and broadcast to(M, L).
- Returns:
When
inplace=False, return a new panel with the added columns; wheninplace=True, return the original panel.- Return type:
- 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 (requireswindow).
- 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 asclose|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:
- 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
methodparameter: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 asclose|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 whenmethod='cs'.new_htype (str, optional) – Output column name; when None, defaults to
cs_z_{by}orts_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:
- 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(): alignsharesandhdatesby labels, supportsjoin='inner'|'outer', and fills missing values withfill_value;resample(): resample along the time axis; you must explicitly provideagg=(covering allhtypes) 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, andhtypes; missing grid points are filled withfill_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 ofself; for the union, putselffirst, then append elements that appear inotherbut not inself.fill_value (float, default np.nan) – Fill value for missing positions after alignment.
- Returns:
Aligned
(self_aligned, other_aligned).- Return type:
- Raises:
TypeError – Raised when
otheris not aHistoryPanel(English message).ValueError – Raised when
joinis invalid, or when the twohtypesare 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
aggto be provided explicitly, and it must cover allhtypesin 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}, whereagg_namesupports'first'|'last'|'min'|'max'|'sum'|'mean'. Must cover allhtypes.
- Returns:
The new panel after resampling; the original object is not modified. An empty panel returns an empty panel.
- Return type:
- Raises:
ValueError – Raised (with an English message) when
aggis missing, does not cover all columns, contains unknown column names, the aggregation method is invalid, orruleis 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);
windowis 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 aswindow.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:
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 asmean/std/sum/min/max/applythat 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 anndarrayto func; otherwise pass aSeries.**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:
Notes
Same as pandas: when the number of valid samples in the window is less than
min_periods, the result is NaN.funcshould 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:
- 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:
- 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:
- 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:
- 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:
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
closecolumn (resolved via_resolve_price_htype(), supportingclose|betc.). The output column name iscumret_<user-provided column name>, consistent withreturns()using theret_<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 processclose(after parsing).method ({'simple', 'log'}, default 'simple') –
simple: from the first valid positive pricet0,p_t/p_{t0}-1;log:log(p_t)-log(p_{t0}).mask (numpy.ndarray, optional) – Same broadcasting rules as
where(); positions that areFalseare treated as missing (NaN) before computation.
- Returns:
shares/hdatesare the same as the original panel; contains only the cumulative return column.- Return type:
- Raises:
ValueError – Raised (in English) when
methodis invalid, columns cannot be parsed,maskcannot be broadcast, or the output column name conflicts with existinghtypes.
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_indexas the denominator; if that time point is excluded bymask, isNaN, or is 0, then the entire time series output for that (share, column) will beNaN. The output column name isnorm_<user-provided column name>.- Parameters:
htypes (str, sequence of str, optional) – Columns to participate in the computation; when
None, onlyclose(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/hdatesas the original panel; contains only the normalized columns.- Return type:
- Raises:
ValueError – Raised when columns cannot be resolved,
maskcannot be broadcast,base_indexis 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'; ifbenchmarkis set, you can attach benchmark rows withtag_along, or keep only excess-prefixed columns withexcess_only(portfolio minus benchmark, with column names prefixed by excess).When
groupsisNone, aggregate the entire panel into one row namednew_share_name. Whengroupsis 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. Whenallow_ungrouped='error', each panel share must belong to exactly one group.When
groupsisNoneandbenchmarkis specified, the benchmark share does not participate in portfolio aggregation (to avoid mixing index and individual-stock weights), and is only used fortag_alongorexcess_only; if no share is available after exclusion (e.g., the panel contains only the benchmark), raiseValueError.The broadcast rules for
maskare consistent withwhere(); 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 ofself.shares; used only whenmode='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
groupsis non-empty, whether to require covering all shares.
- Returns:
A new object;
hdatesand the time length are consistent with the original panel.- Return type:
- 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 leastopen/high/low/close/vol, and generatesmacd_12_26_9,macd_signal_12_26_9,macd_hist_12_26_9, andsma_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
HistoryPanelafter appending preset columns. Wheninplace=True, returns the original object.- Return type:
- 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_namesordata_types, and combine them withshares/symbols, a time range, andfreqto control the retrieval scope; depending on the settings ofas_data_frameandgroup_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 asfreq/asset_type.htypes (list of DataType, optional, deprecated) – List of historical data type objects; semantics are similar to
htype_names. Prefer the newhtype_names/data_typesinterface.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 asH/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 includeany,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
HistoryPanelwhenTrue; returns a dictionary ofDataFramewhenFalse.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 theinfer_data_typesnotes.
- Returns:
HistoryPanel – When
as_data_frameis False, returns a HistoryPanel object containing all requested data.dict of pandas.DataFrame – When
as_data_frameis True, returns a dict of DataFrames grouped bygroup_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
DataFrameobjects into a singleHistoryPanel.- 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 withshares/htypes; when adict, its keys can be used as the default label source.dataframe_as ({'shares', 'htypes'}, default 'shares') –
'shares'means eachDataFramecorresponds to one instrument (columns are htypes);'htypes'means eachDataFramecorresponds 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:
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:
Tutorial Using HistoryPanel to manipulate and analyze historical data §9 (research →
FactorSorter/Operator), §10 (multi-source data paneling), §11 (export to pandas / statsmodels);Design notes HistoryPanel and the optional FactorResearch layer (evaluation conclusions on whether to add an independent factor statistics module).