Oracle存储过程实现BOLL(布林线)计算
BOLL公式
首先我们要了解布林线的计算公式,可以去百度百科或者维基百科上看
这是我整理的布林线公式:
布林线(BOLL):
上轨线(UP): MB + 2 * MD
中轨线(MB): N日的MA
下轨线(DN): MB – 2 * MD
MA: N日均值
MD: 平方根N日的(C – MA)的两次方和除以N
可以看到布林线的计算公式还是很简单的,中轨线(MB)就是当天的N日均值,一般都会使用20日作为参数,其中比较有难度的就是MD这个标准差的计算,C是N日内每日对应的收盘价,或者更直观一点
这个σ就是MD,xi就是N日内每日的均值, ̅x就是MA,n就是参数,一般为20,把对应的数据代进去,我们就能算出MD了;
数据准备
了解公式后没有数据也不能计算,大家可以去下面这篇文章看数据准备,而且布林线的计算也需要20日均线:
https://blog.csdn.net/qq_16186465/article/details/118059033
表准备
我是单独把数据存在一个独立的表里,所以要新建一个BOLL表,大家也可以在原数据表创建对应字段也行:
--创建BOLL表
create table BOLL (dates date, BOLLUP number, BOLLMB number, BOLLDN number);
--把STOCKDATA表中的日期复制给BOLL表
insert into BOLL(dates) select dates from STOCKDATA;
里面这个STOCKDATA表就是上面数据准备的表,所以我这个关联性还是挺大的
存储过程
CREATE OR REPLACE PROCEDURE GETBOLL
AS
var_MD number; -- 近20日收盘价标准差
var_MB number; -- 中轨线, 也是当天20日均线值
var_UP number; -- 上轨线
var_DN number; -- 下轨线
var_count number := 0; -- 用作数组长度,或下标
var_sum number := 0; -- 用作标准差求和部分
type arr_num is table of number index by BINARY_INTEGER; -- 定义一个一维数组
arr_close arr_num; -- 用于存放近20日内收盘价
cursor stockdata is -- 声明游标stockdata
select dates, closingrate
from STOCKDATA
order by dates asc;
BEGIN -- 开始存储过程
for i in stockdata loop -- 游标FOR循环
var_count := var_count + 1; -- 数组下标
var_MB := GETMA(i.dates, 20); -- 调用GETMA函数,传入:当前日期,20日 意为获取当天的20日均线值
arr_close(var_count) := i.closingrate; -- 将当前收盘价存入数组
if var_count = 20 then -- 当数组长度达20时执行
for j in 1 .. 20 loop -- FOR循环从1到20,将数组中的数据求和,此处为计算标准差求和部分
var_sum := var_sum + power((arr_close(j) - var_MB), 2);
end loop; -- 结束循环
for j in 1 .. 19 loop -- 数组中全部数据往前移动一个元素,留最后一个位置给下次的收盘价
arr_close(j) := arr_close(j + 1);
end loop; -- 结束循环
var_MD := sqrt(var_sum / 20); -- 计算完整的标准差
var_UP := var_MB + 2 * var_MD; -- 公式 UP = MB + 2 * MD
var_DN := var_MB - 2 * var_MD; -- 公式 DN = MB - 2 * MD
var_count := 19; -- 数组长度变为19
var_sum := 0; -- 清空数据,方便下次求和
update BOLL set BOLLUP = round(var_UP,2), BOLLDN = round(var_DN,2), BOLLMB = var_MB -- 更新数据
where dates = i.dates;
end if; -- 结束判断
end loop; -- 结束游标FOR循环
commit; -- 提交,使用update、delete、insert、alter时一定要提交
END; -- 结束存储过程
计算布林线的时候只要解决计算MD这个方差,其他都很容易就能代入公式计算了
其中我封装了一个GETMA获取均值的函数:
CREATE OR REPLACE FUNCTION GETMA(var_date in date, days in number)
RETURN number
AS
var_MA number;
var_exists number;
var_sql varchar(100) := '';
BEGIN
select count(*) into var_exists
from user_tab_cols
where table_name= 'STOCKDATA' and column_name= 'MA'||days;
if var_exists = 0 then
MA(days);
end if;
var_sql := 'select MA'||days||' from stockdata where dates = '''||var_date||'''';
execute immediate var_sql into var_MA;
RETURN var_MA;
END;
这里面又有一个调用存储过程MA,是我之前写的计算日均线存储过程,所以关联性确实很大,大家也可以用自己的方法,我也只是给出一个参考,主要还是学习思路吧
结尾
我相信还有比我更好、更快的计算思路和方法,如果有小伙伴的更好可以分享出来大家互相学习