Python使用pyecharts库构建股票交易 可交互可视化展示——基于Tushare大数据开放社区

Python使用pyecharts库构建股票交易 可交互可视化展示——基于Tushare大数据社区


 

1、前言

大家好!欢迎各位访问我的博客,今天给大家分享的是 python使用pyecharts库构建股票交易的可交互可视化展示,并简单设置股票买入卖出条件,统计股票收益率等操作。本次数据的来源是Tushare大数据开发社区(:D 感谢Tushare的数据支持,Tushare拥有丰富的数据内容,如股票、基金、期货、数字货币等行情数据,能够让我们解放双手,逃脱最痛苦的数据收集步骤),本次重点是利用pyecharts库绘制k线图,希望大家能够喜欢。

 

2、成品展示

image
图片1 可交互展示

 

 

图片2 pyecharts-300274-阳光电源.html

 

 

image
图片3 自选股统计收益率分析

 

 

image
图片4 个股分析导出

 

 

3、源码分享

python
import tushare as ts
import pandas as pd
import matplotlib.pyplot as plt
import json
import numpy as np
from matplotlib.pylab import date2num
import datetime
import mpl_finance as mpf
import pyecharts
from pyecharts import options as opts
from pyecharts.commons.utils import JsCode
from pyecharts.charts import *
import numpy as np
from openpyxl import Workbook
from openpyxl.styles import PatternFill
from openpyxl import load_workbook



# 设置Token
ts.set_token('******************') #请填入自己的Token

# 初始化接口
ts_api = ts.pro_api()
print("Tushare 接口调用正常,版本号:" + ts.__version__ +"\n")
print("pyecharts数据交互 接口调用正常,版本号:{}".format(pyecharts.__version__)+"\n")


class RobotTrade():
    id = None
    buyTime = None
    buyPrice = None
    sellTime = None
    sellPrice = None
    profit = None

    def setId(self,id):
        self.id = id

    def buy(self,time,price):
        self.buyTime = time
        self.buyPrice = price

    def sell(self,time,price):
        self.sellTime = time
        self.sellPrice = price
        self.profit = round((self.sellPrice - self.buyPrice)/self.buyPrice,4)

    def Out(self):
        a = self.buyTime
        b = self.sellTime
        c = self.buyPrice
        d = self.sellPrice
        e = self.profit
        f = self.id
        return [a,b,c,d,e,f]

class Stock:
    global returnList
    isTodayBuy = ""
    df = pd.DataFrame([0, 0])
    code = ""
    start = ""
    end = ""
    name = ""
    list_BuyorSell = []

    # 设置股票代码
    def set_code(self,code):

        stock_list = ts_api.stock_basic(exchange='', list_status='L',
                                        fields='ts_code,symbol,name,area,industry,market,list_date')
        a = stock_list["ts_code"].tolist()

        for i in range(len(a)):
            if a[i][0:6] == code:
                self.code=a[i]
                self.name=stock_list.loc[i,"name"]
            # 请求股票列表

    # 获取日线交易数据
    def get_daily_trade(self):  # 股票代码,开始日期20120101,结束日期20180101

        # print("正在获取交易数据:\n    --Start Download")
        if self.start == "":
            self.start = input("请输入交易开始日期:")
            self.end = input("请输入交易结束日期:")

        # 请求日线数据
        # print(self.start)
        df = ts_api.daily(ts_code = self.code, start_date = self.start, end_date = self.end)

        # 按交易日升序排序
        df.sort_values(by=["trade_date"], inplace=True)
        df.reset_index(drop=True, inplace=True)
        self.df = df

        # print("已获取{} {},交易数据,共计{}条交易数据\n".format(self.code,self.name, len(self.df)))

    # 指数移动均线工具
    def get_MA_EMA(self, n):
        df = self.df
        newname = "EMA" + str(n)
        df[newname] = 0  # 初始化n天指数移动均线
        for i in range(n - 1, len(df)):  # 循环第n个数据开始,为之后的每个数据计算EMA
            list_temp = []
            list_ema = []
            for d in range(n):  # 添加数据
                list_temp.append(df.loc[i - (n - d) + 1, "close"])
                list_ema.append(0)
            for d in range(n):  # 进行计算
                if d == 0:
                    list_ema[d] = list_temp[d]
                else:
                    list_ema[d] = (2 * list_temp[d] + (n - 1) * list_ema[d - 1]) / (n + 1)
            df.loc[i, newname] = list_ema[n - 1]
        # print("    --已计算指数移动均线EMA{}".format(n))
        self.df = df

    # 移动均线计算
    def get_MA(self, n):
        df = self.df
        newname = "MA" + str(n)
        df[newname] = None  # 初始化n天指数移动均线
        for i in range(n-1,len(df)):
            list_temp = []
            sum = 0
            avg = 0
            for d in range(n):
                sum = sum + df.loc[ i-(n-d)+1 ,"close"]
            avg = round(sum/n,2)
            df.loc[i, newname] = avg
        # print("    --已计算移动均线MA{}".format(n))

    # 移动均线计算
    def get_Vol_MA(self, n):
        df = self.df
        newname = "VolMA" + str(n)
        df[newname] = None  # 初始化n天指数移动均线
        for i in range(n-1,len(df)):
            list_temp = []
            sum = 0
            avg = 0
            for d in range(n):
                sum = sum + df.loc[ i-(n-d)+1 ,"vol"]
            avg = round(sum/n,2)
            df.loc[i, newname] = avg
        # print("    --已计算成交量移动均线MA{}".format(n))

    # Macd的快速线DIF计算
    def get_Macd_DIF(self, n1, n2):
        df = self.df
        newname = "Macd_DIF"
        df[newname] = 0  # 初始化n天指数移动均线
        for i in range(n2,len(df)):
            df.loc[i, "Macd_DIF"] = df.loc[i, "EMA" + str(n1)] - df.loc[i, "EMA" + str(n2)]
        # print("    --已计算MACD 快速线DIF")
        self.df = df

    # Macd的慢速线DEA计算
    def get_Macd_DEA(self, n):
        df = self.df
        newname = "Macd_DEA"
        df[newname] = 0  # 初始化n天指数移动均线
        for i in range(n - 1, len(df)):  # 循环第n个数据开始,为之后的每个数据计算EMA
            list_temp = []
            list_dif = []
            for d in range(n):  # 添加数据
                list_temp.append(df.loc[i - (n - d) + 1, "Macd_DIF"])
                list_dif.append(0)
            for d in range(n):  # 进行计算
                if d == 0:
                    list_dif[d] = list_temp[d]
                else:
                    list_dif[d] = (2 * list_temp[d] + (n - 1) * list_dif[d - 1]) / (n + 1)
            df.loc[i, newname] = list_dif[n - 1]
        # print("    --已计算MACD 慢速线DEA")
        self.df = df

    # 计算MACD柱状线
    def get_Macd_Bar(self,n):
        df = self.df
        for i in range(n,len(df)):
            df.loc[i,"MACD_Bar"] = 2 * ( df.loc[i, "Macd_DIF"] - df.loc[i, "Macd_DEA"])
        # print("    --已计算MACD 柱状线Bar")
        self.df = df

    # Macd计算
    def get_Macd(self, a=12, b=26, c=9):

        # print("正在计算MACD指标:")

        # 计算EMA12、EMA26 数据
        self.get_MA_EMA(a)
        self.get_MA_EMA(b)

        # 计算三条曲线
        self.get_Macd_DIF(a,b)
        self.get_Macd_DEA(c)
        self.get_Macd_Bar(b)

        # print("    --已完成MACD指标的计算")

    # 交易策略
    def set_Trading_Strategy(self):
        df = self.df
        list_BuyorSell = []
        count = 0
        temp = 0 # 买入后的世界线进行

        for i in range(10,len(df)): # 偷懒从第十个交易日开始
            i = i + temp
            if i >=len(df):
                break
            lowThanma5 = 0 # 收盘价低于5日均线的天数
            Is_skip = False # 是否条件不满足
            Is_selled = False


            # 条件0:买点的前2天收盘价均小于5日均线
            for day in range(1,2):
                if df.loc[i-day,"MA5"] < df.loc[i-day,"close"]:
                    Is_skip = True
            if Is_skip==True:
                continue

            # 条件1:当天收盘价大于5日线
            if df.loc[i,"close"] < df.loc[i,"MA5"]:
                Is_skip = True
            if Is_skip==True:
                continue

            # # 条件2:当天开盘价低于5日线
            # if df.loc[i, "open"] > df.loc[i, "MA5"]:
            #     Is_skip = True
            # if Is_skip == True:
            #     continue

            # 条件3: 当日增幅超过3%
            if ((df.loc[i,"close"]-df.loc[i,"open"]) / df.loc[i,"open"] ) <= 0.03:
                Is_skip = True
            if Is_skip==True:
                continue

            # 条件3:...

            if Is_skip==True:
                continue
            # 买入条件均满足后买入
            r = RobotTrade() # 设置交易机器人id
            r.setId(count)

            if i+1 == len(df): # 是否今天买入
                self.isTodayBuy = "下个交易日开盘立刻买入"
                break
            r.buy(i+1,df.loc[i+1,"open"]) # 机器人后一天买入
            have_price = df.loc[i+1,"open"] # 第二天开盘立刻买入

            # 一但卖出条件成熟,机器人执行卖出
            for day in range(1,31): # 最大持股时间30日

                if i+1+day >= len(df) - 1: # 检查数组是否越界
                    r.sell(len(df) - 1, r.buyPrice)
                    list_BuyorSell.append(r.Out())
                    break

                # 单次操作亏损达到-0.0666时卖出
                if (df.loc[i+1+day,"close"]-r.buyPrice)/r.buyPrice <= -0.0666:
                    r.sell(i + 1 + day, r.buyPrice*0.9334)
                    list_BuyorSell.append(r.Out())
                    Is_selled = True
                    break

                # 单次操作盈利达到+0.2888时卖出
                if (df.loc[i + 1 + day, "high"] - r.buyPrice) / r.buyPrice >= 0.1888:
                    r.sell(i + 1 + day, r.buyPrice * 1.1888)
                    list_BuyorSell.append(r.Out())
                    Is_selled = True
                    break

                # 5日均线小于10日均线的0.98 卖出
                if df.loc[i+1+day,"MA10"]*0.98 > df.loc[i+1+day,"MA5"]:
                    r.sell(i+1+day,df.loc[i+1+day,"close"])
                    list_BuyorSell.append(r.Out())
                    Is_selled = True
                    break

                # 连续3天收盘价小于5日均线 且 5日线小于10日线 卖出
                if df.loc[i + 1 + day, "MA5"] > df.loc[i + 1 + day, "close"] and df.loc[i + 1 + day, "MA5"] < \
                        df.loc[i + 1 + day, "MA10"]:
                    lowThanma5 = lowThanma5 + 1
                    if lowThanma5 >= 3:
                        r.sell(i + 1 + day, df.loc[i + 1 + day, "close"])
                        list_BuyorSell.append(r.Out())
                        Is_selled = True
                        break

                # 若卖出条件未出现,则持仓等候
                a = 1+1 # 摸鱼
                temp = temp + 1

            if Is_selled == True:
                continue

            if i+31 >= len(df)-1: # 检查数组越界
                r.sell(len(df)-1,r.buyPrice)
                list_BuyorSell.append(r.Out())
                break

            # 如果最大持股时间达到时 还持有仓位,则强制卖出
            if Is_selled != True:
                r.sell(i + 31,df.loc[i + 31, "close"])
                list_BuyorSell.append(r.Out())
                Is_selled = True

            # 结束一个周期
            count = count +1

        self.list_BuyorSell = list_BuyorSell
        # print(list_BuyorSell)

    # 绘制MA指标图,返回line_ma
    def get_Pyecharts_MA(self,n,index,itheme="light"):
        df = self.df
        colorlist = ["rgb(47,79,79)","rgb(255,140,0)","rgb(0,191,255)","rgb(187, 102, 255)"]
        icolor = colorlist[index-2]
        line = (
            Line(init_opts=opts.InitOpts(theme=itheme,animation_opts=opts.AnimationOpts(animation=False),))
                # 添加x轴交易日期数据
                .add_xaxis(df["trade_date"].tolist())
                .add_yaxis("MA{}".format(n),df["MA{}".format(n)].tolist(),xaxis_index=index,yaxis_index=index,
                           label_opts=opts.LabelOpts(is_show=False),
                           is_symbol_show=False, # 是否显示小圆点
                           itemstyle_opts=opts.ItemStyleOpts(color=icolor)) # 更改颜色
                .set_global_opts(
                    xaxis_opts=opts.AxisOpts(is_show=False,grid_index=index),
                    yaxis_opts=opts.AxisOpts(is_show=False,grid_index=index),
                    legend_opts=opts.LegendOpts(is_show=True),  # 图例是否显示
                )
            )

        return line

    # 绘制成交量均值线
    def get_Pyecharts_VolMA(self,n,index,itheme="light"):
        df = self.df
        colorlist = ["rgb(47,79,79)","rgb(255,140,0)"]
        icolor = colorlist[index-6]
        line = (
            Line(init_opts=opts.InitOpts(theme=itheme,animation_opts=opts.AnimationOpts(animation=False),))
                # 添加x轴交易日期数据
                .add_xaxis(df["trade_date"].tolist())
                .add_yaxis("VolMA{}".format(n),df["VolMA{}".format(n)].tolist(),xaxis_index=index,yaxis_index=index,
                           label_opts=opts.LabelOpts(is_show=False),
                           is_symbol_show=False, # 是否显示小圆点
                           tooltip_opts=opts.TooltipOpts(is_show=False),
                           itemstyle_opts=opts.ItemStyleOpts(color=icolor)) # 更改颜色
                .set_global_opts(
                    xaxis_opts=opts.AxisOpts(is_show=False,grid_index=index),
                    yaxis_opts=opts.AxisOpts(is_show=False,grid_index=index),
                      # 图例是否显示
                )
            )

        return line

    # 绘制K线图,
    def get_Pyecharts_Kline(self,itheme="light"):
        tradeAction = [] # 交易输出记录
        df = self.df
        valueList = []
        temp_data = [] # 用于标记区域
        temp_data2 = [] # 用于标记线
        totalProfit = 100
        # 构建日交易金额数据list
        for i in range(len(self.list_BuyorSell)):
            profit = self.list_BuyorSell[i][4] # 0.05
            temp_data.append(opts.MarkAreaItem(name="", x=(df.loc[self.list_BuyorSell[i][0],"trade_date"], df.loc[self.list_BuyorSell[i][1],"trade_date"])))
            temp_data2.append([ { "xAxis": df.loc[self.list_BuyorSell[i][0],"trade_date"],
                                  "yAxis": df.loc[self.list_BuyorSell[i][0],"open"],
                                  "value": "盈利:{:.2f}%".format(profit*100)
                                  },
                                {
                                "xAxis": df.loc[self.list_BuyorSell[i][1], "trade_date"],
                                "yAxis": self.list_BuyorSell[i][3],
                                }])
            totalProfit = totalProfit*(1+profit)

            # 输出Excel交易操作信息
            tradeAction.append([ df.loc[self.list_BuyorSell[i][0],"trade_date"], df.loc[self.list_BuyorSell[i][1], "trade_date"], round(df.loc[self.list_BuyorSell[i][0],"open"],2),round(self.list_BuyorSell[i][3],2), "{:.2f}%".format(self.list_BuyorSell[i][4]*100)])

        self.totalProfit = totalProfit
            # name="交易{:0>2d}\n{:.2f}%".format(i+1,profit)
        returnList.append([self.name, self.code, tradeAction, round((self.totalProfit-100)/100*100,2)])

        for i in range(len(df)):
            valueList.append([df.loc[i, "open"], df.loc[i, "close"], df.loc[i, "high"], df.loc[i, "low"],(df.loc[i,"close"]-df.loc[i,"open"])/df.loc[i,"open"]  ])
        x = df["trade_date"].tolist()
        y = valueList
        # 绘制K线图
        kline = (
            Kline(init_opts=opts.InitOpts(theme=itheme,animation_opts=opts.AnimationOpts(animation=True,animation_easing_update="backOut")))  # chalk

                # 添加x轴交易日期数据
                .add_xaxis(x)
                # 添加y轴成交价格数据
                .add_yaxis(series_name="Daily Trade Data", y_axis=y, itemstyle_opts=opts.ItemStyleOpts(  # 风格设置
                    color="red",color0="green",
                    border_color="#ef232a",border_color0="#14b143", # 边框色彩
                    ),
                   markline_opts=opts.MarkLineOpts(
                       label_opts=opts.LabelOpts(
                           position="middle", color="blue"
                       ),
                       data=temp_data2,
                       symbol=["none", "arrow"],
                       symbol_size=10,
                       linestyle_opts=opts.LineStyleOpts(color="blue",width=3)
                   ),
                )

                # 设计标记区 x = 开始,结束
                .set_series_opts(markarea_opts=opts.MarkAreaOpts(data=temp_data,
                                                                 itemstyle_opts=opts.ItemStyleOpts(opacity=0.6, # 透明度
                                                                                                color={
                                                                                                   "type":'linear',
                                                                                                   "x":1,"y":1,"x2":0,"y2":0,
                                                                                                   "colorStops": [{"offset": 0, "color": '#F55555'}, {"offset": 1, "color": '#FCCF31'}]
                                                                                                    }
                                                                                                )
                                                                 )
                                 )
                # 设置x、y轴显示信息
                .set_global_opts(xaxis_opts=opts.AxisOpts(name='交易时间'))
                # .set_global_opts(yaxis_opts=opts.AxisOpts(name='交易价格/元'))
                # 固定y轴的范围
                # .set_global_opts(yaxis_opts=opts.AxisOpts(min_=5, max_=10))

                .set_global_opts(title_opts=opts.TitleOpts(title="{} {} 总盈利{:.2f}% {}".format(self.code,self.name,(self.totalProfit-100)/100*100,self.isTodayBuy), subtitle='日K线图 交易价格/元'),  # 标题选项

                                 legend_opts=opts.LegendOpts(is_show=True),  # 图例选项

                                 datazoom_opts=[  # 缩放选项
                                     opts.DataZoomOpts(
                                         is_show=False,
                                         type_="inside",
                                         xaxis_index=[0,1],
                                         # 初始的框选范围
                                         range_start=80,
                                         range_end=100,
                                     ),
                                     opts.DataZoomOpts(
                                         is_show=True,
                                         xaxis_index=[0,1],
                                         type_="slider",
                                         pos_top="95%",
                                         range_start=80,
                                         range_end=100,
                                     )
                                 ],

                                 yaxis_opts=opts.AxisOpts(  # 坐标轴配置项
                                     is_scale=True,  # 是否显示y轴
                                     splitarea_opts=opts.SplitAreaOpts(  # 分割区域配置项
                                         is_show=True, areastyle_opts=opts.AreaStyleOpts(opacity=1))
                                 ),

                                 # 控制x轴label
                                 xaxis_opts=opts.AxisOpts(axislabel_opts=opts.LabelOpts(formatter=JsCode(
                                     """
                                     function (x) {
                                     a = x.substring(0,4);
                                     b = x.substring(4,6);
                                     c = x.substring(6,8);
                                     return a+'年'+b+'月'+c+'日'; 
                                     }
                                     """)
                                )),



                                 tooltip_opts=opts.TooltipOpts(  # 提示框配置项
                                     trigger="axis",  # 触发类型默认
                                     axis_pointer_type="cross",  # 鼠标指针指示器
                                     background_color="rgba(245, 245, 245, 0.8)",  # 提示框漂浮层背景色
                                     border_width=1,  # 提示框漂浮层边框
                                     border_color="#ccc",
                                     textstyle_opts=opts.TextStyleOpts(color="#000"),  # 提示框文字选项
                                     formatter=JsCode(
                                         """
                                         function (x) {
                                         date = x[0].axisValue.substring(0,4)+ '年' + x[0].axisValue.substring(4,6)+ '月' +x[0].axisValue.substring(6,8)+ '日';
                                         open = x[0].data[1];
                                         close = x[0].data[2];

                                         
                                         return date + '<br>' + '开盘价:' + open + '<br>' +'收盘价:' + close + '<br>' +'涨跌幅:' + Math.round((close-open)/close*100*100)/100 + '%<br>'+ x[1].seriesName +'&nbsp;&nbsp;:'+ x[1].data[1] + '<br>' + x[2].seriesName +':'+ x[2].data[1] + '<br>'+ x[3].seriesName +':'+ x[3].data[1] + '<br>'+ x[4].seriesName +':'+ x[4].data[1] + '<br>'; 
                                         }
                                         """)
                                 ),

                                 axispointer_opts=opts.AxisPointerOpts(  # 坐标轴指示器配置项
                                     is_show=True,
                                     label=opts.LabelOpts(background_color="#777"),
                                 ),

                                 brush_opts=opts.BrushOpts(  # 区域选择组建配置项
                                     x_axis_index="all",  # 指定哪些 xAxisIndex 可以被刷选
                                     brush_link="all",  # 不同系列间,选中的项可以联动。
                                     out_of_brush={"colorAlpha": 0.1},
                                     brush_type="lineX",
                                 ),
                                )
        )
        return kline

    # 绘制成交量图形
    def get_Pyecharts_Bar(self,itheme="light"):
        df = self.df
        valueList = []
        # 构建日交易金额数据list
        for i in range(len(df)):
            valueList.append([df.loc[i, "open"], df.loc[i, "close"], df.loc[i, "high"], df.loc[i, "low"]])
        # 绘制成交量柱状图
        bar = (
            Bar()
                .add_xaxis(xaxis_data=df["trade_date"].tolist())
                .add_yaxis(series_name="Volume",y_axis=df["vol"].tolist(),label_opts=opts.LabelOpts(is_show=False),
                    # 设置多图联动
                    xaxis_index=1,
                    yaxis_index=1,
                    tooltip_opts=opts.TooltipOpts(is_show=False),)

                .set_global_opts(
                    xaxis_opts=opts.AxisOpts(

                        # 控制x轴label
                        axislabel_opts=opts.LabelOpts(formatter=JsCode(
                            """
                            function (x) {
                            a = x.substring(0,4);
                            b = x.substring(4,6);
                            c = x.substring(6,8);
                            return a+'年'+b+'月'+c+'日'; 
                            }
                            """)
                        ),
                        type_="category",
                        is_scale=True,
                        grid_index=1,
                        axisline_opts=opts.AxisLineOpts(is_on_zero=True),
                        axistick_opts=opts.AxisTickOpts(is_show=True),
                        splitline_opts=opts.SplitLineOpts(is_show=False),
                        split_number=20,
                        min_="dataMin",
                        max_="dataMax",),

                    yaxis_opts=opts.AxisOpts(
                        grid_index=1,
                        is_scale=True,
                        split_number=2,
                        axislabel_opts=opts.LabelOpts(is_show=True),
                        axisline_opts=opts.AxisLineOpts(is_show=True),
                        axistick_opts=opts.AxisTickOpts(is_show=True),
                        splitline_opts=opts.SplitLineOpts(is_show=False),),
                legend_opts=opts.LegendOpts(is_show=False),
            )
        )
        return bar

    # 绘制主图并输出页面
    def Print_Main_index(self,kline,bar_volumn,line_ma=None,line_ma2=None,line_ma3=None,line_ma4 = None,itheme="light"):
        bar = bar_volumn

        kline.overlap(line_ma)
        kline.overlap(line_ma2)
        kline.overlap(line_ma3)
        kline.overlap(line_ma4)

        grid_chart = Grid(
            init_opts=opts.InitOpts(
                width="1200px", height="580px",
                animation_opts=opts.AnimationOpts(animation=True,animation_easing="linear"),
                theme=itheme, page_title="Pyecharts_Demo",
            )
        )
        # 添加上图
        grid_chart.add(
            kline,
            grid_opts=opts.GridOpts(pos_left="10%", pos_right="10%", height="60%"),
        )
        # 添加下图
        grid_chart.add(
            bar,
            grid_opts=opts.GridOpts(pos_left="10%", pos_right="10%", pos_top="75%", height="16%"),
        )
        grid_chart.render(path = "C:/Users/***/Desktop/StockAnalysis/pyecharts-{}-{}.html".format(self.code[0:6],self.name))
        import os
        print("已保存文件至{}".format("C:/Users/***/Desktop/StockAnalysis/pyecharts-{}-{}.html".format(self.code[0:6],self.name)))
        # os.system("start C:/Users/***/Desktop/pyecharts-{}-{}.html".format(self.code[0:6],self.name))

    def begin(self):
        self.get_daily_trade()
        # self.get_Macd()
        self.get_MA(5)
        self.get_MA(10)
        self.get_MA(20)
        self.get_MA(150)
        self.get_Vol_MA(5)
        self.get_Vol_MA(10)
        self.set_Trading_Strategy()
        self.line_ma5 = self.get_Pyecharts_MA(5,2) # index由2开始
        self.line_ma10 = self.get_Pyecharts_MA(10,3)
        self.line_ma20 = self.get_Pyecharts_MA(20,4)
        self.line_ma50 = self.get_Pyecharts_MA(150,5)
        self.line_volma5 = self.get_Pyecharts_VolMA(5, 6)
        self.line_volma10 = self.get_Pyecharts_VolMA(10, 7)
        self.kline = self.get_Pyecharts_Kline()
        self.bar_volumn = self.get_Pyecharts_Bar().overlap(self.line_volma5).overlap(self.line_volma10)
        self.Print_Main_index(self.kline, self.bar_volumn, self.line_ma5, self.line_ma10, self.line_ma20, self.line_ma50)

class ExcelWriter:
    path = None
    wb = None
    ws = None

    def setLocation(self,Path):
        self.path = Path

    def newFile(self):
        wb = Workbook()
        ws = wb.active
        self.wb = wb
        self.ws = ws

    def outList(self):
        list = []
        a = -100
        size = 5
        for i in range(70):
            a = a
            b = a + size
            list.append([[a, b], "{}%->{}%".format(a, b), 0])
            a = a + size
        return list

    def inList(self,n,list):
        n = int(n)
        for i in list:
            # print(type(n), type(i[0][0]))
            if int(i[0][0]) <= n and n < int(i[0][1]):
                i[2] = i[2] + 1
        return list

    def writeData(self,Lists): # List 单个元素内容 [stockName,stockCode,[操作1,操作2,...],总盈利]
        dictProfit = self.outList() # 收益率计数列表
        countColumn = 1 # 控制列的输出
        countRow = 1 # 控制行的输出
        Avprofit = 0
        for stock in Lists:
            countRow = 1
            # 输出股票名称及代码
            self.ws.cell(row=countRow,column=countColumn).value = stock[0] + stock[1]
            countRow = countRow+1

            # 输出操作信息
            for action in stock[2]:
                self.ws.cell(row=countRow, column=countColumn).value = "{} {} {} {} {}".format(action[0],action[1],action[2],action[3],action[4])
                countRow = countRow+1

            self.ws.cell(row=25, column=countColumn).value = "个股收益:"
            self.ws.cell(row=26, column=countColumn).value = str(stock[3]) + "%"
            dictProfit = self.inList(stock[3],dictProfit)
            Avprofit = Avprofit + stock[3]
            countColumn = countColumn + 1
        # print(profit)
        self.ws.cell(row=27, column=1).value = "平均收益:"
        self.ws.cell(row=28, column=1).value = str(round(Avprofit/len(Lists),2)) + "%"

        self.ws.cell(row=30, column=1).value = "收益分布分析:"
        countColumn2 = 1
        for i in dictProfit:
            self.ws.cell(row=31, column=countColumn2).value = i[2]
            self.ws.cell(row=32, column=countColumn2).value = i[1]
            countColumn2 = countColumn2 + 1


    def saveExcel(self):
        print("保存文件至 -> {}".format(self.path))
        self.wb.save(self.path)
        import os
        os.system("start  C:/Users/***/Desktop/StockAnalysis/totalAnalysis.xlsx")





if __name__ == '__main__':
    returnList = []
    codeList = []
    with open("C:/Users/***/Desktop/StockAnalysis/code.txt", 'r') as file:
        data = file.readlines()
        for i in data:
            codeList.append(i.replace("\n",""))
    print(codeList)

    # for i in range(10):
    #     code = input("请输入证券代码:")
    #     codeList.append(code)

    for i in codeList:
        stock1 = Stock()
        stock1.set_code(i)
        stock1.start = "20210101"
        stock1.end = "20211201"
        stock1.begin()
    ew = ExcelWriter()
    ew.setLocation("C:/Users/***/Desktop/StockAnalysis/totalAnalysis.xlsx")
    ew.newFile()
    ew.writeData(returnList)
    ew.saveExcel()

 

4、开发日志

交易系统开发日志

10月19日:构思完成,寻求股票交易数据。

10月21日:计划使用Tushare平台获取交易数据。

10月23日:申请Tushare高校学生权限。

10月24日:获取Tushare 1000积分,构建股票信息DataFrame。

10月26日:学习matplotlib绘制K线图。

10月27日:绘制第一张K线图。

10月31日:学习技术指标公式,尝试构建Macd指标(MACD计算结果错误,原因未核查)。

11月5日:开始接触pyecharts绘图库。

11月9日:理清pyecharts库的多图交互逻辑Grid、Overlap、Page。

11月12日:做出第一张基于Pyecharts库的可交互K线图。

11月14日:完成成交量与K线图的页面叠加。

11月18日:完成代码系统化构建。

11月25日:完成MA均线的计算与绘制。

11月26日:
	完成交互的动画效果优化、
	完成x轴日期格式化输出、
	新增RobotTrade类:
	新增自动交易机器人模型
	新增set_Trading_Strategy函数:
		现已支持设置自定义买入卖出条件
	新增MarkArea标记域的父类继承设置:
		能够自动标出买入卖出区域、自动计算当前收益率

11月28日:
	重构Tooltip提示框:
		删除不必要的信息
	新增标记线:
		现已支持显示机器人操作的收益率
	新增区域标识透明度设置

12月3日:
	新增ExcelWriter类,支持将结果输出到Excel:
		已实现统计自选股收益信息,并将其保存。
	新增对下一个交易日的行动安排
	新增TxtRead方法:
		现已支持导入外部自选股列表批量分析。

12月4日:
	优化程序输出、
	新增inList 和outList 方法:
		现已支持收益率的数频统计

好啦本次的分享就到这,欢迎大家留言哟!

posted @ 2022-02-08 14:09  汪汪碎冰冰!  阅读(3676)  评论(13编辑  收藏  举报