利用Python做新能源公司股票分析(可视化)

Posted 卖山楂啦prss

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了利用Python做新能源公司股票分析(可视化)相关的知识,希望对你有一定的参考价值。

这篇文章只有一些代码,分析的内容很多,但是没有进行必要的解释

我也是第一次做,不是很懂股票,可能有一些错误。

# 导包
import numpy as np
import matplotlib.pyplot as plt
from pandas_datareader import data
from scipy.signal import find_peaks
from scipy.stats import norm
import pandas_datareader.data as web
import pandas_datareader.data as webdata
import datetime
import pandas as pd
import seaborn as sns # pip install seaborn
import matplotlib.patches as mpatches
from pyfinance import TSeries # pip install pyfinance
from empyrical import sharpe_ratio,omega_ratio,alpha_beta,stats # pip install empyrical
import warnings
warnings.filterwarnings('ignore')
tickers = ['F','TSLA','FSR','GM','NEE','SO','BYD','NIO','SOL','JKS'] 
startDate = '2019-06-01'
endDate = '2022-06-01'

F = webdata.get_data_stooq('F',startDate,endDate) # 福特
TSLA = webdata.get_data_stooq('TSLA',startDate,endDate) # 特斯拉
FSR = webdata.get_data_stooq('FSR',startDate,endDate)  # 杜克能源公司
GM = webdata.get_data_stooq('GM',startDate,endDate) # 通用汽车
NEE = webdata.get_data_stooq('NEE',startDate,endDate) # NextEra能源公司
SO = webdata.get_data_stooq('SO',startDate,endDate)# 南方公司
BYD = webdata.get_data_stooq('BYD',startDate,endDate)# 比亚迪
NIO = webdata.get_data_stooq('NIO',startDate,endDate) # 蔚来
SOL = webdata.get_data_stooq('SOL',startDate,endDate) # 瑞能新能源
JKS = webdata.get_data_stooq('JKS',startDate,endDate) # 法拉第未来

stocks = pd.DataFrame("F": F["Close"],
                      "TSLA": TSLA["Close"],
                      "FSR": FSR["Close"],
                      "GM": GM["Close"],
                       "NEE": NEE["Close"],
                       "SO": SO["Close"],
                       "BYD": BYD["Close"],
                       "NIO": NIO["Close"],
                       "SOL": SOL["Close"],
                        "JKS": JKS["Close"],
                      )

stocks


Plot the closing prices of the stocks

# 收盘价走势
plt.style.use('ggplot') # 样式
color_palette=sns.color_palette("hls",10) # 颜色
plt.rcParams['font.sans-serif']=['Microsoft YaHei']
fig = plt.figure(figsize = (16,12))
for i,j in enumerate(tickers):
    plt.subplot(5,2,i+1)
    stocks[j].plot(kind='line', style=['-'],color=color_palette[i],label=j)
    plt.xlabel('')
    plt.ylabel('closing prices')
    plt.title(' - closing prices Plot'.format(j))
    plt.legend()
plt.tight_layout()


Percentage change of closing price(day)

# 每日的收益率走势
# 通过上图可以看到,整体呈上下波动趋势,个别时间点波动性较大。
plt.style.use('ggplot')
color_palette=sns.color_palette("hls",10)
plt.rcParams['font.sans-serif']=['Microsoft YaHei']
fig = plt.figure(figsize = (16,12))
for i,j in enumerate(tickers):
    plt.subplot(5,2,i+1)
    stocks[j].pct_change().plot(kind='line', style=['-'],color=color_palette[i],label=j)
    plt.xlabel('')
    plt.ylabel('percentage')
    plt.title(' - Percentage change of closing price'.format(j))
    plt.legend()
plt.tight_layout()


Average daily return of closing price

# 日平均收益
for i in tickers:
    r_daily_mean = ((1+stocks[i].pct_change()).prod())**(1/stocks[i].shape[0])-1
    #print("%s - Average daily return:%f"%(i,r_daily_mean))
    print("%s - Average daily return is:%s"%(i,str(round(r_daily_mean*100,2))+"%"))

F - Average daily return is:0.05%
TSLA - Average daily return is:0.4%
FSR - Average daily return is:0.0%
GM - Average daily return is:0.02%
NEE - Average daily return is:0.06%
SO - Average daily return is:0.06%
BYD - Average daily return is:0.12%
NIO - Average daily return is:0.24%
SOL - Average daily return is:0.17%
JKS - Average daily return is:0.14%

# 日收益率的概率分布图
# 查看分布情况
plt.style.use('ggplot')
plt.rcParams['font.sans-serif']=['Microsoft YaHei']
fig = plt.figure(figsize = (16,12))
for i,j in enumerate(tickers):
    plt.subplot(5,2,i+1)
    sns.distplot(stocks[j].pct_change(), bins=100, color=color_palette[i])
    plt.ylabel('Daily Return')
    plt.title(' - Daily Return distribution'.format(j))
plt.tight_layout();

# 累积日收益率
# 累积日收益率有助于定期确定投资价值。可以使用每日百分比变化的数值来计算累积日收益率,只需将其加上1并计算累积的乘积。
# 累积日收益率是相对于投资计算的。如果累积日收益率超过1,就是在盈利,否则就是亏损。
plt.style.use('ggplot')
plt.rcParams['font.sans-serif']=['Microsoft YaHei']
fig = plt.figure(figsize = (16,12))
for i,j in enumerate(tickers):
    plt.subplot(5,2,i+1)
    cc = (1+stocks[j].pct_change()).cumprod()
    cc.plot(kind='line', style=['-'],color=color_palette[i],label=j)
    plt.xlabel('')
    plt.title(' - Cumulative daily return'.format(j))
    plt.legend()
plt.tight_layout()


Monthly return of closing price

# 月收益率
# 对月收益率进行可视化分析,标注收益率高于四分之三分位数的点。
# 月收益率围绕均线上下波动
fig = plt.figure(figsize = (16,12))
for i,j in enumerate(tickers):
    plt.subplot(5,2,i+1)
    daily_ret = stocks[j].pct_change()
    mnthly_ret = daily_ret.resample('M').apply(lambda x : ((1+x).prod()-1))
    mnthly_ret.plot(color=color_palette[i]) # Monthly return
    start_date=mnthly_ret.index[0]
    end_date=mnthly_ret.index[-1]
    plt.xticks(pd.date_range(start_date,end_date,freq='Y'),[str(y) for y in range(start_date.year+1,end_date.year+1)])
    # Show points with monthly yield greater than 3/4 quantile
    dates=mnthly_ret[mnthly_ret>mnthly_ret.quantile(0.75)].index   
    for i in range(0,len(dates)):
        plt.scatter(dates[i], mnthly_ret[dates[i]],color='r')
    labs = mpatches.Patch(color='red',alpha=.5, label="Monthly return higher than 3/4")
    plt.title('%s - Monthly  return of closing price'%j,size=15)
    plt.legend(handles=[labs])
plt.tight_layout()


Average monthly return

# 月平均收益
plt.style.use('ggplot')
plt.rcParams['font.sans-serif']=['Microsoft YaHei']
fig = plt.figure(figsize = (15,15))
for i,j in enumerate(tickers):
    plt.subplot(5,2,i+1)
    daily_ret = stocks[j].pct_change()
    mnthly_ret = daily_ret.resample('M').apply(lambda x : ((1+x).prod()-1))
    mrets=(mnthly_ret.groupby(mnthly_ret.index.month).mean()*100).round(2) 
    attr=[str(i)+'m' for i in range(1,13)]
    v=list(mrets)
    plt.bar(attr, v,color=color_palette[i],label=j)
    for a, b in enumerate(v):
        plt.text(a, b+0.08,b,ha='center',va='bottom')
    plt.title('- Average monthly return '.format(j))
    plt.legend()
plt.tight_layout()

# 图中显示某些月份具有正的收益率均值,而某些月份具有负的收益率均值,


Three year compound annual growth rate (CAGR)

复合年增长率(Compound Annual Growth Rate,CAGR)是一项投资在特定时期内的年度增长率
CAGR=(现有价值/基础价值)^(1/年数) - 1 或 (end/start)^(1/# years)-1

它是一段时间内的恒定回报率。换言之,该比率告诉你在投资期结束时,你真正获得的收益。它的目的是描述一个投资回报率转变成一个较稳定的投资回报所得到的预想值。

 # 复合年增长率(CAGR)
for i in tickers:
    days = (stocks[i].index[0] - stocks[i].index[-1]).days 
    CAGR_3 = (stocks[i][-1]/ stocks[i][0])** (365.0/days) - 1 
    print("%s (CAGR):%s"%(i,str(round(CAGR_3*100,2))+"%"))

F (CAGR):-12.74%
TSLA (CAGR):-63.6%
FSR (CAGR):-0.03%
GM (CAGR):-5.53%
NEE (CAGR):-14.94%
SO (CAGR):-14.14%
BYD (CAGR):-26.77%
NIO (CAGR):-44.8%
SOL (CAGR):-34.81%
JKS (CAGR):-29.16%


Annualized rate of return

# 年化收益率
# 年化收益率,是判断一只股票是否具备投资价值的重要标准!
# 年化收益率,即每年每股分红除以股价
for i in tickers:
    r_daily_mean = ((1+stocks[i].pct_change()).prod())**(1/stocks[i].shape[0])-1
    annual_rets = (1+r_daily_mean)**252-1
    print("%s'annualized rate of return is:%s"%(i,str(round(annual_rets*100,2))+"%"))

F’annualized rate of return is:14.56%
TSLA’annualized rate of return is:174.14%
FSR’annualized rate of return is:0.03%
GM’annualized rate of return is:5.84%
NEE’annualized rate of return is:17.53%
SO’annualized rate of return is:16.43%
BYD’annualized rate of return is:36.45%
NIO’annualized rate of return is:80.92%
SOL’annualized rate of return is:53.24%
JKS’annualized rate of return is:41.06%


maximum drawdowns

最大回撤率(Maximum Drawdown),它用于测量在投资组合价值中,在下一次峰值来到之前,最高点和最低点之间的最大单次下降。换言之,该值代表了基于某个策略的投资组合风险。

“最大回撤率是指在选定周期内任一历史时点往后推,产品净值走到最低点时的收益率回撤幅度的最大值。最大回撤用来描述买入产品后可能出现的最糟糕的情况。最大回撤是一个重要的风险指标,对于对冲基金和数量化策略交易,该指标比波动率还重要。”
最大回撤率超过了自己的风险承受范围,建议谨慎选择。

# 最大回撤率
def getMaxDrawdown(x):
    j = np.argmax((np.maximum.accumulate(x) - x) / x)
    if j == 0:
        return 0
    i = np.argmax(x[:j])
    d = (x[i] - x[j]) / x[i] * 100
    return d
for i in tickers:
    MaxDrawdown = getMaxDrawdown(stocks[i])
    print("%s maximum drawdowns:%s"%(i,str(round(MaxDrawdown,2))+"%"))

F maximum drawdowns:59.97%
TSLA maximum drawdowns:60.63%
FSR maximum drawdowns:0%
GM maximum drawdowns:57.53%
NEE maximum drawdowns:35.63%
SO maximum drawdowns:38.43%
BYD maximum drawdowns:77.43%
NIO maximum drawdowns:79.77%
SOL maximum drawdowns:88.88%
JKS maximum drawdowns:65.44%


calmer ratios for the top performers

# calmar率
# Calmar比率(Calmar Ratio) 描述的是收益和最大回撤之间的关系。计算方式为年化收益率与历史最大回撤之间的比率。
# Calmar比率数值越大,股票表现越好。
def performance(i):
    a = stocks[i].pct_change()
    s = a.values
    idx = a.index
    tss = TSeries(s, index=idx)
    dd=
    dd['anlzd_ret']=str(round(tss.anlzd_ret()*100,2))+"%"
    dd['cuml_ret']=str(round(tss.cuml_ret()*100,2))+"%"
    dd['max_drawdown']=str(round(tss.max_drawdown()*100,2))+"%"
    dd['sortino_ratio']=str(round(tss.sortino_ratio(freq=250),2))+"%"
    dd['calmar_ratio']=str(round(tss.calmar_ratio()*100,2))+"%"
    dd['sharpe_ratio'] = str(round(sharpe_ratio(tss)*100,2))+"%" # 夏普比率(Sharpe Ratio):风险调整后的收益率.计算投资组合每承受一单位总风险,会产生多少的超额报酬。
    dd['annual_volatility'] = str(round(stats.annual_volatility(tss)*100,2))+"%" # 波动率
    dd['omega_ratio'] = str(round(omega_ratio(tss)*100,2))+"%" # omega_ratio
    df=pd.DataFrame(dd.values(),index=dd.keys(),columns = [i])
    return df
dff = pd.DataFrame()
for i in tickers:
    dd = performance(i)
    dff = pd.concat([dff,dd],axis=1)
dff


Volatility

# 日收益率的年度波动率(滚动)

fig = plt.figure(figsize = (利用Python做新能源公司股票分析(可视化)

python 分析股票收益

利用Python实现股票可视做T盈亏

如何用python计算某支股票持有90天的收益率

R语言使用tidyquant包的tq_transmute函数计算持有某只股票的天月周收益率ggplot2使用条形图(bar plot)可视化股票年收益率数据使用不同的色彩表征正收益率和负收益率

R语言tidyquant包的tq_transmute函数计算持有某只股票的天月周收益率ggplot2使用条形图(bar plot)可视化股票月收益率数据条形图