用python开发了一个绘制股票k线图的工具,还可以预测股票涨跌!【文末附源码和教学视频】

2023-11-17

聊一聊这个工具

起初,我并不在意echarts,这不过是一个偶然、一次选择、一条简单的代码、一个图表的诞生,直到我完成了K线图的绘制。

股票,一个神奇的发明,他看不见摸不着,无法预测,却时刻让你的神经紧绷。他的出现,是对打工人的福音?还是一场灾难?是命运的转折点,还是一夜回到解放前。他都可以帮你实现。

K线图,他让你的投资有了参考,花哨的图表下面隐藏着财富的密码。接下来就让我们一起揭开这神秘的面纱。

效果展示

在这里插入图片描述
输入你喜欢的股票代码,就可以生成近一年的K线图。如此方便简洁,难免不让人心动。

更加令人兴奋的是,根据算法,可以预测出明天股票的涨跌情况。当然准不准我也不知道,仅供参考。

股票数据

该工具使用的股票数据来自于Tushare,只需要注册获取一个token就可以免费得到股票数据。

Tushare官网地址:https://tushare.pro/document/2?doc_id=14

运行项目

第一步: 从文末的源码地址,下载项目并解压到本地电脑

第二步: 配置运行环境,使用pycharm导入项目,在【terminal】下运行下面命令:

pip install -r requirements.txt

如果下载第三方库比较慢,可以考虑换一下pip的下载源:

pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple

阿里云 http://mirrors.aliyun.com/pypi/simple/
中国科技大学 https://pypi.mirrors.ustc.edu.cn/simple/
豆瓣(douban) http://pypi.douban.com/simple/
清华大学 https://pypi.tuna.tsinghua.edu.cn/simple/
中国科学技术大学 http://pypi.mirrors.ustc.edu.cn/simple/

第三步: 更改app.py中的ts_token,使用自己在tushare网站注册获取的token。右击运行app.py在浏览器中就可以看到图表。

前端界面

前端的技术主要用到echarts、element、vue等技术,官方文档上多有详细的案例,只需要参照官方文档案例代码,根据自己需求修改调试好代码即可。

绘制K线图

echarts图表案例:Examples - Apache ECharts

elements组件案例:组件 | Element

源码展示:

<html>
	<head>
		<meta charset="UTF-8" />
		<!-- import CSS -->
		<link rel="stylesheet" href="https://unpkg.com/element-ui/lib/theme-chalk/index.css">
		<title>股票小工具</title>
	</head>
	<body>
		<div id="app">
			<!-- 普通字符串加密取 -->
			<el-row :gutter="10" style="margin-top: 20px;">
				<el-card class="box-card">
					<div slot="header" class="clearfix">
						<span>K线图</span>
					</div>
					<el-row>
						<el-col>
							<el-form label-width="80px" :inline="true" :model="stockForm">
								<el-form-item label="股票代码:">
									<el-input v-model="stockForm.code" placeholder="例如:000001.SZ" clearable />
								</el-form-item>
								<el-form-item>
									<el-button type="primary" v-if="stockForm.code"
										@click="stockFormSubmit('stockForm')">确定</el-button>
									<el-tooltip class="item" v-else effect="dark" content="请填写股票代码!">
										<el-button type="danger">确定</el-button>
									</el-tooltip>
								</el-form-item>
								<el-form-item>
									<el-tag v-if=forcastMsg.includes('涨') type="danger" effect="dark">
										[{stockName+forcastMsg}]
									</el-tag>
									<el-tag v-else type="success" effect="dark">
										[{stockName+forcastMsg}]
									</el-tag>
								</el-form-item>
							</el-form>
						</el-col>
					</el-row>
					<el-row>
						<div id="main" style="width:1000px;height:500px;"></div>
					</el-row>
				</el-card>
			</el-row>
		</div>
	</body>
	<!-- 导入下载的 echarts.min.js -->
	<script src="../static/js/echarts.min.js"></script>
	<!-- import Vue before Element -->
	<script src="https://unpkg.com/vue@2.6.14/dist/vue.min.js"></script>
	<!--<script src="https://unpkg.com/vue/dist/vue.js"></script>-->
	<!-- import JavaScript -->
	<script src="https://unpkg.com/element-ui/lib/index.js"></script>
	<!--导入 axios 获取数据-->
	<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
	<script src="https://cdn.staticfile.org/vue-resource/1.5.1/vue-resource.min.js"></script>
	<script>
		const upColor = "#ec0000"
		const upBorderColor = "#8A0000"
		const downColor = "#00da3c"
		const downBorderColor = "#008F28"

		var nv = new Vue({
			el: '#app',
			delimiters: ['[{', '}]'],
			data: function() {
				return {
					// 表单数据
					stockForm: {
						code: '000001.SZ',
					},
					// 图表数据
					kChartdata: null,
					// 预测信息
					forcastMsg: "预测信息",
					// 股票名
					stockName: "",
				}
			},
			created:function(){
				this.stockFormSubmit()
			},
			methods: {
				// 获取输入的股票代码数据
				async stockFormSubmit(stockForm) {
					const {
						data: res
					} = await this.$http.post("http://127.0.0.1:12345/stock", this.stockForm)
					if (res.status != 200) {
						this.$message({
							showClose: true,
							message: res.msg,
							center: true,
							type: 'error'
						})
					} else {
						this.$message({
							showClose: true,
							message: res.msg,
							center: true,
							type: 'success'
						})
						// 重新赋值新的股票数据
						var myChart = echarts.init(document.getElementById('main'))
						this.kChartdata = res.stock_data
						this.forcastMsg = this.kChartdata.forcast
						this.stockName = this.kChartdata.name
						var option = {
							// 图表标题配置
							title: {
								text: this.stockName + '近一年K线图'
							},
							// 提示框配置
							tooltip: {
								// 是否显示提示框
								show: true,
								// 触发类型,axis 移动到坐标轴就触发
								trigger: "axis",
								// 坐标轴上提示点设置
								axisPointer: {
									type: "cross"
								}
							},
							// 图例配置
							legend: {
								data: ['日K', 'MA5', 'MA10', 'MA20', 'MA30']
							},
							// X 轴配置项
							xAxis: {
								type: "category",
								data: this.kChartdata.stock_trade_days,
								boundaryGap: false,
								axisLine: {
									onZero: false
								},
								splitLine: {
									show: true
								},
								min: "dataMin",
								max: "dataMax"
							},
							// y 轴配置项
							yAxis: {
								scale: true,
								splitArea: {
									show: true
								}
							},
							dataZoom: [{
									type: "inside",
									start: 50,
									end: 100
								},
								{
									show: true,
									type: "slider",
									top: "90%",
									start: 50,
									end: 100
								}
							],
							// 系列配置,根据不同图表有不同的配置
							series: [{
									name: "日K",
									// 图表类型
									type: 'candlestick',
									// 数据内容
									data: this.kChartdata.stock_trade_data,
									// K 线图的图形样式
									itemStyle: {
										// 阳线 图形的颜色
										color: upColor,
										// 阴线 图形的颜色。
										color0: downColor,
										// 阳线 图形的描边颜色
										borderColor: upBorderColor,
										// 阴线 图形的描边颜色
										borderVolor0: downBorderColor
									},
									// 标记点配置
									markPoint: {
										// 标注的文本
										label: {
											// 标签内容格式器,支持字符串模板和回调函数两种形式,字符串模板与回调函数返回的字符串均支持用 \n 换行。
											// 参数 params 是 formatter 需要的单个数据集, value是传入的数据值。
											formatter: function(param) {
												return param != null ? Math.round(param.value) + "" :
													"";
											}
										},
										// 标注的数据数组。每个数组项是一个对象
										data: [
											// 特殊的标注类型,用于标注最大值最小值等
											{
												name: "highest value",
												type: "max",
												// 在使用 type 时有效,用于指定在哪个维度上指定最大值最小值。
												valueDim: "highest",
											},
											{
												name: 'lowest value',
												type: 'min',
												valueDim: 'lowest'
											},
											{
												name: 'average value on close',
												type: 'average',
												valueDim: 'close'
											}
										],
										// 提示框浮层内容格式器,支持字符串模板和回调函数两种形式。
										tooltip: {
											// params 是 formatter 需要的数据集
											formatter: function(param) {
												// name数据名,类目名,data传入的原始数据项
												return param.name + "<br>" + (param.data.coord || "")
											}
										}
									},
									markLine: {
										// 标线两端的标记类型,可以是一个数组分别指定两端,也可以是单个统一指定
										symbol: ['none', 'none'],
										// 标线的数据数组。每个数组项可以是一个两个值的数组,分别表示线的起点和终点,每一项是一个对象
										data: [
											[
												// 定义从最小值到最大值的线
												{
													name: "from lowest to highest",
													type: "min",
													valueDim: "lowest",
													symbol: "circle",
													symbolSize: 10,
													label: {
														show: false
													},
													emphasis: {
														label: {
															show: false
														}
													}
												},
												{
													type: "max",
													valueDim: "highest",
													symbol: "circle",
													symbolSize: 10,
													label: {
														show: false
													},
													emphasis: {
														label: {
															show: false
														}
													}
												},
											],
											// 最小值水平线
											{
												name: "min line on close",
												type: "min",
												valueDim: "close"
											},
											// 最大值水平线
											{
												name: "max line on close",
												type: "max",
												valueDim: "close"
											},
										],
									}
								},
								{
									name: "MA5",
									type: "line",
									data: this.kChartdata.MA5,
									smooth: true,
									lineStyle: {
										opacity: 0.5
									}
								},
								{
									name: "MA10",
									type: "line",
									data: this.kChartdata.MA10,
									smooth: true,
									lineStyle: {
										opacity: 0.5
									}
								},
								{
									name: "MA20",
									type: "line",
									data: this.kChartdata.MA20,
									smooth: true,
									lineStyle: {
										opacity: 0.5
									}
								},
								{
									name: "MA30",
									type: "line",
									data: this.kChartdata.MA30,
									smooth: true,
									lineStyle: {
										opacity: 0.5
									}
								},
							]
						}
						//使用刚指定的配置项和数据显示图像
						myChart.setOption(option)
					}
				},
			}
		});
	</script>
</html>

后端接口

使用flask搭建的微应用,接口介绍:

  • stock:获取输入的股票数据,返回交易数据、MA数据以及预测数据
  • index:获取主界面
import pandas as pd
from flask import Flask, render_template, request
from flask import jsonify
from flask_cors import CORS
import webbrowser
from datetime import datetime, timedelta
import tushare as ts

ts_token = "填写在tushare获取的token"
ts.set_token(ts_token)
pro = ts.pro_api()

app = Flask(__name__)
CORS(app, supports_credentials=True)


def get_stock(code):
    # 获取股票数据
    end_date = datetime.now().strftime("%Y%m%d")
    start_date = datetime.strftime(datetime.now() - timedelta(365), "%Y%m%d")
    df = pro.daily(ts_code=code, start_date=start_date, end_date=end_date).sort_values(by="trade_date")
    try:
        data = pro.query('stock_basic', exchange='', list_status='L', fields='ts_code,name')
        data.to_excel("./static/excel/stock_basic_info.xlsx", index=False)
        name = data[data["ts_code"] == code]["name"].values[0]
    except Exception as e:
        data = pd.read_excel("./static/excel/stock_basic_info.xlsx")
        name = data[data["ts_code"] == code]["name"].values[0]
    if df.empty:
        return None
    df["MA5"] = df["close"].rolling(4).mean().map(lambda x: round(x, 3))
    df["f1"] = df["MA5"] - df["close"]
    forcast_msg = f"预测 {end_date} 会跌!"
    if sum(df.tail(7)["f1"] > 0) > 4:
        forcast_msg = f"预测 {end_date} 会涨!"
    result = {
        "stock_trade_days": df["trade_date"].values.tolist(),
        "stock_trade_data": df[["open", "close", "low", "high"]].values.tolist(),
        "MA5": df["close"].rolling(4).mean().map(lambda x: round(x, 3)).fillna("-").tolist(),
        "MA10": df["close"].rolling(9).mean().map(lambda x: round(x, 3)).fillna("-").tolist(),
        "MA20": df["close"].rolling(19).mean().map(lambda x: round(x, 3)).fillna("-").tolist(),
        "MA30": df["close"].rolling(29).mean().map(lambda x: round(x, 3)).fillna("-").tolist(),
        "forcast": forcast_msg,
        "name": name
    }
    return result


@app.route("/")
def index():
    return render_template('index.html')


@app.route("/stock", methods=["GET", "POST"])
def stock():
    # 获取提交的股票代码
    rq_json = request.json
    stock_code = rq_json["code"]
    # 获取股票数据,数据解释:时间,开盘价,收盘价,最低价,最高价
    get_stock_result = get_stock(stock_code)
    if get_stock_result:
        result = {
            "status": 200,
            "stock_data": get_stock_result,
            "msg": f"获取{stock_code}股票数据成功!"
        }
        return jsonify(result)
    else:
        result = {
            "status": 400,
            "stock_data": None,
            "msg": f"获取{stock_code}股票数据失败!"
        }
        return jsonify(result)


if __name__ == '__main__':
    webbrowser.open("http://127.0.0.1:12345/")
    app.run(debug=False, port=12345)

运行后就可以在浏览器中看到,感兴趣的朋友可以试试!

源码地址

链接:https://pan.baidu.com/s/1pkAZDi3jLQoh8vifHaj0nA?pwd=vd3s

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

用python开发了一个绘制股票k线图的工具,还可以预测股票涨跌!【文末附源码和教学视频】 的相关文章

随机推荐

  • 手机访问静态html页面,手机访问电脑本地静态页面

    如果用webstrom打开一个单独的页面 在浏览器中现实的地址是 如果这恰好是你正在开发的用于移动端的页面 想要在手机上访问以便于测试验证效果 怎么访问到呢 在webstorm的setting中是有相关可设置的 只是我试了不好用 下面有几种
  • eclipse导入后将普通项目变为java项目

    eclipse用subclipse导入svn项目时 没有选择项目类型 这样就不能修改项目的buildpath no action aviliable 打开workspace下面的 projcet文件在标签
  • SparkSQL HiveSQL 常用正则表达式

    SparkSQL HiveSQL 常用正则表达式 目录 SparkSQL HiveSQL 常用正则表达式 1 匹配汉字 2 匹配手机号码 3 匹配身份证 4 SparkSQL HiveSQL 常用正则函数 5 SparkSQL 分组 聚合
  • 期待2021!

    好久没写文章了 甚至好久没有看文章了 要说这些天怎么过去了呢 恍恍惚惚 竟一时语塞 恍惚着 这2020竟马上过去了 好多好多人都写了分享了自己的年终总结 看了一些 大家好像都很有收获 再想想自己 也不能说没有任何收获 但是说不出来 最大的收
  • docker镜像服务器间复制

    概述 我们制作好镜像后 有时需要将镜像复制到另一台服务器使用 能达到以上目的有两种方式 一种是上传镜像到仓库中 本地或公共仓库 但是另一台服务器很肯能只是与当前服务器局域网想通而没有公网的 所以如果使用仓库的方式 只能自己搭建私有仓库 这会
  • SpringBoot+Dubbo分布式SOA项目骨架搭建(二)

    SpringBoot Dubbo分布式SOA项目骨架搭建 项目介绍 本项目是来自于上一篇文章http blog csdn net songxinjianqwe article details 77478385 中的服务化拆分这个部分 经过一
  • QSplitter(分离器或分隔符)

    QSplitter 分离器或分隔符 本文为原创文章 转载请注明出处 或注明转载自 黄邦勇帅 原名 黄勇 本文出自本人原创著作 Qt5 10 GUI完全参考手册 网盘地址 https pan baidu com s 1iqagt4SEC8PU
  • 顺序表的原理与初始化

    顺序表是简单的一种线性结构 逻辑上相邻的数据在计算机内的存储位置也是相邻的 可以 快速定位第几个元素 中间不允许有空值 插入 删除时需要移动大量元素 顺序表的三个要素 用 elems 记录存储位置的基地址 分配一段连续的存储空间 size
  • crontab的使用方法介绍

    使用crontab你可以在指定的时间执行一个shell脚本或者一系列Linux命令 例如系统管理员安排一个备份任务使其每天都运行 安装 apt get install cron 服务器环境下默认都会安装 使用 crontab e 进入编辑页
  • java常见面试题及答案 11-20(JVM)

    11 JVM内存分哪几个区 每个区的作用是什么 java虚拟机主要分为以下一个区 方法区 1 有时候也成为永久代 在该区内很少发生垃圾回收 但是并不代表不发生GC 在这里进行的GC主要是对方法区里的常量池和对类型的卸载 2 方法区主要用来存
  • 安全测试初体验-XSS

    XSS XSS攻击成功后 攻击者能够对用户当前浏览器的页面植入恶意脚本 通过恶意脚本 控制用户的浏览器 这些用以完成各种具体功能的恶意脚本 被称为 XSS Payload XSS Payload实际上就是JavaScript脚本 所以任何J
  • JS逆向之某头条jsvmp逻辑层算法分析

    今天我们来研究下 某头条的jsvmp逻辑层加密算法 其主要的目的是想在大家在接触此类算法时 给出点实质性的建议和思路 0x01 分析加密 进入到目标网站通过分析请求会发现一个动态的 signature 加密参数 0x02 定位加密 不同于以
  • 在matlab中编译C++和opencv

    1 在matlab中运行 mex setup命令 选择C 类型 2 运行mex build 此时matlab配置基本完成 3在VS中添加matlab中的库目录和头文件目录 附加库目录 matlab安装目录下面的 extern lib win
  • 【Docker】 使用Docker-Compose 搭建基于 WordPress 的博客网站

    引 本文将使用流行的博客搭建工具 WordPress 搭建一个私人博客站点 部署过程中使用到了 Docker MySQL 站点搭建完成后经行了发布文章的体验 WordPress WordPress 是一个广泛使用的开源内容管理系统 CMS
  • 报告老师!AICA 学员交作业了!

    关注 飞桨PaddlePaddle 公众号 获取更多技术内容
  • linux-ssh安全策略(sshd)

    实际使用中 为限制ssh高危端口我们一般做以下策略 1 修改端口 ssh默认用22 2 密码强口令 3 root限制 4 新增ssh登录白名单 5 开启端口防火墙 6 有条件的话整个密钥登录更安全 不过avatar目前不支持密钥登录 所以项
  • 最安全的加密算法

    在密码学里 有一种理想的加密方案 叫做一次一密乱码本 one time pad one time pad的算法有以下要求 1 密钥必须随机产生2 密钥不能重复使用3 密钥和密文的长度是一样的 one time pad是最安全的加密算法 双方
  • “汉堡+奶昔”怎么就成了精致生活的热门标签?

    图片来源 视觉中国 文章来源 DT财经 左手汉堡 右手奶昔 这是新天地Coco的时髦新日常 最近沪上刮起一阵打卡新风潮 汉堡竟然成了标记城市美好生活的一大利器 还在纠结晚餐去金拱门还是汉堡王的DT君 发现自己在吃汉堡这件事上竟然也要被划出潮
  • 一步一步教你怎样给Apache Spark贡献代码

    本文将教大家怎样用10个步骤完成给Apache Spark贡献代码这个任务 到 Apache Spark 的github 页面内点击 fork 按钮 你的github帐户中会出现 spark 这个项目 本地电脑上 使用 git clone
  • 用python开发了一个绘制股票k线图的工具,还可以预测股票涨跌!【文末附源码和教学视频】

    文章目录 聊一聊这个工具 效果展示 股票数据 运行项目 前端界面 后端接口 源码地址 聊一聊这个工具 起初 我并不在意echarts 这不过是一个偶然 一次选择 一条简单的代码 一个图表的诞生 直到我完成了K线图的绘制 股票 一个神奇的发明