HQChart实战教程67-worker批量计算股票指标

news2025/2/24 12:10:58

HQChart实战教程67-worker批量计算股票指标

  • 什么是Worker
  • 批量指标计算
  • 示例地址
  • 步骤
    • 1. 创建一个后台工作线程类
    • 2. 发送指标计算任务
    • 3. 接收计算结果
    • 数据对接
  • 完整源码
    • demo_workerthread_sina.html
    • hqchart_worker_sina.js
  • HQChart插件源码地址

什么是Worker

Worker 接口是 Web Workers API 的一部分,指的是一种可由脚本创建的后台任务,任务执行中可以向其创建者收发信息。

批量指标计算

通过把指标计算迁移到后台线程中,可以提高效率(可以开N个后台线程,平行计算),也不会卡主线程。HQChart通达信指标计算引擎是一个独立的计算模块,通过在后台线程中独立调用计算模块就可以达到批量计算指标

示例地址

在这里插入图片描述

https://jones2000.github.io/HQChart/webhqchart.demo/samples/demo_workerthread_sina.html
注意:K线数据是网上找的,不支持跨域,调试的时候需要给浏览器安装一个跨域插件,就可以用
可以参看教程解决Chrome本地调试跨域.

步骤

1. 创建一个后台工作线程类

hqchart内置一个后台指标计算的工作线程类HQChartScriptWorker, 可以直接派生这个类, 然后把数据对接上就可以了。 其他的基类都封装好了。
HQChartScriptWorker源码地址:https://github.com/jones2000/HQChart/blob/master/webhqchart/umychart.worker.js

2. 发送指标计算任务

通过系统api接口postMessage可以发送数据给工作线程

function RunIndexScript(symbol, index, jobID)
{
      var message=
      {
          ID:JSCHART_WORKER_MESSAGE_ID.EXECUTE_SCRIPT, //任务类型(固定值)
          AryIndex:  //需要执行的指标名称或指标脚本
          [
              {Index:index},
              //{Index:"MACD"},
              //{Index:"TEST", Name:"测试脚本", Script:'T:MA((L+H)/2,10)'}
          ],

          Symbol:symbol,	//股票代码
          Name:symbol,		//股票名称
          Period:5,   //5分钟K线
          Right:0,   //复权
          HQDataType:HQ_DATA_TYPE.KLINE_ID, //K线指标(固定值)
          Guid:jobID,
          IsApiPeriod:true, //后台计算周期
      };

      g_HQWorker.postMessage(message);
  }

3. 接收计算结果

绑定onmessage的回调,就可以

var g_HQWorker=new Worker("hqchart_worker_sina.js");
g_HQWorker.onmessage=(e)=>{ OnRecvWorkerMessage(e); }

function OnRecvWorkerMessage(e)
{
    if (e.data.ID==JSCHART_WORKER_MESSAGE_ID.FINISH_EXECUTE_SCRIPT)  //指标计算完成
    {
        console.log("[OnRecvWorkerMessage] data=", e.data);
    }
}

数据结构
在这里插入图片描述

{
   Data:指标数据 { Date:日期, Time:时间,  Out:指标输出变量, Stock:股票信息,  Index:指标名称 }
   IndexInfo: 指标信息
   JobInfo: 发送指标命令的内容
}

注意: 返回的指标结果数据是一个数组

数据对接

和前端图形一样,通过NetworkFilter对接数据

function JSSampleScriptWorker()
{
    this.newMethod=HQChartScriptWorker;   //派生
    this.newMethod();
    delete this.newMethod;

    this.NetworkFilter=function(data, callback, indexInfo, message)
    {
    //数据对接
        console.log(`[JSSampleScriptWorker::NetworkFilter] [${data.Name}][${data.Explain}] data=`, data);

        if (data.Name=="JSSymbolData::GetSymbolData")
        {
        
        }
............
    }
      

完整源码

demo_workerthread_sina.html

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">  
<head>  
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />  

<title>工作线程计算</title>  
    
</head>  
<body>
    <div id="range_title">5分钟周期指标计算</div>
    <br/>
    <div>
        <div class="table_row">
            <span class="item_symbol">600000.sh</span>
            <span class="item_indexname">MA</span>
            <div id="item_result_1">计算结果</div>
        </div>

        <div class="table_row">
            <span class="item_symbol">605166.sh</span>
            <span class="item_indexname">RSI</span>
            <div id="item_result_2">计算结果</div>
        </div>

        <div class="table_row">
            <span class="item_symbol">601169.sh</span>
            <span class="item_indexname">MACD</span>
            <div id="item_result_3">计算结果</div>
        </div>
    </div>

    <br/>
    <div>
        <span id="button_1" class="btn-style">开始计算</span>
    </div>

    <script src="../jscommon/umychart.resource/js/jquery.min.js"></script>
    <script src='../jscommon/umychart.console.js'></script>     <!-- 日志输出 -->
    <script src="../jscommon/umychart.network.js"></script>     <!-- 网络请求分装 -->
    <script src="../jscommon/umychart.js"></script>             <!-- K线图形 -->
    <script src="../jscommon/umychart.complier.js"></script>    <!-- 麦语言解析执行器 -->
    <script src="../jscommon/umychart.index.data.js"></script>  <!-- 基础指标库 -->
    <script src="../jscommon/umychart.style.js"></script>       <!-- 白色风格和黑色风格配置信息 -->

   
    <script>
        
        var g_HQWorker=new Worker("hqchart_worker_sina.js");
        g_HQWorker.onmessage=(e)=>{ OnRecvWorkerMessage(e); }

        var jobCount=1;
        var job_list=
        [
            { Symbol:"sh600000.sh", Index:"MA", OutDomID:"item_result_1" },
            { Symbol:"sh605166.sh", Index:"RSI", OutDomID:"item_result_2" },
            { Symbol:"sh601169.sh", Index:"MACD", OutDomID:"item_result_3" },
        ];

        function OnRecvWorkerMessage(e)
        {
            if (e.data.ID==JSCHART_WORKER_MESSAGE_ID.FINISH_EXECUTE_SCRIPT)
            {
                console.log("[OnRecvWorkerMessage] data=", e.data);
                var jobID=e.data.JobInfo.Guid;

                var aryDate=e.data.Data.Date;
                var aryTime=e.data.Data.Time;

                var index=aryTime.length-10; //输出最后条记录
                var aryResult=[];
                var outText="";
                for(var i=index;i<aryTime.length;++i)
                {
                    var date=aryDate[i];
                    var time=aryTime[i];

                    var text=`Date=${date}, Time:${time} `;
                    for(var j=0;j<e.data.Data.Out.length;++j)
                    {
                        var name=e.data.Data.Out[j].Name;
                        var value=e.data.Data.Out[j].Data[i];

                        text+=`${name}=${value.toFixed(4)}, `;
                    }
                    aryResult.push(text);

                    outText+=text;
                    outText+='<br>';
                }

                var domID=null;
                for(var i=0;i<job_list.length;++i)
                {
                    var item=job_list[i];
                    if (item.JobID==jobID)
                    {
                        domID=item.OutDomID;
                        break;
                    }
                }

                if (!domID) return;

                $("#"+domID)[0].innerHTML=outText;
            }
        }

        
        function RunIndexScript(symbol, index, jobID)
        {
            var message=
            {
                ID:JSCHART_WORKER_MESSAGE_ID.EXECUTE_SCRIPT,
                AryIndex:
                [
                    {Index:index},
                    //{Index:"MACD"},
                    //{Index:"TEST", Name:"测试脚本", Script:'T:MA((L+H)/2,10)'}
                ],

                Symbol:symbol,
                Name:symbol,
                Period:5,   //5分钟K线
                Right:0,
                HQDataType:HQ_DATA_TYPE.KLINE_ID,
                Guid:jobID,
                IsApiPeriod:true,
            };

            g_HQWorker.postMessage(message);
        }

        function RunAll()
        {
            for(var i=0;i<job_list.length;++i)
            {
                var item=job_list[i];
                item.JobID=++jobCount;

                RunIndexScript(item.Symbol, item.Index, item.JobID);
            }
        }

        $(function () 
        {
            $("#button_1").click(function() { RunAll(); } );
        })

      
    </script>  
</body>  
</html>



<style>

.btn-style
{
    padding: 3px 8px;
    border: 1px solid #ececec;
    border-radius: 5px;
    background-color: #f5f5f5;
    cursor: pointer;
}

.item_symbol
{
    display:block;
    line-height: 50px;
    width:100px;
    align-items: center;
}

.item_indexname
{
    display:block;
    line-height: 50px;
    width:100px;
    align-items: center;
}

.table_row
{
    display: flex; 
    height: 200px;
    border-style:solid;
    border-width:1px;
    border-color:#BEBEBE;
}

    
</style>

hqchart_worker_sina.js

/
// 工作线程
//
//


importScripts("../jscommon/umychart.complier.js","../jscommon/umychart.js", "../jscommon/umychart.index.data.js","../jscommon/umychart.worker.js");

JSConsole.Complier.Log=()=>{ }

function JSSampleScriptWorker()
{
    this.newMethod=HQChartScriptWorker;   //派生
    this.newMethod();
    delete this.newMethod;

    this.NetworkFilter=function(data, callback, indexInfo, message)
    {
        //数据对接
        console.log(`[JSSampleScriptWorker::NetworkFilter] [${data.Name}][${data.Explain}] data=`, data);

        if (data.Name=="JSSymbolData::GetSymbolData")
        {
            var requestData=data.Request.Data;
            if (requestData.period==5)    //5分钟K线
            {
                var symbol=requestData.symbol;
                symbol=symbol.replace(".sh","");
                //http://money.finance.sina.com.cn/quotes_service/api/json_v2.php/CN_MarketData.getKLineData?symbol=sz000001&scale=5&ma=5&datalen=1023
                var url=`https://money.finance.sina.com.cn/quotes_service/api/json_v2.php/CN_MarketData.getKLineData?symbol=${symbol}&scale=5&ma=5&datalen=1023`;

                console.log(`[JSSampleScriptWorker::NetworkFilter] url=${url}`);

                var response=this.HttpRequest(url);
                if (response.response)
                {
                    var recv=JSON.parse(response.response);

                    this.RecvHistoryMinuteData(recv, callback, data);
                }
            }
        }
        
    }

    this.RecvHistoryMinuteData=function(recv, callback, data)
    {
        var hqChartData={code:0, data:[] };
        hqChartData.symbol=hqChartData.name=data.Request.Data.symbol;

        var yClose=null;
        for(var i=0;i<recv.length;++i)
        {
            var item=recv[i];

            var dateTime=new Date(item.day);
            var date=dateTime.getFullYear()*10000+(dateTime.getMonth()+1)*100+dateTime.getDate();
            var time=dateTime.getHours()*100+dateTime.getMinutes();

            var close=parseFloat(item.close);
            var high=parseFloat(item.high);
            var low=parseFloat(item.low);
            var open=parseFloat(item.open);
            var vol=parseFloat(item.volume);
            var amount=null;

            if (close==null) continue;

            var newItem=[ date, yClose, open, high, low, close, vol, amount, time];
            hqChartData.data.push(newItem);

            yClose=close;
        }

       
        console.log("[JSSampleScriptWorker::RecvHistoryMinuteData] hqchartData ", hqChartData)
        callback(hqChartData);
    }

    this.HttpRequest=function(url)
    {
        var req = new XMLHttpRequest();
        req.open('GET', url, false);
        req.onerror=(e)=>{ 
            console.log(e);
        }
        req.send();
        return req;
    }
}

var g_ScriptWorker=new JSSampleScriptWorker();


g_ScriptWorker.Create();

HQChart插件源码地址

https://github.com/jones2000/HQChart

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1159106.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

DDoS类型攻击对企业造成的危害

超级科技实验室的一项研究发现&#xff0c;每十家企业中&#xff0c;有四家(39%)企业没有做好准备应对DDoS攻击&#xff0c;保护自身安全。且不了解应对这类攻击最有效的保护手段是什么。 由于缺乏相关安全知识和保护&#xff0c;使得企业面临巨大的风险。 当黑客发动DDoS攻击…

PS新手教程-如何使用PS把图片置入另一张图片里

如何使用PS把图片置入另一张图片里&#xff1f;给大家介绍如何使用PS把图片置入另一张图片里&#xff0c;一起来看看吧。 1.打开ps软件&#xff0c;按快捷键CtrlO键&#xff0c;弹出打开对话框&#xff0c;选中一张图片&#xff0c;单击“打开”按钮。 2.在菜单栏“文件”中&a…

ubuntu(18.04)中架设HiGlass docker镜像服务,已尝试mcool、bedpe、wig格式文件

前言 使用到的软件 docker 文档 &#xff1a; https://www.docker.com/ HiGlass 文档&#xff1a;http://docs.higlass.io/higlass_docker.html#running-locally https://github.com/higlass/higlass-dockerhiglass-docker 地址&#xff1a;https://github.com/higla…

模型应用系实习生-模型训练笔记(更新至线性回归、Ridge回归、Lasso回归、Elastic Net回归、决策树回归、梯度提升树回归和随机森林回归)

sklearn机械学习模型步骤以及模型 一、训练准备&#xff08;x_train, x_test, y_train, y_test&#xff09;1.1 导包1.2 数据要求1.21 导入数据1.22 数据类型查看检测以及转换1.22 划分数据 二、回归2.1 线性回归2.2 随机森林回归2.3 GradientBoostingRegressor梯度提升树回归2…

工业4G路由器桥接多网络,提升工业环境网络覆盖

一款专为工业环境应用所设计的物联网通讯设备“工业4G路由器”&#xff0c;它具有多种功能和特性。其中之一就是桥接功能&#xff0c;在工业领域中被广泛应用并起着重要的通信作用。 桥接功能是指工业4G路由器通过无线网络的方式&#xff0c;为不同的工业设备提供网络并将其连…

基于人工电场算法的无人机航迹规划-附代码

基于人工电场算法的无人机航迹规划 文章目录 基于人工电场算法的无人机航迹规划1.人工电场搜索算法2.无人机飞行环境建模3.无人机航迹规划建模4.实验结果4.1地图创建4.2 航迹规划 5.参考文献6.Matlab代码 摘要&#xff1a;本文主要介绍利用人工电场算法来优化无人机航迹规划。 …

解决【spring boot】Process finished with exit code 0的问题

文章目录 1. 复现错误2. 分析错误3. 解决问题 1. 复现错误 今天从https://start.spring.io下载配置好的spring boot项目&#xff1a; 启动后却报出如下错误&#xff1a; 即Process finished with exit code 0 2. 分析错误 Process finished with exit code 0翻译成中文进程已完…

注册中心ZK、nameServer、eureka、Nacos介绍与对比

前言 注册中心的由来 微服务架构是存在着很多跨服务调用,每个服务都存在着多个节点,如果有多个提供者和消费者,当提供者增加/减少或者消费者增加/减少,双方都需要感知发现。所以诞生了注册中心这个中间件。 市面上有很多注册中心,如 Zookeeper、NameServer、Eureka、Na…

SaaS可配置性设计要点

1 引言 考虑到系统SaaS需求&#xff0c;就成熟的SaaS应用而言&#xff0c;元数据服务是为用户提供定制和配置应用、满足其特定需求的主要手段。 可配置能力主要反映在这4个方面&#xff1a;1 程序外观&#xff1b;2 工作流程与业务规则&#xff1b;3 数据模型&#xff1b…

docker 存储目录迁移

参考&#xff1a;【Docker专题】WSL镜像包盘符迁移详细笔记 - 掘金 docker迁移 一 默认目录 Windows版本&#xff08;Windows 10 wsl 2&#xff09;docker 默认程序安装到c盘&#xff0c;数据存放于 C:\Users\当前用户名\AppData\Local\Docker\wsl\data\ext4.vhdx 这样会导致…

多机多卡分布式训练

1. 环境搭建 分布式训练框架&#xff1a;acceleratedeepspeedpdsh(可有可无)基础环境&#xff1a;cuda、显卡驱动、pytorch 1.1 安装相关包 cuda安装&#xff1a;参考官网安装步骤 wget https://developer.download.nvidia.com/compute/cuda/11.8.0/local_installers/cuda-…

python raise语句的两种用法

python raise语句的两种用法 1、主动抛出异常的方法是使用 raise 语句&#xff1a; raise ValueError()2、可以同时指明错误原因&#xff1a; raise ValueError("输入值不符合要求")**3、这个函数没有处理可能出错的情况。**比如函数的age参数不能随意取值&#x…

呵护笔记本屏幕,同时获得更全方位的隐私保护

之前看到很多人都在给手机贴防窥膜&#xff0c;但是我试过之后觉得效果并不好。其实&#xff0c;防窥膜这个东西用在笔记本上会更实用一些。特别是那些经常在公共场所办公的朋友&#xff0c;比如我。最近我发现了一款威宝的防窥膜&#xff0c;质量非常靠谱。如果你也有同样的需…

天体学爱好者基础知识-太阳系//未完待续,业余者的学习

难过的时候&#xff0c;仰望天空吧&#xff0c;人类有时候&#xff0c;做的事情真的太愚昧且无聊了&#xff0c;渺小的尘埃&#xff0c;也可以飘际宇宙。 太阳系-八大行星 卫星围绕着恒星公转。行星必须围绕着恒星公转。 什么是行星&#xff1f;行星和恒星、卫星有什么区别&am…

qt5使用QWebEngineView崩溃的问题

在使用QWebEngineView加载崩溃 需要把下图的文件放入exe文件中

7年经验之谈 —— 常用的接口抓包工具和接口测试工具!

一、接口 统称为API&#xff0c;它是指程序与程序之间的对接、交接。 二、接口测试 它主要用于检测外部系统与系统之间以及内部各个子系统之间的交互点&#xff0c;主要是为了检验不同组件&#xff08;模块&#xff09;之间数据的传递是否正确&#xff0c;同时接口测试还要测…

Google play开发者账号被封的几种常见原因及相关解决思路

在Google paly上&#xff0c;每天都有大量的应用被成功发布&#xff0c;同时也有很多开发者账号被封禁。特别是在今年的十月份之前&#xff0c;谷歌的"封号潮"给很多开发者带来了沉重的打击。不过&#xff0c;令人欣慰的是&#xff0c;自十月份之后&#xff0c;情况逐…

518抽奖软件,是否支持作弊~内定~指定中奖人~设置范围

518抽奖软件简介 518抽奖软件&#xff0c;518我要发&#xff0c;超好用的年会抽奖软件&#xff0c;简约设计风格。 包含文字号码抽奖、照片抽奖两种模式&#xff0c;支持姓名抽奖、号码抽奖、数字抽奖、照片抽奖。(www.518cj.net) 主打纯净&#xff0c;不可作弊 市面上&…

【C语言】备战校赛Day1

日期:11.1 星期二 L1-001 Hello World 题目描述 这道超级简单的题目没有任何输入。 你只需要在一行中输出著名短句“Hello World!”就可以了。 输入样例: 无 输出样例: Hello World! 解题代码 int main() {printf("Hello World!");return 0; } 该题较为简单,但要注…

Web安全系列——CSRF攻击

文章首发公众号&#xff1a; 海天二路搬砖工 前言 CSRF 攻击是Web应用中最常见的攻击方式之一。 CSRF攻击给网站身份验证、用户账户和个人隐私带来极大威胁。了解 CSRF 攻击的流程、原理与防御措施&#xff0c;是构建安全可靠的Web应用程序的必要条件。 什么是CSRF攻击 CS…