作者:琥珀里有波罗的海来源:数据如琥珀打造自己的股票分析系统1、前言数据分析很重要的一步是结果展示与汇报,无论是给客户还是上级。你可以选择PPT展示,也可以给出word文档展示,但是如果有一个交互式的网站(app)展示,无疑是更加吸引人。说起网站,很多人想到PHP,JS,但是绝大多数“数据分析师”没有这些技术,原因主要是:这完全是两个领域,精力有限的人很少会大量投入时间来精通。python有很多优秀的开源网页设计框架,Django和Flask便是其中两个“巨头”,在企业中应用广泛。但是Django和Flask 固然优秀,但是它毕竟只是框架,关于页面设计的细节多数还是JS,而且有的时候你学了好几天设计出来的页面依然平庸无奇(我的就是奇丑无比)。但是数据分析数据师如果想通过网页快速展示自己的成果,一定要学JS?一定要“重量级”框架?一定要忍受奇丑无比?NO!NO! NO!今天我们可以用纯python入门一个股票分析系统,不用JS,不用深入框架,入门一样酷炫,简约而不简单。2、主角登场作为入门教程,我们要实现以下功能:

  • 设计一个网站app,查看股票的历史记录

  • 获取股票列表,支持下拉选择以及输入检索

  • 支持时间段查询

  • 画出经典的股票趋势图

  • 动态调整时间段

  • 支持鼠标悬停显示当日详细详细

下面我们一一解释每个环节的实现方式,我估计本实现的难度系数在2颗星(只要你懂python)。2.1 网站如何设计这是一个轻量版的网站,我们这里自然无需用Django和(原生)Flask的重量级框架,但是即便是一个简单的demo,我依然希望网站保留可扩展的能力,比如实际的应用中我们可能还需要其他功能:

  • 需要实时显示当日股票信息

  • 显示大盘信息

  • 显示多个趋势

  • 显示周趋势,月度趋势

  • 添加表格,显示股票问题

  • 显示实时新闻

  • 甚至增加一键买/卖

  • 增加量化分析模型

以上通通可以实现,依然无需JS,有兴趣的可以进一步交流。今天的网站设计采用的Plotly Dash,我相信很多人听过Plolty这个包,也用它画过简单的图(相当于交互版的matplotlib),但是dash 的功能很多人没有使用过。网站链接如下:https://plotly.com/dash/你可以看到很多交互式Dashboard的设计,比如用于制造业。关于Plotly Dash,以下优缺点纯属个人亲测(实际项目)感受,可以帮你决定是否适合你:

  • 优点:

    • html 设计以及用户操作响应采用python,无需了解JS

    • 框架采用的Flask,所以Flask的功能都可以在这里实现,意味着强大的后续功能扩展

    • 对Flask进行了一定程度的封装,所以入手极快

    • 界面美观,如上图,用过plotly的人都喜欢它的设计

    • 支持交互式操作,比如plotly的图画带有各种按钮

    • 被很多开源BI 支持,比如Grafana

    • 适合数据分析师

  • 缺点:

    • 不适合大型项目,用户响应速度没有JS快(因为是纯python)

    • 不适合网站开发者,因为使用习惯不同

2.2 股票信息如何获取这里不建议采用爬虫的方式进行获取,因为时间成本太高,而且获取的质量不稳定,作为一个网站,我们需要选用稳定的源。有很多股票信息的开源包可以选择,我亲测过两个接口包,一个是akshare,一个Tushare。这个demo中我们两个都进行了测试,但是akshare的访问速度和稳定性不佳(有可能是我个人网络问题),最后我选择了Tushare。关于Tushare,采用注册制,注册即可获取足够积分来稳定的获取股票的信息,为了稳定性,我最终选择了Tushare,它也的确不辜负所望。由于我的积分目前不足以获取股票的周线,月线,以及大盘的信息,所以没法在demo中涵盖。如果你是新手,不如点击我的邀请链接,注册的同时帮我获取积分吧:https://tushare.pro/register?reg=1290332.3 开启实战首先导入我们所需的“主角”以及“配角”,这里依然将每个所需的包功能放在注释中。

import tushare as ts  # 获取股票信息import dash # 设计网站from datetime import datetime, timedeltaimport dash_core_components as dcc #设计网站采用的核心插件库import dash_bootstrap_components as dbc #设计网站采用的美化页面import dash_html_components as html  #设计网站采用的核心插件库from dash.dependencies import Input, Output, State # 完成用户点击响应import plotly.graph_objects as go # 画出趋势图from dash.exceptions import PreventUpdateimport pandas as pd

我们需要给我们网站中每个元素定义ID,方便后面进行回调,响应用户的操作。

# ID definitionsid_button_update_a_share_list = 'id-button-update-a-share-list'id_dpl_share_code = 'id-dpl-share-code'id_date_picker_range = 'id-date-picker-range'id_button_query_trend = 'id-button-query-trend'id_graph_hist_trend_graphic = 'id-graph-hist-trend-graphic'

这里主要的控件就是:

  1. 下拉列表,用于选择股票

  2. 右侧有更新股票清单按钮,用于更新股票清单,因为股票清单很久才更新一次,我们没有必要每次开网页都实时获取,可以从本地数据库或者本地文件中获取。

  3. 选择时间控件

  4. 查看股票信息按钮

  5. 绘图区

2.4 定义多个功能函数

为了方便调用,我们将一些常用的功能变成函数:

  1. update_a_share_list 用于从csv中读取股票代码以及名称
  2. get_A_stock_list 用于从网上下载最新的股票清单信息
  3. write_A_stock_list_to_csv 网上下载的信息同步到本地
  4. share_dict_to_option 将本地文件中的信息,合并成控件的选项,因为有些人知道股票代码,有些人知道股票名称,因此有必要支持两种检索
  5. get_trend_df:用于通过股票代码,以及时间段来获取日线
  6. plot_candlestick:用于画股票的K线,
def update_a_share_list():    # display a stock share list from csv    a_share_list_df = pd.read_csv(A_STOCK_FILE, index_col='ts_code')    share_dict = a_share_list_df.to_dict()['name']    return share_dict_to_option(share_dict)def get_A_stock_list():    # fetch list from internet    share_df = ts_pro.stock_basic(        exchange='',        list_status='L',        fields='ts_code,name')    share_df.set_index('ts_code', inplace=True)    return share_dfdef write_A_stock_list_to_csv(file):    # sync to csv    share_df = get_A_stock_list()    share_df.to_csv(file)def share_dict_to_option(share_dict):    # convert name and code to options    name_list = [str(key) + '-' + str(value)                 for key, value in share_dict.items()]    return list_to_option_list(name_list)def split_share_to_code(share):    # split options to get code    code = share.split('-')[0]    return codedef list_to_option_list(list):    # quick create dropdown options from list    return [{"label": i, "value": i} for i in list]def get_trend_df(code, start_date, end_date):    # get history tend by ts_code,start_date,end_datess    df = ts_pro.daily(ts_code=code, start_date=start_date, end_date=end_date)    df['trade_date'] = pd.to_datetime(df['trade_date'], format='%Y%m%d')    df.set_index('trade_date', inplace=True)    df.sort_index(inplace=True)  # sort result by date (datetime)    return dfdef plot_candlestick(df):    # plot candlestick    # customize the color to China Stock    fig = go.Figure(        data=[            go.Candlestick(                x=df.index,                open=df['open'],                high=df['high'],                low=df['low'],                close=df['close'],                increasing=dict(                    line=dict(                        color="#FF0000")),                decreasing=dict(                    line=dict(                        color="#00FF00")),            )])    fig.update_layout(        margin=dict(l=2, r=10, t=20, b=20),        paper_bgcolor="LightSteelBlue",    )  # change the layout of figure    return fig

2.5 设计网页

网站框架的建立仅仅需要一行代码:dash.Dash(__name__)。这样就自动创建好一切框架,剩下的就是需要添加按钮,控件等。

这里我们通过按钮的设计来看一下该方案的简单快捷:

update_a_share_button = dbc.Button(    id=id_button_update_a_share_list,    color='light',    children='更新列表', outline=True)

这是一个python函数,意味着你需要的主要配置都在函数的参数中。id 是前文提到的元素id,主要用于回调函数。color 不用说,就是颜色定义。因为这个更新股票列表按钮不常用,所以配色采用‘light’,outline 设为True,让他看起来像隐藏了一样,只有鼠标滑过才会显示。

  • Dropdown 是下拉列表控件,option参数很关键,也就是下拉的选项。调用我们前面定义的函数update_a_share_list来添加选项。

  • 为了让界面美观一点,这里我们调用bootstrap进行对齐设计。

  • Graph 控件用于绘图,核心的K线采用plot_candlestick函数绘制。

  • 最后,设计好的所有控件,放在app.layout中即可。

这样一个静态的网页就设计好了。

# create dash appapp = dash.Dash(__name__)# layout designheader = html.H2("股票查询", className='text-center')# update list buttonupdate_a_share_button = dbc.Button(    id=id_button_update_a_share_list,    color='light',    children='更新列表', outline=True)# share select dropdown listselect_share = dcc.Dropdown(    id=id_dpl_share_code,    options=update_a_share_list())# datetime pickerdate_pick = dcc.DatePickerRange(    id='id-date-picker-range',    max_date_allowed=datetime.today(),    start_date=datetime.today().date() - timedelta(days=60),    end_date=datetime.today().date())# query buttonquery_button = dbc.Button(    "查询",    color="warning",    className="mr-1",    id=id_button_query_trend,    outline=False)# make a better row/col layoutselect_share_row = dbc.Container(    [        dbc.Row(            [                dbc.Col(                    [select_share],                    className='col-5'),                dbc.Col(                    [update_a_share_button],                    className='col-2')]),        html.Br(),        dbc.Row(            [                dbc.Col(                    [date_pick],                    className='col-5'),                dbc.Col(                    [query_button],                    className='col-1')])])# get default figuredefault_fig = plot_candlestick(    get_trend_df(        '000001.SZ',        start_date='20200101',        end_date='20200707'))# graphic divgraphic_div = dbc.Container(    [dcc.Graph(figure=default_fig, id=id_graph_hist_trend_graphic)])# fully layoutapp.layout = html.Div([    header,    select_share_row,    html.Br(),    graphic_div,])

2.6 响应用户操作Dash 采用callback 函数用于响应用户的操作,主要的状态有三个:

  • Input:表示”一触即发“,也就是用户只要进行了该操作,就会调用callback 函数,常见的如按钮的点击动作

  • State:表示“整装待发”,也就是只有Input 被执行时,callback会检查该元素的状态。该状态改变时,不会立马执行callback操作。比如下拉列表的选择。注意:如果你想让下拉列表选择变化后,立马会调出相应的趋势,那么可以把下拉列表的相应操作放在Input中

  • Output:就是callback的结果返回给哪个控件。

所以结合上面的基本信息,我们可以写出绘图callback。Output, Input,State 函数都会有两个参数,第一个是元素的id,也就是指定元素。第二个是元素的属性,比如按钮的n_clicks属性,下拉列表的当然值value,日期选择控件的start_date和end_date。

  • Output(id_graph_hist_trend_graphic, 'figure'),

  • Input(id_button_query_trend, 'n_clicks'),

  • State(id_dpl_share_code, 'value'),

  • State(id_date_picker_range, 'start_date'),

  • State(id_date_picker_range, 'end_date')]

@app.callback(    Output(id_graph_hist_trend_graphic, 'figure'),    [Input(id_button_query_trend, 'n_clicks')],    [State(id_dpl_share_code, 'value'),     State(id_date_picker_range, 'start_date'),     State(id_date_picker_range, 'end_date')])def update_output_div(query, share, start, end):    if query is not None:        share_code = split_share_to_code(share)        start_str = start.replace("-", "")        end_str = end.replace("-", "")        return plot_candlestick(            get_trend_df(                share_code,                start_date=start_str,                end_date=end_str))    else:        raise PreventUpdate

2.7 运行程序

运行程序只有一行代码,但是这里可以指定IP,端口等,让网站被其他人访问。默认的网址 http://127.0.0.1:8050/

if __name__ == '__main__':    app.run_server(debug=True)

3、总结

作为一个入门级,适合数据分析师的网站设计示例,本示例演示如何设计一个股票历史查询网站。Plotly 以及Dash 对于数据分析来说,无疑是利器,可以不需其他前端语言完成一个酷炫的界面设计。Tushare 可以稳定的获取各种股票/金融相关的信息。

最重要的是,虽然该方案入门及其简单,但是扩展能力也很强,适合快速交付成果给客户。

扫描回复「股票02」获取本文代码

pb graph鼠标移上显示数据_数据分析手把手入门:打造自己的股票分析系统相关推荐

  1. pb graph鼠标移上显示数据_Plotly数据可视化:离线版、微软vscode版的Python的基本作图...

    1 介绍: ===== 1.1 Plotly 是一款用来做数据分析和可视化的在线平台,功能非常强大. 1.2 Plotly是一个非常著名且强大的开源数据可视化框架,它通过构建基于浏览器显示的web形式 ...

  2. python 网页上显示数据_怎么用python将excel数据写入网页中,python 网页上excel表格数据分析...

    用python读取excel,怎样显示要查找的数据? 感觉还是CSV格式的好一些,EXCEL的要装插件,以CSV为例,段代码 sqlserver char 对应c# import linecache ...

  3. python 网页上显示数据_用Python实现网页数据抓取

    需求: 获取某网站近10万条数据记录的相关详细信息. 分析:数据的基本信息存放于近1万个页面上,每个页面上10条记录.如果想获取特定数据记录的详细信息,需在基本信息页面上点击相应记录条目,跳转到详细信 ...

  4. java如何在窗口上显示数据_如何把Java程序窗口在屏幕中间显示

    摘要:这篇Java开发技术栏目下的"如何把Java程序窗口在屏幕中间显示",介绍的技术点是"Java程序.屏幕中间.Java.显示.窗口.中间",希望对大家开发 ...

  5. baidu 地图 鼠标移上显示标签 鼠标离开隐藏标签

    为了解决 label太多,文字会重叠看不清 所以提出这种办法 核心代码 1,创建的时候 将label设置为隐藏 2,通过百度地图监听事件 ,  mouseover或onmouseover 触发显示 3 ...

  6. css鼠标移上显示红色禁止符号

    小小样式让我找了好久,搜索不对也不行啊,鼠标 hover 时指针的样式一般为箭头,但是可以设置小手或者其他,此文意在用 css 样式设置指针禁止符号 // 以下两个css表达式皆为一个红色的圈加一个斜 ...

  7. Vue 框架-02-事件:点击, 双击事件,鼠标移上事件

    Vue 框架-02-事件:点击, 双击事件,鼠标移上事件 1.单击事件:v-on:click 源码 app2.js : //实例化 vue 对象 new Vue({//注意代码格式//el:eleme ...

  8. vue实现文字过长鼠标移上去显示对应文字,移走隐藏

    vue实现文字过长鼠标移上去显示对应文字,移走隐藏 vue项目里实现列表里因文字过长,加上鼠标移上去显示对应文字效果 示例图片 html js 数据定义 style vue项目里实现列表里因文字过长, ...

  9. js 隔行变色+鼠标移上换色+鼠标离开颜色恢复+鼠标点击弹出点击的是第几行是什么颜色

    隔行变色: 先获取要操作的HTML标签 var oLis = document.querySelectorAll('li') 循环HTML标签 for (var i = 0; i < oLis. ...

最新文章

  1. 提权巧用RAR.EXE
  2. 明年,我要用 AI 给全村写对联
  3. 面试java后端开发之后的一些感受
  4. boost::math::quadrature::daubechies_wavelet_transform用法的测试程序
  5. 拆卸invokedynamic
  6. python 比特输出_Python小碗菜:and/or 与 amp;/| 到底有什么区别
  7. 中国特夫行业市场供需与战略研究报告
  8. C++学习笔记之由文本文件读取数据到vector模板建立的二维数组 并存储为新的文本文件...
  9. Atitit 软件程序的定义 软件广义定义 程序代码,文档 ,数据 方法,规则, 狭义定义 软件=程序+数据+文档 软件(英文:Software)是一系列按照特定顺序组织的计算机数据和指
  10. 吹响数字经济时代的冲锋号 2021宝德X86生态伙伴大会在深召开
  11. MYSQL排序加分页报错Out of sort memory, consider increasing server sort buffer size
  12. JAVA POI 读取2017Excel
  13. matlab中制作软件,在matlab app designer中制作多个3d图形动画
  14. 关于vim的详细配置
  15. spring boot自动化配置
  16. 网络、信息系统安全等级保护测评机构定级报告及定级备案表
  17. 2021年4月19日 深圳头条后台开发实习面试(一面)(含总结)
  18. 三极管(如NPN)集电极正偏 发射极反偏会怎么样呢? 电流会倒流吗? 其他三种都知道,就是不知道这种情况...
  19. 题解 DTOJ #4016.辉夜的夜空明珠(moon)
  20. YY一下VR游戏的潜入玩法

热门文章

  1. 大顶堆,小顶堆——排序问题
  2. JS实现GPS坐标转化为高德坐标
  3. uboot sf 命令用法
  4. 微信公众平台自定义菜单无法更改怎么办?看这里就够了!微信公众号自定义菜单没办法修改怎么回事
  5. MAMP环境下安装php扩展
  6. 5.5 Python图像处理之图像编码-位平面编码
  7. python入门(@property,@*.setter)
  8. 3D游戏引擎入门课程——角色动画
  9. 专业的面相识别的企业|人脸识别离线SDK |人证比对API
  10. css将div变为块,css+div 浮动分块