相信大多数的打工一族也像我一样,每个月工资下来,还完消费账单,支付房租甚至是房贷车贷之后,手头留存已经是所剩无几,日子总是过得很拮据,总是想着有没有办法能够让自己的手头变得宽裕一些,虽然进行长期投资没有办法让你短时间内变成富翁,但是提早规划你手头上的资金即便很少,积少成多,你会发现合理规划投资,让财富增长并不是一件遥远的事情;我是一个风险规避型的投资者,所以我不太敢购买股票,但是我也希望能够让自己手头上的资金不断增长,所以我选择了风险较为中等的投资方式,投资基金;下面分享一些我平时选择基金的一些原则和方法给大家,文末还有通过PYTHON爬取基金数据,进行基金表现数据监控的干货哦,希望对python爬虫有兴趣的朋友有帮助;
一、基金选择
1.基金种类:本人主要以混合基金为主,买入方式主要为“半定投”(指设置指定时间定投,但是如果定投当天基金出现上涨趋势则会取消当期定投,选择该周期内其他基金出现下降的时间买入)
2.单只基金选择:
2.1 基金公司:主要筛选4星以上的基金公司基金
2.2 基金:选择2.1基金公司中的4星以上的基金进行定投
3.买入卖出策略:
3.1通过python爬虫将基金公司的星级数据爬取下来后筛选4星以上的基金公司;
3.2 通过python爬取基金的评级和历史的收益数据,筛选评级和历史收益较高的基金
3.3 对3.2预先筛选的部分基金结合3.1的基金公司星级和基金经理的星级进行综合评估,决定最后进行投资的基金;
同时对选择的基金收益进行分析,参考历史收益情况在不同的时间段设置不同的买入卖出策略;
以下附上爬取基金收益数据的python代码,希望大家都能够实现财富自由,加油!
# 导入需要的模块
import requests
from bs4 import BeautifulSoup
import re
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib
import datetime
# 发送邮件
import smtplib
import email
from email.mime import multipart # import MIMEMultipart
from email.mime import text # import MIMEText
from email.mime import base # import MIMEBase
import os.path
import mimetypes
# 导入数据库相关库
import pymysql
from sqlalchemy import create_engine
#online() #needed for online viewing
#plt.rcParams['fon.sans-serif']=['SimHei'] #用来正常显示中文标签
#plt.rcParams['axes.unicode_minus']=False #用来正常显示负号
#用中文出现的情况,需要u'内容'
#指定默认字体
#matplotlib.rcParams['font.sans-serif'] = ['SimHei']
#matplotlib.rcParams['font.family']='sans-serif'
matplotlib.rcParams['font.sans-serif'] = ['SimHei'] #用来正常显示中文标签
matplotlib.rcParams['font.family']='sans-serif'
matplotlib.rc('font', serif='Microsoft YaHei UI') #指定微软雅黑字体类型
matplotlib.rcParams.update({'font.size': 12}) #字号
#解决负号'-'显示为方块的问题
matplotlib.rcParams['axes.unicode_minus'] = False
#解决负号'-'显示为方块的问题
matplotlib.rcParams['axes.unicode_minus'] = False
# 抓取网页
def get_url(url, params=None, proxies=None):
rsp = requests.get(url, params=params, proxies=proxies)
rsp.raise_for_status()
return rsp.text
# 从网页抓取数据
def get_fund_data(code,per=10,sdate='',edate='',proxies=None):
url = 'http://fund.eastmoney.com/f10/F10DataApi.aspx'
params = {'type': 'lsjz', 'code': code, 'page':1,'per': per, 'sdate': sdate, 'edate': edate}
html = get_url(url, params, proxies)
soup = BeautifulSoup(html, 'html.parser')
# 获取总页数
pattern=re.compile(r'pages:(.*),')
result=re.search(pattern,html).group(1)
pages=int(result)
# 获取表头
heads = []
for head in soup.findAll("th"):
heads.append(head.contents[0])
# 数据存取列表
records = []
# 从第1页开始抓取所有页面数据
page=1
while page<=pages:
params = {'type': 'lsjz', 'code': code, 'page':page,'per': per, 'sdate': sdate, 'edate': edate}
html = get_url(url, params, proxies)
soup = BeautifulSoup(html, 'html.parser')
# 获取数据
for row in soup.findAll("tbody")[0].findAll("tr"):
row_records = []
for record in row.findAll('td'):
val = record.contents
# 处理空值
if val == []:
row_records.append(np.nan)
else:
row_records.append(val[0])
# 记录数据
records.append(row_records)
# 下一页
page=page+1
# 数据整理到dataframe
np_records = np.array(records) #array为矩阵的形式
try:
data= pd.DataFrame()
for col,col_name in enumerate(heads):#enumerate对列表、元组等类型操作时,同时返回元素的索引和元素的值,默认索引从0开始,可以增加参数指定索引开始值(enumerate([],1))
data[col_name] = np_records[:,col]
return data
except:
pass
# 涨跌判断
def ifup(d):
df=[]
df1=[]
for i in d:
if float(i)>0:
df1="涨"
elif float(i)<0:
df1="跌"
elif float(i)==0:
df1="持平"
else:
df1=""
df.append(df1)
return df
# 邮箱认证
# "username": "***@***.com",
# "password": "******",
def Send_email(file_name_list, email_text, recei_list):
mail_info = {
"from": "***@***.com", # 自己的邮箱账号
"to": "******", # 接收邮件的对方账号
"hostname": "http://smtp.163.com",
"username": "***@***.com", # 开通smtp服务的邮箱账号
"password": "******", # 开通smtp服务的对应密码
"mail_subject": "test",
"mail_text": "hello, this is a test email, sended by python",
"mail_encoding": "utf-8"
}
server = smtplib.SMTP_SSL(mail_info["hostname"], port=465)
server.ehlo(mail_info["hostname"])
server.login(mail_info["username"], mail_info["password"]) # 仅smtp服务器需要验证时
# 构造MIMEMultipart对象做为根容器
main_msg = multipart.MIMEMultipart()
# 构造MIMEText对象做为邮件显示内容并附加到根容器
text_msg = text.MIMEText(email_text, _charset="utf-8")
main_msg.attach(text_msg)
# 构造MIMEBase对象做为文件附件内容并附加到根容器
for file_name in file_name_list:
## 读入文件内容并格式化 [方式1]
data = open(file_name, 'rb')
ctype, encoding = mimetypes.guess_type(file_name)
if ctype is None or encoding is not None:
ctype = 'application/octet-stream'
maintype, subtype = ctype.split('/', 1)
file_msg = base.MIMEBase(maintype, subtype)
file_msg.set_payload(data.read())
data.close()
email.encoders.encode_base64(file_msg) # 把附件编码
## 设置附件头
basename = os.path.basename(file_name)
file_msg.add_header('Content-Disposition', 'attachment', filename=basename, encoding='utf-8')
main_msg.attach(file_msg)
# 设置根容器属性
main_msg['From'] = mail_info['from']
main_msg['To'] = ';'.join(recei_list)
main_msg['Subject'] = email_text
main_msg['Date'] = email.utils.formatdate()
# 得到格式化后的完整文本
fullText = main_msg.as_string()
# 用smtp发送邮件
try:
server.sendmail(mail_info['from'], recei_list, fullText)
finally:
server.quit()
#此处发送2张dataframe样表为例,应该放入实际的数据分析任务代码
from pandas import DataFrame
# from main import Send_email
import datetime
import os
os.chdir('./')
# 主程序
if __name__ == "__main__":
url_fund = 'http://fund.eastmoney.com/js/fundcode_search.js'
r = requests.get(url_fund)
html = r.text
data = re.findall('"(.*?)"', html)
l = int(len(data) / 5)
df1 = []
df2 = []
for i in range(l - 1):
df1 = [data[5 * i], data[5 * i + 1], data[5 * i + 2], data[5 * i + 3], data[5 * i + 4]]
df2.append(df1)
df = pd.DataFrame(df2, columns=['基金代码', '基金拼音简称', '基金中文名称', '基金类型', '基金拼音全称'])
# 数据筛选后需要重置索引后才可以按照索引进行遍历
df = df[df['基金类型'] == "混合型"].reset_index(drop=True)
codes = ['110011', '050026', '003032']
names = ['易方达中小盘混合', '博时医疗保健行业混合A', '平安医疗健康混合']
# 测试使用实例
# codes = ['110011', '050026']
# names = ['易方达中小盘混合', '博时医疗保健行业混合A']
data_all =[]
for i in range(len(codes)):
data=get_fund_data(codes[i],per=49,sdate='2015-01-01',edate=datetime.datetime.now().strftime('%Y-%m-%d'))
# 增加月份、年份、星期和涨跌标识
# try:
dt=pd.to_datetime(data['净值日期'],format='%Y/%m/%d')
# dt=dt.apply(dt,'%Y-%m-%d')
data['月份']=dt.map(lambda x:x.month)
data['年份']=dt.map(lambda x:x.year)
# 获取星期数据
data['星期_int']=[int(i.strftime("%w")) for i in dt]
data['星期'] = data['星期_int'].replace([0,1,2,3,4,5,6],["星期日","星期一","星期二","星期三","星期四","星期五","星期六"])
# data['星期'] = weekday(data['星期_int'])
data['基金代码']=codes[i]
data['基金名称']=names[i]
#调整数据格式
data['净值日期'] = pd.to_datetime(data['净值日期'], format='%Y/%m/%d')
data['单位净值'] = data['单位净值'].astype(float)
data['累计净值'] = data['累计净值'].astype(float)
data['日增长率'] = data['日增长率'].str.strip('%').astype(float) #去掉%号
data['涨跌'] =ifup(data['日增长率'])
# 按照日期升序排序并重建索引
data = data.sort_values(by='净值日期', axis=0, ascending=False).reset_index(drop=True)
# 重置dataframe各列顺序
data=data.reindex(columns=['基金代码','基金名称','净值日期','单位净值','累计净值','日增长率','申购状态','赎回状态','分红送配','月份','年份','星期_int','星期','涨跌'])
# 分组汇总
data_groupmonth=data.groupby('月份')['日增长率'].apply(sum).reset_index()
data_groupweek = data.groupby('星期_int')['日增长率'].apply(sum).reset_index()
# data_groupmw= data.groupby(['月份', '星期_int'])['日增长率'].apply(sum).reset_index()
data_groupmw = data.groupby(['月份', '星期_int'])['日增长率'].apply(sum).unstack().reset_index()
data_groupyear = data.groupby('年份')['日增长率'].apply(sum).reset_index()
# data_groupym = data.groupby(['年份','月份'])['日增长率'].apply(sum).reset_index()
data_groupym = data.groupby(['年份', '月份'])['日增长率'].apply(sum).unstack().reset_index()
#将多个dataframe输出到同一个工作簿
writer = pd.ExcelWriter('D:/Python/基金数据/基金净值/'+names[i]+codes[i]+'.xlsx')
data.to_excel(writer, '明细数据')
#不同维度的汇总数据放在同一个sheet中
data_groupmonth.to_excel(writer, '汇总统计',index=False)
data_groupweek.to_excel(writer, '汇总统计',startcol=4,index=False)
data_groupmw.to_excel(writer, '汇总统计', startcol=8, index=False)
data_groupyear.to_excel(writer, '汇总统计', startcol=18, index=False)
data_groupym.to_excel(writer, '汇总统计', startcol=21, index=False)
# 输出数值列数据的描述统计量
data.describe().to_excel(writer, '汇总统计', startrow=20,startcol=0)
writer.save()
data_all.append(data)
# 将所有数据汇总在一张表
writer_all = pd.ExcelWriter('D:/Python/基金数据/基金净值/全部基金数据.xlsx')
# concat只能接受列表型数据凭借,data为DataFrame型数据,直接用concat会报错,先用append拼接成list后再用concat
data_all2=pd.concat(data_all)
# 增加.unstack()函数可以将月份转置为表头显示
data_all2_m=data_all2.groupby(['基金名称','月份'])['日增长率'].sum().unstack().reset_index()
data_all2_w = data_all2.groupby(['基金名称', '星期_int'])['日增长率'].sum().unstack().reset_index()
# data_all
data_all2.to_excel(writer_all,'明细数据')
data_all2_m.to_excel(writer_all,'汇总统计')
data_all2_w.to_excel(writer_all, '汇总统计',startcol=15,index=False)
# # 将数据导入数据库
try:
conn = create_engine("mysql+pymysql://root:[email protected]:3306/fund?charset=utf8")
data_all2.to_sql('funddata', conn, if_exists='replace', index=False, chunksize=100)
except:
pass
writer_all.save()
file_name_list = ['D:\Python\基金数据\基金净值\全部基金数据.xlsx']
email_text = "%s基金收益数据分析结果日报" % datetime.datetime.now().strftime('%Y%m%d %H%M')
recei_list = ['***@***.com'] # 写上自己的邮箱测试一下
Send_email(file_name_list, email_text, recei_list)