python数据分析Pandas案例之股票分析

数据分析之股票分析案例

本案例总结涉及Pandas重要知识点如下:
  • 了解tushare模块的使用

  • 了解shift()函数的使用

  • 了解resample() 函数的使用

  • 还有set_index()的使用,还需要注意pd.to_datetime(df['trade_date'])此处更改为df['trade_date'].astype(str) 否则会转换失败,日期全变为1970年。即:df['trade_date']=pd.to_datetime(df['trade_date'].astype(str))

  • 知道loc[]函数还可以根据逻辑bool值来定位

  • 了解了rolling()函数来计算均线

  • 了解了金融知识之均线,金叉与死叉的概念

  • 了解使用了级联操作函数concat()

需求如下:
  • 1.使用tushare包获取某股票的历史行情数据。

  • 2.输出该股票所有收盘比开盘上涨3%以上的日期。

  • 3.输出该股票所有开盘比前日收盘跌幅超过2%的日期。

  • 4.计算:假如我从2010年1月1日开始,每月第一个交易日买入1手股票,每年最后一个交易日卖出所有股票,到今天为止,我的收益如何?

  • 5.计算该股票历史数据的5日均线和30日均线

  • 6.可视化历史数据的收盘价和两条均线

  • 7.分析输出所有金叉日期和死叉日期

  • 8.计算:如果我从假如我从2010年1月1日开始,初始资金为100000元,金叉尽量买入,死叉全部卖出,则到今天为止,我的炒股收益率如何?

  • tushare财经数据接口包

    • pip install tushare
1.使用tushare包获取某股票的历史行情数据。
  • tushare官方文档api介绍

  • 我们需要先去tushare注册一个账号,获取接口token

  • 然后利用下方函数ts.set_token('your_token'),当然也可以直接pro=ts.pro_api('your_token')

  • 如果要获取别的股票数据参考官方给的api使用方式

  • 下方我调用的是daily来获取茅台历史所有数据,具体使用方式请参考上方文档链接

import tushare as ts
import pandas as pd
from pandas import DataFrame,Series
import numpy as np
ts.set_token('your_token')
pro=ts.pro_api()
df=pro.daily(ts_code='600519.SH', start_date='20000101')
df.to_csv('./maotai.csv')
  • 上方代码成功读取茅台的历史股票日数据,并把它存到了本地csv文件中

  • csv文件如下:

  • 在这里插入图片描述

  • 我们成功取到了近5000多条数据。

2.输出该股票所有收盘比开盘上涨3%以上的日期。
  • 1.首先读出数据

  • df=pd.read_csv('./maotai.csv')
    print(df.head())
    
  • out:

  •    Unnamed: 0    ts_code  trade_date  ...  pct_chg       vol       amount
    0           0  600519.SH    20240717  ...   1.7209  34311.01  5115680.654
    1           1  600519.SH    20240716  ...   0.0746  20316.44  2998367.128
    2           2  600519.SH    20240715  ...  -0.2651  19176.26  2835374.730
    3           3  600519.SH    20240712  ...   1.1443  23386.34  3451132.648
    4           4  600519.SH    20240711  ...   1.7042  29020.14  4236960.596
    
    [5 rows x 12 columns]
    
    进程已结束,退出代码为 0
    
  • 2.我们发现多出了一列Unnamed: 0,因此我们需要将此列删除

  • #删除df中指定的一列
    df.drop(labels='Unnamed: 0',axis=1,inplace=True) #drop函数特殊,axis=1时为列
    
  • 3.查看每一列的数据类型

    df.info()
    

    out:

    <class 'pandas.core.frame.DataFrame'>
    RangeIndex: 5479 entries, 0 to 5478
    Data columns (total 11 columns):
     #   Column      Non-Null Count  Dtype  
    ---  ------      --------------  -----  
     0   ts_code     5479 non-null   object 
     1   trade_date  5479 non-null   int64  
     2   open        5479 non-null   float64
     3   high        5479 non-null   float64
     4   low         5479 non-null   float64
     5   close       5479 non-null   float64
     6   pre_close   5479 non-null   float64
     7   change      5479 non-null   float64
     8   pct_chg     5479 non-null   float64
     9   vol         5479 non-null   float64
     10  amount      5479 non-null   float64
    dtypes: float64(9), int64(1), object(1)
    memory usage: 471.0+ KB
    None
    
    进程已结束,退出代码为 0
    
  • 4.我们发现trade_date时int64类型,我们可以把它转换成日期,并设置为索引,方便后续操作

  • df['trade_date']=pd.to_datetime(df['trade_date'])
    				#此处更改为df['trade_date'].astype(str) 否则会转换失败
    df.set_index('trade_date',inplace=True)
    print(df.head())
    
  • out

  •                                           ts_code     open    high  ...  pct_chg       vol       amount
    trade_date                              ...                                
    2024-07-17  600519.SH  1476.10  1503.0  ...   1.7209  34311.01  5115680.654
    2024-07-16  600519.SH  1476.00  1482.0  ...   0.0746  20316.44  2998367.128
    2024-07-15  600519.SH  1470.00  1488.0  ...  -0.2651  19176.26  2835374.730
    2024-07-12  600519.SH  1473.01  1486.4  ...   1.1443  23386.34  3451132.648
    2024-07-11  600519.SH  1449.97  1469.0  ...   1.7042  29020.14  4236960.596
    
    [5 rows x 10 columns]
    
    进程已结束,退出代码为 0
    
  • 5.这里我们利用loc函数支持逻辑运算来索引的方式获取

  • 例如逻辑运算返回结果如下:

  • print((df['close']-df['open'])/df['open']>0.03)
    
  • out

  • trade_date
    2024-07-17    False
    2024-07-16    False
    2024-07-15    False
    2024-07-12    False
    2024-07-11    False
                  ...  
    2001-08-31    False
    2001-08-30    False
    2001-08-29    False
    2001-08-28     True
    2001-08-27     True
    Length: 5479, dtype: bool
    
    进程已结束,退出代码为 0
    
  • 我们可以用这个逻辑结果去用loc取对应的行,如果为true则返回,false则不会返回

  • date=df.loc[(df['close']-df['open'])/df['open']>0.03] #获取符合条件的dataframe数据
    print(date.index)  #索引即为日期,我们取索引
    
  • 6.返回的就是符合要求的日期:

  • DatetimeIndex(['2024-07-02', '2024-06-24', '2024-03-12', '2024-02-21',
                   '2023-12-28', '2023-07-28', '2023-05-22', '2023-01-05',
                   '2022-11-15', '2022-11-04',
                   ...
                   '2004-01-14', '2004-01-05', '2003-10-29', '2003-01-14',
                   '2002-01-31', '2002-01-18', '2001-12-21', '2001-09-10',
                   '2001-08-28', '2001-08-27'],
                  dtype='datetime64[ns]', name='trade_date', length=356, freq=None)
    
    进程已结束,退出代码为 0
    
3.输出该股票所有开盘比前日收盘跌幅超过2%的日期。
  • 1.逻辑表达式为:(开盘-前日收盘)/前日收盘 < -0.02

  • 2.我们可以将close列向下移1位,这样对应的df[‘close’]就是对应的前日的闭盘数据了,我们用到了shift()函数

  • print(df['close'].shift(1))
    
  • out

  • trade_date
    2024-07-17        NaN
    2024-07-16    1501.40
    2024-07-15    1476.00
    2024-07-12    1474.90
    2024-07-11    1478.82
                   ...   
    2001-08-31      36.99
    2001-08-30      37.01
    2001-08-29      37.10
    2001-08-28      36.38
    2001-08-27      36.86
    Name: close, Length: 5479, dtype: float64
    
    进程已结束,退出代码为 0
    
  • 3.因此用于loc函数的逻辑表达式为:

  • (df['open'] - df['close']) / df['open'] > 0.03
    
  • 4.使用loc()函数获取符合条件的数据:

    • 在分析的过程中如果产生了boolean值则下一步马上将布尔值作为源数据的行索引
    • 如果布尔值作为df的行索引,则可以取出true对应的行数据,忽略false对应的行数据
  • df.loc[(df['open'] - df['close']) / df['open'] > 0.03]
    
  • 5.从符合条件的表格中获取日期索引即为符合题意的日期

  • #在分析的过程中如果产生了boolean值则下一步马上将布尔值作为源数据的行索引
     #如果布尔值作为df的行索引,则可以取出true对应的行数据,忽略false对应的行数据
    print(df.loc[(df['open'] - df['close']) / df['open'] > 0.03].index)
    
  • out

  • DatetimeIndex(['2024-01-17', '2023-11-01', '2023-10-19', '2023-08-28',
                   '2023-04-12', '2022-10-27', '2022-10-24', '2022-10-19',
                   '2022-10-10', '2022-03-07',
                   ...
                   '2003-01-02', '2002-11-08', '2002-04-17', '2002-01-28',
                   '2002-01-17', '2002-01-04', '2001-12-20', '2001-11-16',
                   '2001-11-07', '2001-10-10'],
                  dtype='datetime64[ns]', name='trade_date', length=198, freq=None)
    
    进程已结束,退出代码为 0
    
4.收益计算
  • 假如我从2010年1月1日开始,每月第一个交易日买入1手股票,每年最后一个交易日卖出所有股票,到今天为止,我的收益如何?

  • 分析:

    • 时间节点:2010-2024
    • 一手股票:100支股票
    • 买:
      • 一个完整的年需要买入1200支股票
    • 卖:
      • 一个完整的年需要卖出1200支股票
    • 买卖股票的单价:
      • 开盘价
  • 1.首先我们需要切片出我们所需的时间段,因为时间格式是索引,因此可以直接这样切:

  • new_df = df['2010-01':'2024-07']
    print(new_df)
    
  • out

  •              ts_code     open     high  ...  pct_chg       vol       amount
    trade_date                               ...                                
    2024-07-17  600519.SH  1476.10  1503.00  ...   1.7209  34311.01  5115680.654
    2024-07-16  600519.SH  1476.00  1482.00  ...   0.0746  20316.44  2998367.128
    2024-07-15  600519.SH  1470.00  1488.00  ...  -0.2651  19176.26  2835374.730
    2024-07-12  600519.SH  1473.01  1486.40  ...   1.1443  23386.34  3451132.648
    2024-07-11  600519.SH  1449.97  1469.00  ...   1.7042  29020.14  4236960.596
    ...               ...      ...      ...  ...      ...       ...          ...
    2010-01-08  600519.SH   164.00   164.00  ...  -1.0500  36702.09   593162.176
    2010-01-07  600519.SH   166.76   167.19  ...  -1.8200  48825.55   801445.269
    2010-01-06  600519.SH   168.99   169.50  ...  -1.5800  39889.03   666073.283
    2010-01-05  600519.SH   170.99   171.50  ...  -0.2900  31513.18   535720.422
    2010-01-04  600519.SH   172.00   172.00  ...   0.0700  44304.88   753405.635
    
    [3525 rows x 10 columns]
    
    进程已结束,退出代码为 0
    
    
  • 2.接下来我们要获取每月第一个交易日的数据,我们可以用到resample()函数,并用sum函数求和

  • 注意!!!!卡了我好久!注意下方两参数数据区别!时间索引不一样!但数据是一样的!

  • print(new_df.resample('M').first())
    print(new_df.resample('MS').first())
    
  • out

  •               ts_code     open     high      low    close  pre_close  change  \
    trade_date                                                                     
    2010-01-31  600519.SH   172.00   172.00   169.31   169.94     169.82    0.12   
    2010-02-28  600519.SH   168.88   169.58   167.01   168.89     168.54    0.35   
    2010-03-31  600519.SH   166.45   167.45   165.99   166.24     166.84   -0.60   
    2010-04-30  600519.SH   158.78   160.50   158.76   160.06     158.76    1.30   
    2010-05-31  600519.SH   127.99   129.56   126.89   128.64     129.03   -0.39   
    ...               ...      ...      ...      ...      ...        ...     ...   
    2019-10-31  600519.SH  1153.00  1180.00  1152.01  1167.10    1150.00   17.10   
    2019-11-30  600519.SH  1181.00  1191.95  1172.50  1185.00    1180.01    4.99   
    2019-12-31  600519.SH  1118.20  1140.02  1118.20  1133.00    1129.00    4.00   
    2020-01-31  600519.SH  1128.00  1145.06  1116.00  1130.00    1183.00  -53.00   
    2020-02-29  600519.SH   985.00  1010.68   980.00  1003.92    1052.80  -48.88   
    
                pct_chg        vol        amount  
    trade_date                                    
    2010-01-31   0.0700   44304.88  7.534056e+05  
    2010-02-28   0.2100   29655.94  4.998670e+05  
    2010-03-31  -0.3600   21734.74  3.615503e+05  
    2010-04-30   0.8200   23980.83  3.832288e+05  
    2010-05-31  -0.3000   23975.16  3.085046e+05  
    ...             ...        ...           ...  
    2019-10-31   1.4870   31045.27  3.631091e+06  
    2019-11-30   0.4229   22811.96  2.697638e+06  
    2019-12-31   0.3543   30784.41  3.479717e+06  
    2020-01-31  -4.4801  148099.16  1.669684e+07  
    2020-02-29  -4.6429  123442.88  1.231499e+07  
    
    [122 rows x 10 columns]
                  ts_code     open     high      low    close  pre_close  change  \
    trade_date                                                                     
    2010-01-01  600519.SH   172.00   172.00   169.31   169.94     169.82    0.12   
    2010-02-01  600519.SH   168.88   169.58   167.01   168.89     168.54    0.35   
    2010-03-01  600519.SH   166.45   167.45   165.99   166.24     166.84   -0.60   
    2010-04-01  600519.SH   158.78   160.50   158.76   160.06     158.76    1.30   
    2010-05-01  600519.SH   127.99   129.56   126.89   128.64     129.03   -0.39   
    ...               ...      ...      ...      ...      ...        ...     ...   
    2019-10-01  600519.SH  1153.00  1180.00  1152.01  1167.10    1150.00   17.10   
    2019-11-01  600519.SH  1181.00  1191.95  1172.50  1185.00    1180.01    4.99   
    2019-12-01  600519.SH  1118.20  1140.02  1118.20  1133.00    1129.00    4.00   
    2020-01-01  600519.SH  1128.00  1145.06  1116.00  1130.00    1183.00  -53.00   
    2020-02-01  600519.SH   985.00  1010.68   980.00  1003.92    1052.80  -48.88   
    
                pct_chg        vol        amount  
    trade_date                                    
    2010-01-01   0.0700   44304.88  7.534056e+05  
    2010-02-01   0.2100   29655.94  4.998670e+05  
    2010-03-01  -0.3600   21734.74  3.615503e+05  
    2010-04-01   0.8200   23980.83  3.832288e+05  
    2010-05-01  -0.3000   23975.16  3.085046e+05  
    ...             ...        ...           ...  
    2019-10-01   1.4870   31045.27  3.631091e+06  
    2019-11-01   0.4229   22811.96  2.697638e+06  
    2019-12-01   0.3543   30784.41  3.479717e+06  
    2020-01-01  -4.4801  148099.16  1.669684e+07  
    2020-02-01  -4.6429  123442.88  1.231499e+07  
    
    [122 rows x 10 columns]
    
  • 还是对resample的参数不够了解,故总结如下:

    • 在 Pandas 的 resample 方法中,还有许多其他的频率代码可以用来指定不同的重采样频率。这些频率代码主要用于处理时间序列数据,可以根据需求来选择适合的频率。以下是一些常用的频率代码及其含义:

      • B: 工作日频率(Business day)
      • D: 天频率(Calendar day)
      • W: 周频率(Weekly)
      • M: 月末频率(Month end)
      • MS: 月初频率(Month start)
      • Q: 季度末频率(Quarter end)
      • BM: 月末工作日频率(Business month end)
      • BQ: 季度末工作日频率(Business quarter end)
      • H: 小时频率(Hourly)
      • Tmin: 分钟频率(Minutely)
      • S: 秒频率(Secondly)
      • L: 毫秒频率(Millisecond)
      • U: 微秒频率(Microsecond)

      此外,还有一些复合频率代码,可以更加灵活地控制重采样的行为,例如:

      • 2W: 每两周
      • 3Q: 每三个季度末
      • 5T: 每五分钟
        • 你可以根据具体的需求和时间序列数据的特性,选择合适的频率代码来进行重采样操作。这些频率代码在使用 resample 方法时可以指定为参数,以便对时间序列数据进行不同粒度的统计和汇总。
  • 3.计算购买股票花费的钱总和

  • df_month_first=new_df.resample('M').first()
    cost_monney=df_month_first['open'].sum()*100
    print(cost_monney)
    
  • out:

  • 13690045.000000002
    
    进程已结束,退出代码为 0
    
  • 4.接下来每年末卖出去这一年买的所有股票,而本年(2024)的股票就按最后一天的收盘价卖出吧

  • print(new_df.resample('A').last())
    
  • out:

  •               ts_code     open     high  ...  pct_chg       vol       amount
    trade_date                               ...                                
    2010-12-31  600519.SH   181.80   184.28  ...   1.0900  46084.87   843075.733
    2011-12-31  600519.SH   192.70   194.88  ...   0.5700  29460.86   569875.567
    2012-12-31  600519.SH   213.31   214.80  ...  -1.5500  51914.83  1085776.117
    2013-12-31  600519.SH   124.00   129.31  ...   3.1500  57546.49   730676.611
    2014-12-31  600519.SH   185.60   190.00  ...   1.4900  46269.36   871581.692
    2015-12-31  600519.SH   218.22   219.50  ...  -0.3100  19673.87   429872.169
    2016-12-31  600519.SH   326.61   335.29  ...   2.0900  34687.67  1152982.239
    2017-12-31  600519.SH   718.00   726.50  ...  -2.9500  76038.87  5372514.665
    2018-12-31  600519.SH   563.30   596.40  ...   4.7975  63678.37  3705150.490
    2019-12-31  600519.SH  1183.00  1188.00  ...  -0.2361  22588.81  2666705.100
    2020-12-31  600519.SH  1941.00  1998.98  ...   3.3626  38860.07  7682300.728
    2021-12-31  600519.SH  2070.00  2072.98  ...  -1.2048  29664.91  6061415.344
    2022-12-31  600519.SH  1736.00  1752.99  ...   0.4654  25333.12  4409544.297
    2023-12-31  600519.SH  1720.00  1749.58  ...   0.0586  27538.68  4768857.531
    2024-12-31  600519.SH  1473.01  1486.40  ...   1.1443  23386.34  3451132.648
    
    [15 rows x 10 columns]
    
    进程已结束,退出代码为 0
    
  • 5.现在才2024年7月份,可见resample的时间索引是假的,并非真实的,其返回的数据只不过是该年的最后一项数据而已,因此我们把最后一行数据切掉,即new_df.resample('A').last()[:-1]

  • get_monney=new_df.resample('A').last()[:-1]['open'].sum()*1200 #每年最后一个交易日的开盘价卖出
    print(get_monney)
    this_year_monney=700*new_df[-1:]['close'].sum()  #为什么*700,因为现在是7月,已经买了7手了,现在全部抛光
    print(this_year_monney)
    print('总利润为:',get_monney+this_year_monney-cost_monney)
    
  • out

  • 13648248.000000002
    1035174.0
    总利润为: 993377.0
    
    进程已结束,退出代码为 0
    
5.双均线策略制定
必备概念
  • 什么是均线?

    • 对于每一个交易日,都可以计算出前N天的移动平均值,然后把这些移动平均值连起来,成为一条线,就叫做N日移动平均线。移动平均线常用线有5天、10天、30天、60天、120天和240天的指标。
    • 5天和10天的是短线操作的参照指标,称做日均线指标;
    • 30天和60天的是中期均线指标,称做季均线指标;
    • 120天和240天的是长期均线指标,称做年均线指标。
  • 均线计算方法:MA=(C1+C2+C3+...+Cn)/N C:某日收盘价 N:移动平均周期(天数)

  • 股票分析技术中的金叉死叉,可以简单解释为:

    • 分析指标中的两根线,一根为短时间内的指标线,另一根为较长时间的指标线。
    • 如果短时间的指标线方向拐头向上,并且穿过了较长时间的指标线,这种状态叫“金叉”;
    • 如果短时间的指标线方向拐头向下,并且穿过了较长时间的指标线,这种状态叫“死叉”;
    • 一般情况下,出现金叉后,操作趋向买入;死叉则趋向卖出。当然,金叉和死叉只是分析指标之一,要和其他很多指标配合使用,才能增加操作的准确性。
要求如下:
  • 1.计算该股票历史数据的5日均线和30日均线

  • 2.可视化历史数据的收盘价和两条均线

  • 3.分析输出所有金叉日期和死叉日期

1.计算该股票历史数据的5日均线和30日均线
  • rolling()函数的使用计算均线

  • m5 = df['close'].rolling(5).mean()
    m30 = df['close'].rolling(30).mean()
    print(m5)
    print(m30)
    

out:

  • trade_date
    2001-08-27         NaN #前4天不能算5日均线,故为空值
    2001-08-28         NaN
    2001-08-29         NaN
    2001-08-30         NaN
    2001-08-31      36.580
                    ...   
    2024-07-11    1442.142
    2024-07-12    1447.306
    2024-07-15    1458.286
    2024-07-16    1465.880
    2024-07-17    1478.642
    Name: close, Length: 5479, dtype: float64
    trade_date
    2001-08-27            NaN #前30天不能算30日均线,故为空值
    2001-08-28            NaN
    2001-08-29            NaN
    2001-08-30            NaN
    2001-08-31            NaN
                     ...     
    2024-07-11    1527.221667
    2024-07-12    1521.549000
    2024-07-15    1515.764000
    2024-07-16    1510.317667
    2024-07-17    1505.257667
    Name: close, Length: 5479, dtype: float64
    
    进程已结束,退出代码为 0
    
2.可视化历史数据的收盘价和两条均线
  • 两条均线(完整)

    • import matplotlib.pyplot as plt
      m5 = df['close'].rolling(5).mean()
      m30 = df['close'].rolling(30).mean()
      plt.plot(m5)
      plt.plot(m30)
      plt.show()
      

在这里插入图片描述

  • 两条均线(局部一部分)
import matplotlib.pyplot as plt
plt.plot(m5[30:200]) #最早也只能从30开始,因为30日均线前29条数据为nan
plt.plot(m30[30:200])
plt.show()

out:

  • 在这里插入图片描述

  • 收盘价:

    • import matplotlib.pyplot as plt
      plt.plot(df['close'])
      plt.show()
      
    • out

    • 在这里插入图片描述

3.分析输出所有金叉日期和死叉日期
  • 原理图:
    - ![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=%E9%87%91%E5%8F%89%E6%AD%BB%E5%8F%89(1&pos_id=img-CuUZ9FTR-1721289871267).png)

  • 1.获取s1和s2的bool逻辑关系

    m5=m5[30:]
    m30=m30[30:]
    s1=m5<m30
    s2=m5>m30
    print(s1.head(),s2.head())
    
  • 2.切割源数据大小等于s1s2的大小,因为loc函数中的bool逻辑关系条数要与源数据相同,因此切割。

  • df=df[30:]
    
  • 3.获取死叉日期

  • death = s1 & s2.shift(1) #判定死叉的条件
    df.loc[death] #死叉对应的行数据
    death_date=df.loc[death].index
    print(death_date)
    
  • out:

  • DatetimeIndex(['2002-01-17', '2002-01-30', '2002-03-29', '2002-07-25',
                   '2002-12-27', '2003-03-17', '2003-04-22', '2003-06-20',
                   '2003-06-30', '2004-02-27',
                   ...
                   '2022-10-10', '2023-02-08', '2023-02-23', '2023-04-12',
                   '2023-08-21', '2023-09-11', '2023-09-26', '2023-12-05',
                   '2024-04-09', '2024-05-24'],
                  dtype='datetime64[ns]', name='trade_date', length=119, freq=None)
    
    进程已结束,退出代码为 0
    
  • 4.获取金叉日期

  • golden = ~(s1 | s2.shift(1))#判定金叉的条件
    golden_date = df.loc[golden].index #金叉的时间
    print(golden_date)
    
  • out

    • DatetimeIndex(['2001-11-22', '2002-01-24', '2002-02-04', '2002-06-21',
                     '2002-12-05', '2003-01-16', '2003-04-15', '2003-05-30',
                     '2003-06-24', '2003-10-13',
                     ...
                     '2022-09-29', '2022-11-18', '2023-02-14', '2023-03-31',
                     '2023-06-15', '2023-08-30', '2023-09-22', '2023-11-06',
                     '2024-02-08', '2024-04-26'],
                    dtype='datetime64[ns]', name='trade_date', length=119, freq=None)
      
      进程已结束,退出代码为 0
      
      
4.金叉死叉收益计算
  • 如果我从假如我从2010年1月1日开始,初始资金为100000元,金叉尽量买入,死叉全部卖出,则到今天为止,我的炒股收益率如何?

  • 分析:

    • 买卖股票的单价使用开盘价
    • 买卖股票的时机
    • 最终手里会有剩余的股票没有卖出去
      • 会有。如果最后一天为金叉,则买入股票。估量剩余股票的价值计算到总收益。
        • 剩余股票的单价就是用最后一天的收盘价。
  • 1.金叉买入,死叉卖出,因此我们需要将金叉和死叉的日期合在一起,并按日期排序,然后循环一遍这些日期,不断重复买和卖即可,因此合并操作如下:

    • s1 = Series(data=1,index=golden_date) #1作为金叉的标识 golden_date 为金叉日期列表
      s2 = Series(data=0,index=death_date) #0作为死叉的标识
      s=pd.concat((s1,s2),axis=0)
      s = s.sort_index()
      s = s['2010':]##存储的是2010年以后金叉和死叉对应的时间
      print(s)
      
    • out

    • trade_date
      2010-01-20    1
      2010-01-22    0
      2010-02-03    1
      2010-02-26    0
      2010-06-04    1
                   ..
      2023-12-05    0
      2024-02-08    1
      2024-04-09    0
      2024-04-26    1
      2024-05-24    0   #最后一个日期为死叉,全部卖出,不用考虑后面金叉买进来而未卖出去的情况
      Length: 154, dtype: int64
      
      进程已结束,退出代码为 0
      
  • 2.根据s中的数据模拟买卖,循环一遍即可

    • 代码如下:

      • principal = 100000 #本金,不变
        money = principal #可变的,买股票话的钱和卖股票收入的钱都从该变量中进行操作
        hold = 0 #持有股票的数量(股数:100股=1手)
        for i in range(0,len(s)): #i表示的s这个Series中的隐式索引
            #i = 0(死叉:卖) = 1(金叉:买)
            if s[i] == 1:#金叉的时间
                #基于100000的本金尽可能多的去买入股票
                #获取股票的单价(金叉时间对应的行数据中的开盘价)
                time = s.index[i] #金叉的时间
                p = df.loc[time]['open'] #股票的单价
                hand_count = money // (p*100) #使用100000最多买入多少手股票
                hold = hand_count * 100        
                money -= (hold * p) #将买股票话的钱从money中减去
            else:
                #将买入的股票卖出去        
                #找出卖出股票的单价
                death_time = s.index[i]
                p_death = df.loc[death_time]['open'] #卖股票的单价
                money += (p_death * hold) #卖出的股票收入加入到money
                hold = 0
        #如何判定最后一天为金叉还是死叉
        last_money = hold * df['close'][-1] #剩余股票的价值
        
        #总收益
        sum_money=money + last_money - principal
        print(sum_money)
        
      • out

      • 1760385.0
        
        进程已结束,退出代码为 0
        
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值