Oracle存储过程实现X日均线计算

Oracle存储过程实现X日均线计算

前期准备

首先我们需要有一个存有股票数据的数据表,我的数据表如下(部分数据,使用的图形界面软件是Navicat):
在这里插入图片描述
主要有五个字段,分别对应日期、开盘价、最高价、最低价、收盘价,大家可以用自己的命名方式,表结构为:
在这里插入图片描述
使用Navicat创建表时最好字段名的字母都是大写,不然后续操作时有小写的字段或表名都要用双引号括起来才能识别出来,是真的麻烦;
那么这些数据从哪里来呢?
我是老师直接给的,所以没去了解从哪下载,大家可以去一些券商软件或者一些正规的股票网站应该有下载功能,当然,这种东西大家一定要谨慎,要钱才能下的,你直接给他一句傻x,或者大家就直接从下面的链接里下,然后导入数据库:
https://download.csdn.net/download/qq_16186465/19733135

编写存储过程

首先我们要知道X日均线是什么,就是X日收盘价的算术平均数,比如我要算5日均线,那么股票的前四天是肯定没有5日均线的,都没5天的数据怎么算出来,所以5日均线是从第5条才开始有值的,后面就以5天为一个网格一直往后计算,也称之为移动平均。
知道了计算方法后我们就可以编写存储过程了:

CREATE OR REPLACE procedure MA (N in number)
as
	var_ma number; -- N日均线值
	var_count number := 0; -- 数组长度或下标
	var_sum number := 0; -- 近N日收盘价的和
	type arr_num is table of number index by BINARY_INTEGER;  -- 定义一个一维数组
	var_close arr_num; -- 存放近N日收盘价
	cursor stockdata is -- 声明游标stockdata
		select dates, closingrate
			from stockdata
			order by dates asc;
begin
	execute immediate 'alter table stockdata add MA'||N||' number'; -- 创建N日均线字段
	for i in stockdata loop -- 游标FOR循环
		var_count := var_count + 1; -- 数组当前长度或下标
		var_close(var_count) := i.closingrate; -- 当天收盘价存入数组当前下标位置
		if var_count = N then -- 当数组长度为N时执行
			for j in 1 .. N loop -- 近N日收盘价求和
				var_sum := var_sum + var_close(j);
			end loop;
			for j in 1 .. (N-1) loop -- 数组内下标为1到N-1的数据往前移动一个元素
				var_close(j) := var_close(j + 1);
			end loop;
			var_ma := var_sum / N; -- 求N日均线值
			var_sum := 0; -- 清空
			var_count := N - 1; -- 让下一个收盘价存到下标为N的位置
			execute immediate 'update stockdata set MA'||N||' = '||round(var_ma,2)||' where dates = '''||i.dates||''''; -- 更新数据
		end if;
	end loop; -- 结束游标FOR循环
	commit; -- 提交
end; -- 结束存储过程

大致的思路就是先在表里创建一个字段来存放数据,运用游标循环,用一个数组来存放近N(为传入的参数)日的收盘价,然后求平均值,求完之后把数组里的数据都往前移动一个元素,相当于把原来的第一个数踢出去,下次循环再加入那天的收盘价在数组的第N个位置,继续计算平均数,并且每次计算后都将平均数更新到对应当天日期的数据行中,以此类推;最后一定要commit提交
在这里插入图片描述
对了,还要注意存储过程中的表名和字段名要换成自己的,如果表名和字段和我的不一样肯定会报错的

调用存储过程

Nacicait的话直接在存储过程那个窗口就有个运行键,直接点击输入参数就行,一般的日均线有5天、10天、20天、60天,当然现在有存储过程想要几天就几天,只要不超过所有数据的行数:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
显示这个就算成功了,然后就去数据表看看有没有
在这里插入图片描述
如果有发现一页只有1000条数据的小伙伴,右下角有个换页按钮,还有上面有个排序,更方便按顺序查看,因为我发现update会把原数据顺序打乱,很奇怪,不知道他的源码实现原理是什么
在这里插入图片描述

结尾

这样我们就完成了使用存储过程计算X日均线并且存入数据表,但我觉得我这个算法还是很慢,特别是创建字段和更新数据消耗了大量的时间,不知道大家有没有更好的想法呢

补充

由于上面的算法是在已存在数据的情况下进行计算的,主要适用于分析已经有的数据,如果说要随着时间增加,每个新的交易日的数据再次计算的话,显然这个算法是不合适的,这个更像一个初始化的过程。于是我又写了个用于计算每天新增数据后的均值计算方法

CREATE OR REPLACE PROCEDURE GET_NEW_MA (N in number)
AS
	var_date date; --最新日期
	var_ma number; -- 近N日均值
BEGIN
	select avg(closingrate) into var_ma --计算近N日均值
	from (
		select dates, closingrate from stockdata
		order by dates desc
	)
	where rownum <= N;
	select dates into var_date -- 获取最新日期
	from (
		select dates from stockdata
		order by dates desc
	)
	where rownum = 1;
	execute immediate 'update stockdata set MA'||N||' = '||round(var_ma,2)||' where dates = '''||var_date||''''; -- 更新数据
	commit; -- 提交
END;

我想象的,这个的主要场景是每天收市后,使用此方法计算当天的均值。如果说并不是每天都定时计算,而是隔一段时间计算一次的话,这个方法也是不合适的,还需要进一步优化才行,实现的方法也是很多的

  • 5
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 11
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

1594231563

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值