Python 金融交易实用指南(二)(3)

简介: Python 金融交易实用指南(二)

Python 金融交易实用指南(二)(2)https://developer.aliyun.com/article/1523757

DataFrames 中的分组操作

pandas 中的分组操作通常遵循操作的分割-应用-组合过程:

  1. 首先,数据根据一个或多个键分成组。
  2. 然后,我们对这些组应用必要的函数来计算所需的结果。
  3. 最后,我们将它们组合起来构建转换后的数据集。

因此,对单索引 DataFrame 进行分组会构建一个分层 DataFrame。步骤如下:

  1. 让我们使用pandas.DataFrame.reset_index(…)方法从先前的dfDataFrame 中移除所有分层索引:
df = df.reset_index(); df
  1. 这返回了以下带有整数索引的 DataFrame:
alpha    numeric        A           B
0    a        1            -0.807285    0.170242
1    a        2             0.704596    1.568901
2    a        3            -1.417366    0.573896
3    b        1             1.110121    0.366712
...
  1. 让我们使用pandas.DataFrame.groupby(...)方法来按alpha列对AB列进行分组:
grouped = df[['A','B']].groupby(df['alpha']); grouped
  1. 这产生了以下的DataFrameGroupBy对象,随后我们可以对其进行操作:
<pandas.core.groupby.DataFrameGroupBy object at 0x7fd21f24cc18>
  1. 我们可以使用DataFrameGroupBy.describe(...)方法来收集摘要描述性统计信息:
grouped.describe()
  1. 这产生了以下输出,其中生成了AB的统计信息,但是按alpha列分组:
A        B
alpha            
a        count    3.000000    3.000000
mean   -0.506685    0.771013
std     1.092452    0.719863
min    -1.417366    0.170242
25%    -1.112325    0.372069
50%    -0.807285    0.573896
75%    -0.051344    1.071398
max     0.704596    1.568901
...
  1. 我们可以使用DataFrameGroupBy.apply(...)方法应用pandas.DataFrame.unstack(...)方法,该方法接受不同的函数并将它们应用于grouped对象的每个组:
grouped.apply(pd.DataFrame.unstack)
  1. 这产生了以下分层 DataFrame:
alpha      
a      A  0   -0.807285
          1    0.704596
          2   -1.417366
       B  0    0.170242
          1    1.568901
          2    0.573896
...
dtype: float64
  1. 还存在DataFrameGroupBy.agg(...)方法,它接受函数并使用该方法为每个组的每个列聚合该方法。下一个示例使用mean方法进行聚合:
grouped[['A', 'B']].agg('mean')
  1. 输出包含了按alpha值分组的AB列的均值:
A            B
alpha        
    a    -0.506685     0.771013
    b     0.670435     0.868550
    c     0.455688    -0.497468
    d    -0.786246     0.107246
  1. 类似的方法是DataFrameGroupBy.transform(...)方法,唯一的区别在于 transform 一次只对一列起作用,并返回与系列长度相同的值序列,而 apply 可以返回任何类型的结果:
from scipy import stats
grouped[['A', 'B']].transform(stats.zscore)
  1. 这会为列AB生成 Z 得分,我们在第二章中解释了这个探索性数据分析
A             B
0    -0.337002    -1.022126
1     1.357964     1.357493
2    -1.020962    -0.335367
3     0.610613    -0.567813
4    -1.410007     1.405598
5     0.799394    -0.837785
6    -1.000000     1.000000
7     1.000000    -1.000000
8    -1.000000    -1.000000
9     1.000000     1.000000

我们现在将学习如何转换 DataFrame 轴索引中的值。

转换 DataFrame 轴索引中的值

让我们首先重新检查我们将在这些示例中使用的 df2 DataFrame:

df2

这包含以下数据:

Columns   colA         colB         colC
Index            
A        -2.071652     0.742857     0.632307
B         0.113046    -0.384360     0.414585
C         0.690674     1.511816     2.220732
D         0.184174    -1.069291    -0.994885

我们可以使用 pandas.DataFrame.index 属性重命名索引标签,就像我们之前看到的那样:

df2.index = ['Alpha', 'Beta', 'Gamma', 'Delta']; 
df2

这会生成以下转换后的 DataFrame:

Columns       colA             colB             colC
Alpha        -2.071652         0.742857         0.632307
Beta          0.113046        -0.384360         0.414585
Gamma         0.690674         1.511816         2.220732
Delta         0.184174        -1.069291        -0.994885

pandas.Index.map(...) 方法应用于转换索引的函数。

在以下示例中,map 函数取名称的前三个字符并将其设置为新名称:

df2.index = df2.index.map(lambda x : x[:3]); df2

输出如下:

Columns     colA         colB         colC
Alp        -2.071652     0.742857     0.632307
Bet         0.113046    -0.384360     0.414585
Gam         0.690674     1.511816     2.220732
Del         0.184174    -1.069291    -0.994885

pandas.DataFrame.rename(...) 方法允许我们转换索引名称和列名称,并接受从旧名称到新名称的字典映射:

df2.rename(index={'Alp': 0, 'Bet': 1, 'Gam': 2, 'Del': 3}, 
           columns={'colA': 'A', 'colB': 'B', 'colC': 'C'})

结果 DataFrame 在两个轴上都有新标签:

Columns      A            B            C
0           -2.071652     0.742857     0.632307
1            0.113046    -0.384360     0.414585
2            0.690674     1.511816     2.220732
3            0.184174    -1.069291    -0.994885

通过学习这个课程,我们将学习如何处理 DataFrame 中的缺失数据。

处理 DataFrame 中的缺失数据

缺失数据是数据科学中常见的现象,可能由多种原因导致 - 例如,技术错误,人为错误,市场假期。

过滤掉缺失数据

在处理缺失数据时,第一个选择是删除具有任何缺失数据的所有观察。

此代码块使用 pandas.DataFrame.at[...] 属性修改了 df2 DataFrame,并将一些值设置为 NaN

for row, col in [('Bet', 'colA'), ('Bet', 'colB'), 
  ('Bet', 'colC'), ('Del', 'colB'), ('Gam', 'colC')]:
    df2.at[row, col] = np.NaN
df2

修改后的 DataFrame 如下:

Columns      colA         colB          colC
Alp         -1.721523    -0.425150      1.425227
Bet          NaN          NaN           NaN
Gam         -0.408566    -1.121813      NaN
Del          0.361053     NaN           0.580435

pandas.DataFrame.isnull(...) 方法在 DataFrame 中查找缺失值:

df2.isnull()

结果是一个 DataFrame,其中缺失值为 True,否则为 False

Columns     colA     colB     colC
Alp         False    False    False
Bet         True     True     True
Gam         False    False    True
Del         False    True     False

pandas.DataFrame.notnull(...) 方法执行相反操作(检测到非缺失值):

df2.notnull()

输出是以下 DataFrame:

Columns    colA    colB    colC
Alp        True    True    True
Bet        False   False   False
Gam        True    True    False
Del        True    False   True

pandas.DataFrame.dropna(...) 方法允许我们删除具有缺失值的行。 附加的 how= 参数控制哪些行被删除。 要删除所有字段都为 NaN 的行,我们执行以下操作:

df2.dropna(how='all')

结果是以下修改后的 DataFrame,其中 Bet 行被移除,因为那是唯一一个所有值都为 NaN 的行:

Columns    colA         colB         colC
Alp       -1.721523    -0.425150     1.425227
Gam       -0.408566    -1.121813     NaN
Del        0.361053     NaN          0.580435

how= 设置为 any 会删除具有任何 NaN 值的行:

df2.dropna(how='any')

这给我们以下包含所有非 NaN 值的 DataFrame:

Columns     colA         colB       colC
Alp        -1.721523    -0.42515    1.425227

现在我们将看看如何填充缺失数据。

填充缺失数据

处理缺失数据的第二个选择是使用我们选择的值或使用同一列中的其他有效值来填充缺失值以复制/推断缺失值。

让我们首先重新检查一下 df2 DataFrame:

df2

这产生以下带有一些缺失值的 DataFrame:

Columns     colA         colB        colC
Alp        -1.721523    -0.425150    1.425227
Bet         NaN          NaN         NaN
Gam        -0.408566    -1.121813    NaN
Del         0.361053     NaN         0.580435

现在,让我们使用 pandas.DataFrame.fillna(...) 方法,使用 method='backfill'inplace=True 参数来使用 backfill 方法从其他值向后填充缺失值并就地更改 DataFrame:

df2.fillna(method='backfill', inplace=True); 
df2

新的 DataFrame 包含以下内容:

Columns     colA         colB        colC
Alp        -1.721523    -0.425150    1.425227
Bet        -0.408566    -1.121813    0.580435
Gam        -0.408566    -1.121813    0.580435
Del         0.361053     NaN         0.580435

(Del,colB) 处的 NaN 值是因为该行后没有观察到值,因此无法执行向后填充。 这可以使用向前填充来修复。

使用函数和映射来转换 DataFrame

pandas DataFrame 的值也可以通过传递函数和字典映射来修改,这些函数和映射作用于一个或多个数据值,并生成新的转换值。

让我们通过添加一个新列 Category 来修改 df2 DataFrame,其中包含离散文本数据:

df2['Category'] = ['HIGH', 'LOW', 'LOW', 'HIGH']; df2

新的 DataFrame 包含以下内容:

Columns     colA         colB        colC        Category
Alp         1.017961     1.450681   -0.328989    HIGH
Bet        -0.079838    -0.519025    1.460911    LOW
Gam        -0.079838    -0.519025    1.460911    LOW
Del         0.359516     NaN         1.460911    HIGH

pandas.Series.map(...) 方法接受包含从旧值到新值的映射的字典,并对值进行转换。以下代码片段将 Category 中的文本值更改为单个字符:

df2['Category'] = df2['Category'].map({'HIGH': 'H', 
                                       'LOW': 'L'}); 
df2

更新后的 DataFrame 如下所示:

Columns     colA         colB        colC        Category
Alp         1.017961     1.450681   -0.328989    H
Bet        -0.079838    -0.519025    1.460911    L
Gam        -0.079838    -0.519025    1.460911    L
Del         0.359516     NaN         1.460911    H

pandas.DataFrame.applymap(...) 方法允许我们在 DataFrame 中对数据值应用函数。

以下代码应用了 numpy.exp(...) 方法,计算指数:

df2.drop('Category', axis=1).applymap(np.exp)

结果是一个包含原始 DataFrame 值的指数值的 DataFrame(除了 NaN 值):

Columns    colA        colB        colC
Alp        2.767545    4.266020    0.719651
Bet        0.923266    0.595101    4.309883
Gam        0.923266    0.595101    4.309883
Del        1.432636    NaN         4.309883

现在我们已经学会了如何转换 DataFrame,我们将看到如何对 DataFrame 中的值进行离散化和分桶。

DataFrame 值的离散化/分桶

实现离散化的最简单方法是创建数值范围,并为落入某个区间的所有值分配一个单独的离散标签。

首先,让我们为我们的使用生成一个随机值 ndarray:

arr = np.random.randn(10); 
arr

这包括以下内容:

array([  1.88087339e-01,  7.94570445e-01,  -5.97384701e-01,
        -3.01897668e+00, -5.42185315e-01,   1.10094663e+00,
         1.16002554e+00,  1.51491444e-03,  -2.21981570e+00,
         1.11903929e+00])

pandas.cut(...) 方法可用于离散化这些数值。以下代码使用 bins=labels=[...] 参数将值分为五个离散值,并提供标签:

cat = pd.cut(arr, bins=5, labels=['Very Low', 'Low', 'Med', 
                                  'High', 'Very High']); 
cat

在转换后,我们得到了离散值:

[High, Very High, Med, Very Low, Med, Very High, Very High, High, Very Low, Very High]
Categories (5, object): [Very Low < Low < Med < High < Very High]

pandas.qcut(...) 方法类似,但使用四分位数将连续值划分为离散值,以便每个类别具有相同数量的观测值。

以下使用 q= 参数构建了五个离散区间:

qcat = pd.qcut(arr, q=5, labels=['Very Low', 'Low', 'Med', 
                                 'High', 'Very High']); 
qcat

四分位数离散化产生以下类别:

[Med, High, Low, Very Low, Low, High, Very High, Med, Very Low, Very High]
Categories (5, object): [Very Low < Low < Med < High < Very High]

以下代码块构建了一个包含原始连续值以及由 cutqcut 生成的类别的 pandas DataFrame:

pd.DataFrame({'Value': arr, 'Category': cat, 
              'Quartile Category': qcat})

此 DataFrame 允许并列比较:

Category    Quartile     Category    Value
0           High         Med         0.188087
1           Very High    High        0.794570
2           Med          Low        -0.597385
3           Very Low     Very Low   -3.018977
4           Med          Low        -0.542185
5           Very High    High        1.100947
6           Very High    Very High   1.160026
7           High         Med         0.001515
8           Very Low     Very Low   -2.219816
9           Very High    Very High   1.119039

pandas.Categorical.categories 属性为我们提供了区间范围:

pd.cut(arr, bins=5).categories

在这种情况下,区间/数值范围如下:

Index(['(-3.0232, -2.183]', '(-2.183, -1.347]', 
       '(-1.347, -0.512]', '(-0.512, 0.324]', 
       '(0.324, 1.16]'],
      dtype='object')

我们也可以检查 qcut 的区间:

pd.qcut(arr, q=5).categories

它们与先前的区间略有不同,并显示如下:

Index(['[-3.019, -0.922]', '(-0.922, -0.216]', 
       '(-0.216, 0.431]', '(0.431, 1.105]', 
       '(1.105, 1.16]'],
      dtype='object')

现在我们将看到如何对 DataFrame 值进行排列和抽样以生成新的 DataFrame。

对 DataFrame 值进行排列和抽样以生成新的 DataFrame

对可用数据集进行排列以生成新数据集,以及对数据集进行抽样以进行子抽样(减少观测数量)或超抽样(增加观测数量)是统计分析中常见的操作。

首先,让我们生成一个随机值 DataFrame 进行操作:

df = pd.DataFrame(np.random.randn(10,5), 
                  index=np.sort(np.random.randint(0, 100, 
                                                 size=10)), 
                  columns=list('ABCDE')); 
df

结果如下:

A          B          C          D          E
 0  -0.564568  -0.188190  -1.678637  -0.128102  -1.880633
 0  -0.465880   0.266342   0.950357  -0.867568   1.504719
29   0.589315  -0.968324  -0.432725   0.856653  -0.683398
...

当应用于 DataFrame 时,numpy.random.permutation(...) 方法会沿着索引轴随机洗牌,并且可以用于对数据集的行进行置换:

df.loc[np.random.permutation(df.index)]

这产生了以下随机打乱行的 DataFrame:

A         B          C           D         E
42   0.214554   1.108811   1.352568   0.238083  -1.090455
 0  -0.564568  -0.188190  -1.678637  -0.128102  -1.880633
 0  -0.465880   0.266342   0.950357  -0.867568   1.504719
62  -0.266102   0.831051  -0.164629   0.349047   1.874955
...

我们可以使用 numpy.random.randint(...) 方法在一定范围内生成随机整数,然后使用 pandas.DataFrame.iloc[...] 属性从我们的 DataFrame 中进行随机替换采样(同一观察结果可能会被多次选择

以下代码块随机选择了五行,并进行了替换采样:

df.iloc[np.random.randint(0, len(df), size=5)]

这导致了以下随机子采样的 DataFrame:

A          B           C         D          E
54   0.692757  -0.584690  -0.176656   0.728395  -0.434987
98  -0.517141   0.109758  -0.132029   0.614610  -0.235801
29   0.589315  -0.968324  -0.432725   0.856653  -0.683398
35   0.520140   0.143652   0.973510   0.440253   1.307126
62  -0.266102   0.831051  -0.164629   0.349047   1.874955

在接下来的章节中,我们将探索使用 pandas.DataFrames 进行文件操作。

使用 pandas.DataFrames 探索文件操作

pandas 支持将 DataFrames 持久化到纯文本和二进制格式中。常见的文本格式是 CSV 和 JSON 文件,最常用的二进制格式是 Excel XLSX、HDF5 和 pickle。

在本书中,我们专注于纯文本持久化。

CSV 文件

CSV 文件(逗号分隔值 文件)是数据交换标准文件。

Python 金融交易实用指南(二)(4)https://developer.aliyun.com/article/1523759

相关文章
|
2月前
|
数据可视化 数据处理 Python
如何使用Python实现一个基于均线的交易策略
【10月更文挑战第9天】本文介绍了如何使用Python实现一个基于均线的交易策略。主要步骤包括导入所需库(如`pandas`、`numpy`和`matplotlib`),加载股票或期货的历史数据,计算均线和其他指标,实现交易策略逻辑,以及可视化交易结果。示例代码展示了如何根据均线交叉点进行开仓、止损和止盈操作,并提供了注意事项,如数据来源、交易成本和风险管理。
82 7
|
1月前
|
数据采集 数据可视化 数据处理
如何使用Python实现一个交易策略。主要步骤包括:导入所需库(如`pandas`、`numpy`、`matplotlib`)
本文介绍了如何使用Python实现一个交易策略。主要步骤包括:导入所需库(如`pandas`、`numpy`、`matplotlib`),加载历史数据,计算均线和其他技术指标,实现交易逻辑,记录和可视化交易结果。示例代码展示了如何根据均线交叉和价格条件进行开仓、止损和止盈操作。实际应用时需注意数据质量、交易成本和风险管理。
65 5
|
5月前
|
存储 分布式计算 数据可视化
Python 金融编程第二版(四)(2)
Python 金融编程第二版(四)
51 0
|
5月前
|
存储 SQL 数据可视化
Python 金融编程第二版(四)(1)
Python 金融编程第二版(四)
39 0
|
2月前
|
数据采集 人工智能 自然语言处理
AI Agent 金融助理0-1 Tutorial 利用Python实时查询股票API的FinanceAgent框架构建股票(美股/A股/港股) AI Finance Agent
金融领域Finance AI Agents方面的工作,发现很多行业需求和用户输入的 query都是和查询股价/行情/指数/财报汇总/金融理财建议相关。如果需要准确的 金融实时数据就不能只依赖LLM 来生成了。常规的方案包括 RAG (包括调用API )再把对应数据和prompt 一起拼接送给大模型来做文本生成。稳定的一些商业机构的金融数据API基本都是收费的,如果是以科研和demo性质有一些开放爬虫API可以使用。这里主要介绍一下 FinanceAgent,github地址 https://github.com/AI-Hub-Admin/FinanceAgent
|
5月前
|
机器学习/深度学习 存储 TensorFlow
使用Python实现深度学习模型:智能金融风控与信用评估
【7月更文挑战第25天】 使用Python实现深度学习模型:智能金融风控与信用评估
11257 7
|
4月前
|
数据可视化 数据挖掘 索引
【python】Python马铃薯批发市场交易价格数据分析可视化(源码+数据集)【独一无二】
【python】Python马铃薯批发市场交易价格数据分析可视化(源码+数据集)【独一无二】
122 0
|
3月前
|
机器学习/深度学习 数据采集 TensorFlow
使用Python实现智能股票交易策略
使用Python实现智能股票交易策略
75 0
|
3月前
|
机器学习/深度学习 数据采集 TensorFlow
使用Python实现智能金融市场预测
使用Python实现智能金融市场预测
44 0
|
4月前
|
数据可视化 数据挖掘 数据处理
【python】python淘宝交易数据分析可视化(源码+数据集)【独一无二】
【python】python淘宝交易数据分析可视化(源码+数据集)【独一无二】
144 1