stock-sdk 1.2.0 → 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +62 -13
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -5,12 +5,41 @@
|
|
|
5
5
|
[](https://github.com/chengzuopeng/stock-sdk/blob/master/LICENSE)
|
|
6
6
|
[](https://github.com/chengzuopeng/stock-sdk)
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
**[English](./README_EN.md)** | 中文
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
为 **前端和 Node.js 设计的股票行情 SDK**。
|
|
11
|
+
|
|
12
|
+
无需 Python、无需后端服务,直接在 **浏览器或 Node.js** 中获取 **A 股 / 港股 / 美股 / 公募基金** 的实时行情与 K 线数据。
|
|
13
|
+
|
|
14
|
+
**✨ 零依赖 | 🌐 Browser + Node.js | 📦 <10KB | 🧠 完整 TypeScript 类型**
|
|
11
15
|
|
|
12
16
|
📦 [NPM](https://www.npmjs.com/package/stock-sdk) | 📖 [GitHub](https://github.com/chengzuopeng/stock-sdk) | 🎮 [在线演示](https://chengzuopeng.github.io/stock-sdk/)
|
|
13
17
|
|
|
18
|
+
## Why stock-sdk?
|
|
19
|
+
|
|
20
|
+
如果你是前端工程师,可能遇到过这些问题:
|
|
21
|
+
|
|
22
|
+
* 股票行情工具大多是 **Python 生态**,前端难以直接使用
|
|
23
|
+
* 想做行情看板 / Demo,不想额外维护后端服务
|
|
24
|
+
* 财经接口返回格式混乱、编码复杂(GBK / 并发 / 批量)
|
|
25
|
+
* AkShare 很强,但并不适合浏览器或 Node.js 项目
|
|
26
|
+
|
|
27
|
+
**stock-sdk 的目标很简单:**
|
|
28
|
+
|
|
29
|
+
> 让前端工程师,用最熟悉的 JavaScript / TypeScript,优雅地获取股票行情数据。
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## 使用场景
|
|
34
|
+
|
|
35
|
+
* 📊 股票行情看板(Web / Admin)
|
|
36
|
+
* 📈 数据可视化(ECharts / TradingView)
|
|
37
|
+
* 🎓 股票 / 金融课程 Demo
|
|
38
|
+
* 🧪 量化策略原型验证(JS / Node)
|
|
39
|
+
* 🕒 Node.js 定时抓取行情数据
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
14
43
|
## 特性
|
|
15
44
|
|
|
16
45
|
- ✅ **零依赖**,轻量级(压缩后 < 10KB)
|
|
@@ -32,22 +61,38 @@ yarn add stock-sdk
|
|
|
32
61
|
pnpm add stock-sdk
|
|
33
62
|
```
|
|
34
63
|
|
|
35
|
-
##
|
|
64
|
+
## 快速开始(10 行 Demo)
|
|
36
65
|
|
|
37
|
-
```
|
|
66
|
+
```ts
|
|
38
67
|
import { StockSDK } from 'stock-sdk';
|
|
39
68
|
|
|
40
69
|
const sdk = new StockSDK();
|
|
41
70
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
71
|
+
const quotes = await sdk.getSimpleQuotes([
|
|
72
|
+
'sh000001',
|
|
73
|
+
'sz000858',
|
|
74
|
+
'sh600519',
|
|
75
|
+
]);
|
|
76
|
+
|
|
77
|
+
quotes.forEach(q => {
|
|
78
|
+
console.log(`${q.name}: ${q.price} (${q.changePercent}%)`);
|
|
79
|
+
});
|
|
80
|
+
```
|
|
45
81
|
|
|
46
|
-
|
|
47
|
-
const klines = await sdk.getHistoryKline('000001', { period: 'daily' });
|
|
82
|
+
## 示例:全市场 A 股行情
|
|
48
83
|
|
|
49
|
-
|
|
50
|
-
|
|
84
|
+
前端直接一次性获取全市场 A 股行情(5000+股票),无需 Python 或后端服务。
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
const allQuotes = await sdk.getAllAShareQuotes({
|
|
88
|
+
batchSize: 300,
|
|
89
|
+
concurrency: 5,
|
|
90
|
+
onProgress: (completed, total) => {
|
|
91
|
+
console.log(`进度: ${completed}/${total}`);
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
console.log(`共获取 ${allQuotes.length} 只股票`);
|
|
51
96
|
```
|
|
52
97
|
|
|
53
98
|
## API 文档
|
|
@@ -276,7 +321,7 @@ interface TodayTimelineResponse {
|
|
|
276
321
|
interface TodayTimeline {
|
|
277
322
|
time: string; // 时间 HH:mm
|
|
278
323
|
price: number; // 成交价
|
|
279
|
-
volume: number; //
|
|
324
|
+
volume: number; // 累计成交量(股)
|
|
280
325
|
amount: number; // 累计成交额(元)
|
|
281
326
|
avgPrice: number; // 当日均价
|
|
282
327
|
}
|
|
@@ -495,7 +540,7 @@ console.log(raw[0].fields); // ['51', '五 粮 液', '000858', ...]
|
|
|
495
540
|
|
|
496
541
|
---
|
|
497
542
|
|
|
498
|
-
##
|
|
543
|
+
## 浏览器直接使用
|
|
499
544
|
|
|
500
545
|
SDK 使用原生 `TextDecoder` 解码 GBK 编码数据,无需额外 polyfill。
|
|
501
546
|
|
|
@@ -537,3 +582,7 @@ yarn dev
|
|
|
537
582
|
---
|
|
538
583
|
|
|
539
584
|
📦 [NPM](https://www.npmjs.com/package/stock-sdk) | 📖 [GitHub](https://github.com/chengzuopeng/stock-sdk) | 🎮 [在线演示](https://chengzuopeng.github.io/stock-sdk/) | 🐛 [Issues](https://github.com/chengzuopeng/stock-sdk/issues)
|
|
585
|
+
|
|
586
|
+
---
|
|
587
|
+
|
|
588
|
+
如果这个项目对你有帮助,欢迎 Star ⭐ 或提出 Issue 反馈。
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var N=Object.defineProperty;var H=Object.getOwnPropertyDescriptor;var E=Object.getOwnPropertyNames;var _=Object.prototype.hasOwnProperty;var z=(a,e)=>{for(var n in e)N(a,n,{get:e[n],enumerable:!0})},B=(a,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let t of E(e))!_.call(a,t)&&t!==n&&N(a,t,{get:()=>e[t],enumerable:!(r=H(e,t))||r.enumerable});return a};var W=a=>B(N({},"__esModule",{value:!0}),a);var Y={};z(Y,{StockSDK:()=>A,default:()=>K});module.exports=W(Y);function U(a){return new TextDecoder("gbk").decode(a)}function s(a){if(!a||a==="")return 0;let e=parseFloat(a);return Number.isNaN(e)?0:e}function u(a){if(!a||a==="")return null;let e=parseFloat(a);return Number.isNaN(e)?null:e}function
|
|
1
|
+
"use strict";var N=Object.defineProperty;var H=Object.getOwnPropertyDescriptor;var E=Object.getOwnPropertyNames;var _=Object.prototype.hasOwnProperty;var z=(a,e)=>{for(var n in e)N(a,n,{get:e[n],enumerable:!0})},B=(a,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let t of E(e))!_.call(a,t)&&t!==n&&N(a,t,{get:()=>e[t],enumerable:!(r=H(e,t))||r.enumerable});return a};var W=a=>B(N({},"__esModule",{value:!0}),a);var Y={};z(Y,{StockSDK:()=>A,default:()=>K});module.exports=W(Y);function U(a){return new TextDecoder("gbk").decode(a)}function s(a){if(!a||a==="")return 0;let e=parseFloat(a);return Number.isNaN(e)?0:e}function u(a){if(!a||a==="")return null;let e=parseFloat(a);return Number.isNaN(e)?null:e}function I(a){let e=a.split(";").map(r=>r.trim()).filter(Boolean),n=[];for(let r of e){let t=r.indexOf("=");if(t<0)continue;let o=r.slice(0,t).trim();o.startsWith("v_")&&(o=o.slice(2));let i=r.slice(t+1).trim();i.startsWith('"')&&i.endsWith('"')&&(i=i.slice(1,-1));let m=i.split("~");n.push({key:o,fields:m})}return n}function x(a,e){let n=[];for(let r=0;r<a.length;r+=e)n.push(a.slice(r,r+e));return n}async function L(a,e){let n=[],r=[];for(let t of a){let o=Promise.resolve().then(()=>t()).then(i=>{n.push(i)});if(r.push(o),r.length>=e){await Promise.race(r);for(let i=r.length-1;i>=0;i--)await Promise.race([r[i].then(()=>"fulfilled"),Promise.resolve("pending")])==="fulfilled"&&r.splice(i,1)}}return await Promise.all(r),n}var G="https://qt.gtimg.cn",V="https://web.ifzq.gtimg.cn/appstock/app/minute/query",J="https://assets.linkdiary.cn/shares/ashare-code.json",M="https://push2his.eastmoney.com/api/qt/stock/kline/get",X="https://push2his.eastmoney.com/api/qt/stock/trends2/get";function D(a){return a.startsWith("sh")?"1":a.startsWith("sz")||a.startsWith("bj")?"0":a.startsWith("6")?"1":"0"}function l(a){if(!a||a===""||a==="-")return null;let e=parseFloat(a);return Number.isNaN(e)?null:e}var A=class{constructor(e={}){this.baseUrl=e.baseUrl??G,this.timeout=e.timeout??1e4}async request(e){let n=`${this.baseUrl}/?q=${encodeURIComponent(e)}`,r=new AbortController,t=setTimeout(()=>r.abort(),this.timeout);try{let o=await fetch(n,{signal:r.signal});if(!o.ok)throw new Error(`HTTP error! status: ${o.status}`);let i=await o.arrayBuffer(),m=U(i);return I(m)}finally{clearTimeout(t)}}async getFullQuotes(e){return!e||e.length===0?[]:(await this.request(e.join(","))).filter(r=>r.fields&&r.fields.length>0&&r.fields[0]!=="").map(r=>this.parseFullQuote(r.fields))}parseFullQuote(e){let n=[];for(let t=0;t<5;t++)n.push({price:s(e[9+t*2]),volume:s(e[10+t*2])});let r=[];for(let t=0;t<5;t++)r.push({price:s(e[19+t*2]),volume:s(e[20+t*2])});return{marketId:e[0]??"",name:e[1]??"",code:e[2]??"",price:s(e[3]),prevClose:s(e[4]),open:s(e[5]),volume:s(e[6]),outerVolume:s(e[7]),innerVolume:s(e[8]),bid:n,ask:r,time:e[30]??"",change:s(e[31]),changePercent:s(e[32]),high:s(e[33]),low:s(e[34]),volume2:s(e[36]),amount:s(e[37]),turnoverRate:u(e[38]),pe:u(e[39]),amplitude:u(e[43]),circulatingMarketCap:u(e[44]),totalMarketCap:u(e[45]),pb:u(e[46]),limitUp:u(e[47]),limitDown:u(e[48]),volumeRatio:u(e[49]),avgPrice:u(e[51]),peStatic:u(e[52]),peDynamic:u(e[53]),high52w:u(e[67]),low52w:u(e[68]),circulatingShares:u(e[72]),totalShares:u(e[73]),raw:e}}async getSimpleQuotes(e){if(!e||e.length===0)return[];let n=e.map(t=>`s_${t}`);return(await this.request(n.join(","))).filter(t=>t.fields&&t.fields.length>0&&t.fields[0]!=="").map(t=>this.parseSimpleQuote(t.fields))}parseSimpleQuote(e){return{marketId:e[0]??"",name:e[1]??"",code:e[2]??"",price:s(e[3]),change:s(e[4]),changePercent:s(e[5]),volume:s(e[6]),amount:s(e[7]),marketCap:u(e[9]),marketType:e[10]??"",raw:e}}async getFundFlow(e){if(!e||e.length===0)return[];let n=e.map(t=>`ff_${t}`);return(await this.request(n.join(","))).filter(t=>t.fields&&t.fields.length>0&&t.fields[0]!=="").map(t=>this.parseFundFlow(t.fields))}parseFundFlow(e){return{code:e[0]??"",mainInflow:s(e[1]),mainOutflow:s(e[2]),mainNet:s(e[3]),mainNetRatio:s(e[4]),retailInflow:s(e[5]),retailOutflow:s(e[6]),retailNet:s(e[7]),retailNetRatio:s(e[8]),totalFlow:s(e[9]),name:e[12]??"",date:e[13]??"",raw:e}}async getPanelLargeOrder(e){if(!e||e.length===0)return[];let n=e.map(t=>`s_pk${t}`);return(await this.request(n.join(","))).filter(t=>t.fields&&t.fields.length>0&&t.fields[0]!=="").map(t=>this.parsePanelLargeOrder(t.fields))}parsePanelLargeOrder(e){return{buyLargeRatio:s(e[0]),buySmallRatio:s(e[1]),sellLargeRatio:s(e[2]),sellSmallRatio:s(e[3]),raw:e}}async getHKQuotes(e){if(!e||e.length===0)return[];let n=e.map(t=>`r_hk${t}`);return(await this.request(n.join(","))).filter(t=>t.fields&&t.fields.length>0&&t.fields[0]!=="").map(t=>this.parseHKQuote(t.fields))}parseHKQuote(e){return{marketId:e[0]??"",name:e[1]??"",code:e[2]??"",price:s(e[3]),prevClose:s(e[4]),open:s(e[5]),volume:s(e[6]),time:e[30]??"",change:s(e[31]),changePercent:s(e[32]),high:s(e[33]),low:s(e[34]),amount:s(e[36]),lotSize:u(e[40]),circulatingMarketCap:u(e[46]),totalMarketCap:u(e[47]),currency:e[e.length-3]??"",raw:e}}async getUSQuotes(e){if(!e||e.length===0)return[];let n=e.map(t=>`s_us${t}`);return(await this.request(n.join(","))).filter(t=>t.fields&&t.fields.length>0&&t.fields[0]!=="").map(t=>this.parseUSQuote(t.fields))}parseUSQuote(e){return{marketId:e[0]??"",name:e[1]??"",code:e[2]??"",price:s(e[3]),change:s(e[4]),changePercent:s(e[5]),volume:s(e[6]),amount:s(e[7]),marketCap:u(e[8]),raw:e}}async getFundQuotes(e){if(!e||e.length===0)return[];let n=e.map(t=>`jj${t}`);return(await this.request(n.join(","))).filter(t=>t.fields&&t.fields.length>0&&t.fields[0]!=="").map(t=>this.parseFundQuote(t.fields))}parseFundQuote(e){return{code:e[0]??"",name:e[1]??"",nav:s(e[5]),accNav:s(e[6]),change:s(e[7]),navDate:e[8]??"",raw:e}}async batchRaw(e){return this.request(e)}async getTodayTimeline(e){let n=new AbortController,r=setTimeout(()=>n.abort(),this.timeout);try{let t=await fetch(`${V}?code=${e}`,{signal:n.signal});if(!t.ok)throw new Error(`HTTP error! status: ${t.status}`);let o=await t.json();if(o.code!==0)throw new Error(o.msg||"API error");let i=o.data?.[e];if(!i)return{code:e,date:"",data:[]};let m=i.data?.data||[],d=i.data?.date||"",h=!1;if(m.length>0){let p=m[0].split(" "),c=parseFloat(p[1])||0,g=parseInt(p[2],10)||0,f=parseFloat(p[3])||0;g>0&&c>0&&f/g>c*50&&(h=!0)}let k=m.map(p=>{let c=p.split(" "),g=c[0],f=`${g.slice(0,2)}:${g.slice(2,4)}`,y=parseInt(c[2],10)||0,b=parseFloat(c[3])||0,w=h?y*100:y,P=w>0?b/w:0;return{time:f,price:parseFloat(c[1])||0,volume:w,amount:b,avgPrice:Math.round(P*100)/100}});return{code:e,date:d,data:k}}finally{clearTimeout(r)}}async getAShareCodeList(e=!0){let n=new AbortController,r=setTimeout(()=>n.abort(),this.timeout);try{let t=await fetch(J,{signal:n.signal});if(!t.ok)throw new Error(`HTTP error! status: ${t.status}`);let o=await t.json();return e?o:o.map(i=>i.replace(/^(sh|sz|bj)/,""))}finally{clearTimeout(r)}}async getAllAShareQuotes(e={}){let{batchSize:n=500,concurrency:r=7,onProgress:t}=e,o=await this.getAShareCodeList(),i=x(o,n),m=i.length,d=0,h=i.map(p=>async()=>{let c=await this.getFullQuotes(p);return d++,t&&t(d,m),c});return(await L(h,r)).flat()}async getAllQuotesByCodes(e,n={}){let{batchSize:r=500,concurrency:t=7,onProgress:o}=n,i=x(e,r),m=i.length,d=0,h=i.map(p=>async()=>{let c=await this.getFullQuotes(p);return d++,o&&o(d,m),c});return(await L(h,t)).flat()}async getHistoryKline(e,n={}){let{period:r="daily",adjust:t="hfq",startDate:o="19700101",endDate:i="20500101"}=n,m=e.replace(/^(sh|sz|bj)/,""),d={daily:"101",weekly:"102",monthly:"103"},h={"":"0",qfq:"1",hfq:"2"},k=`${D(m)}.${m}`,p=new URLSearchParams({fields1:"f1,f2,f3,f4,f5,f6",fields2:"f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61,f116",ut:"7eea3edcaed734bea9cbfc24409ed989",klt:d[r],fqt:h[t],secid:k,beg:o,end:i}),c=new AbortController,g=setTimeout(()=>c.abort(),this.timeout);try{let f=await fetch(`${M}?${p.toString()}`,{signal:c.signal});if(!f.ok)throw new Error(`HTTP error! status: ${f.status}`);let b=(await f.json())?.data?.klines;return!Array.isArray(b)||b.length===0?[]:b.map(w=>{let[P,T,v,Q,S,F,j,q,C,R,$]=w.split(",");return{date:P,code:m,open:l(T),close:l(v),high:l(Q),low:l(S),volume:l(F),amount:l(j),amplitude:l(q),changePercent:l(C),change:l(R),turnoverRate:l($)}})}finally{clearTimeout(g)}}async getMinuteKline(e,n={}){let{period:r="1",adjust:t="hfq",startDate:o="1979-09-01 09:32:00",endDate:i="2222-01-01 09:32:00"}=n,m=e.replace(/^(sh|sz|bj)/,""),d=`${D(m)}.${m}`,h=new AbortController,k=setTimeout(()=>h.abort(),this.timeout);try{if(r==="1"){let p=new URLSearchParams({fields1:"f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13",fields2:"f51,f52,f53,f54,f55,f56,f57,f58",ut:"7eea3edcaed734bea9cbfc24409ed989",ndays:"5",iscr:"0",secid:d}),c=await fetch(`${X}?${p.toString()}`,{signal:h.signal});if(!c.ok)throw new Error(`HTTP error! status: ${c.status}`);let f=(await c.json())?.data?.trends;if(!Array.isArray(f)||f.length===0)return[];let y=o.replace("T"," ").slice(0,16),b=i.replace("T"," ").slice(0,16);return f.map(w=>{let[P,T,v,Q,S,F,j,q]=w.split(",");return{time:P,open:l(T),close:l(v),high:l(Q),low:l(S),volume:l(F),amount:l(j),avgPrice:l(q)}}).filter(w=>w.time>=y&&w.time<=b)}else{let p={"":"0",qfq:"1",hfq:"2"},c=new URLSearchParams({fields1:"f1,f2,f3,f4,f5,f6",fields2:"f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61",ut:"7eea3edcaed734bea9cbfc24409ed989",klt:r,fqt:p[t],secid:d,beg:"0",end:"20500000"}),g=await fetch(`${M}?${c.toString()}`,{signal:h.signal});if(!g.ok)throw new Error(`HTTP error! status: ${g.status}`);let y=(await g.json())?.data?.klines;if(!Array.isArray(y)||y.length===0)return[];let b=o.replace("T"," ").slice(0,16),w=i.replace("T"," ").slice(0,16);return y.map(P=>{let[T,v,Q,S,F,j,q,C,R,$,O]=P.split(",");return{time:T,open:l(v),close:l(Q),high:l(S),low:l(F),changePercent:l(R),change:l($),volume:l(j),amount:l(q),amplitude:l(C),turnoverRate:l(O)}}).filter(P=>P.time>=b&&P.time<=w)}}finally{clearTimeout(k)}}},K=A;0&&(module.exports={StockSDK});
|
package/dist/index.d.cts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
function L(i){return new TextDecoder("gbk").decode(i)}function r(i){if(!i||i==="")return 0;let e=parseFloat(i);return Number.isNaN(e)?0:e}function u(i){if(!i||i==="")return null;let e=parseFloat(i);return Number.isNaN(e)?null:e}function U(i){let e=i.split(";").map(s=>s.trim()).filter(Boolean),n=[];for(let s of e){let t=s.indexOf("=");if(t<0)continue;let o=s.slice(0,t).trim();o.startsWith("v_")&&(o=o.slice(2));let a=s.slice(t+1).trim();a.startsWith('"')&&a.endsWith('"')&&(a=a.slice(1,-1));let
|
|
1
|
+
function L(i){return new TextDecoder("gbk").decode(i)}function r(i){if(!i||i==="")return 0;let e=parseFloat(i);return Number.isNaN(e)?0:e}function u(i){if(!i||i==="")return null;let e=parseFloat(i);return Number.isNaN(e)?null:e}function U(i){let e=i.split(";").map(s=>s.trim()).filter(Boolean),n=[];for(let s of e){let t=s.indexOf("=");if(t<0)continue;let o=s.slice(0,t).trim();o.startsWith("v_")&&(o=o.slice(2));let a=s.slice(t+1).trim();a.startsWith('"')&&a.endsWith('"')&&(a=a.slice(1,-1));let m=a.split("~");n.push({key:o,fields:m})}return n}function N(i,e){let n=[];for(let s=0;s<i.length;s+=e)n.push(i.slice(s,s+e));return n}async function x(i,e){let n=[],s=[];for(let t of i){let o=Promise.resolve().then(()=>t()).then(a=>{n.push(a)});if(s.push(o),s.length>=e){await Promise.race(s);for(let a=s.length-1;a>=0;a--)await Promise.race([s[a].then(()=>"fulfilled"),Promise.resolve("pending")])==="fulfilled"&&s.splice(a,1)}}return await Promise.all(s),n}var K="https://qt.gtimg.cn",O="https://web.ifzq.gtimg.cn/appstock/app/minute/query",H="https://assets.linkdiary.cn/shares/ashare-code.json",I="https://push2his.eastmoney.com/api/qt/stock/kline/get",E="https://push2his.eastmoney.com/api/qt/stock/trends2/get";function M(i){return i.startsWith("sh")?"1":i.startsWith("sz")||i.startsWith("bj")?"0":i.startsWith("6")?"1":"0"}function l(i){if(!i||i===""||i==="-")return null;let e=parseFloat(i);return Number.isNaN(e)?null:e}var A=class{constructor(e={}){this.baseUrl=e.baseUrl??K,this.timeout=e.timeout??1e4}async request(e){let n=`${this.baseUrl}/?q=${encodeURIComponent(e)}`,s=new AbortController,t=setTimeout(()=>s.abort(),this.timeout);try{let o=await fetch(n,{signal:s.signal});if(!o.ok)throw new Error(`HTTP error! status: ${o.status}`);let a=await o.arrayBuffer(),m=L(a);return U(m)}finally{clearTimeout(t)}}async getFullQuotes(e){return!e||e.length===0?[]:(await this.request(e.join(","))).filter(s=>s.fields&&s.fields.length>0&&s.fields[0]!=="").map(s=>this.parseFullQuote(s.fields))}parseFullQuote(e){let n=[];for(let t=0;t<5;t++)n.push({price:r(e[9+t*2]),volume:r(e[10+t*2])});let s=[];for(let t=0;t<5;t++)s.push({price:r(e[19+t*2]),volume:r(e[20+t*2])});return{marketId:e[0]??"",name:e[1]??"",code:e[2]??"",price:r(e[3]),prevClose:r(e[4]),open:r(e[5]),volume:r(e[6]),outerVolume:r(e[7]),innerVolume:r(e[8]),bid:n,ask:s,time:e[30]??"",change:r(e[31]),changePercent:r(e[32]),high:r(e[33]),low:r(e[34]),volume2:r(e[36]),amount:r(e[37]),turnoverRate:u(e[38]),pe:u(e[39]),amplitude:u(e[43]),circulatingMarketCap:u(e[44]),totalMarketCap:u(e[45]),pb:u(e[46]),limitUp:u(e[47]),limitDown:u(e[48]),volumeRatio:u(e[49]),avgPrice:u(e[51]),peStatic:u(e[52]),peDynamic:u(e[53]),high52w:u(e[67]),low52w:u(e[68]),circulatingShares:u(e[72]),totalShares:u(e[73]),raw:e}}async getSimpleQuotes(e){if(!e||e.length===0)return[];let n=e.map(t=>`s_${t}`);return(await this.request(n.join(","))).filter(t=>t.fields&&t.fields.length>0&&t.fields[0]!=="").map(t=>this.parseSimpleQuote(t.fields))}parseSimpleQuote(e){return{marketId:e[0]??"",name:e[1]??"",code:e[2]??"",price:r(e[3]),change:r(e[4]),changePercent:r(e[5]),volume:r(e[6]),amount:r(e[7]),marketCap:u(e[9]),marketType:e[10]??"",raw:e}}async getFundFlow(e){if(!e||e.length===0)return[];let n=e.map(t=>`ff_${t}`);return(await this.request(n.join(","))).filter(t=>t.fields&&t.fields.length>0&&t.fields[0]!=="").map(t=>this.parseFundFlow(t.fields))}parseFundFlow(e){return{code:e[0]??"",mainInflow:r(e[1]),mainOutflow:r(e[2]),mainNet:r(e[3]),mainNetRatio:r(e[4]),retailInflow:r(e[5]),retailOutflow:r(e[6]),retailNet:r(e[7]),retailNetRatio:r(e[8]),totalFlow:r(e[9]),name:e[12]??"",date:e[13]??"",raw:e}}async getPanelLargeOrder(e){if(!e||e.length===0)return[];let n=e.map(t=>`s_pk${t}`);return(await this.request(n.join(","))).filter(t=>t.fields&&t.fields.length>0&&t.fields[0]!=="").map(t=>this.parsePanelLargeOrder(t.fields))}parsePanelLargeOrder(e){return{buyLargeRatio:r(e[0]),buySmallRatio:r(e[1]),sellLargeRatio:r(e[2]),sellSmallRatio:r(e[3]),raw:e}}async getHKQuotes(e){if(!e||e.length===0)return[];let n=e.map(t=>`r_hk${t}`);return(await this.request(n.join(","))).filter(t=>t.fields&&t.fields.length>0&&t.fields[0]!=="").map(t=>this.parseHKQuote(t.fields))}parseHKQuote(e){return{marketId:e[0]??"",name:e[1]??"",code:e[2]??"",price:r(e[3]),prevClose:r(e[4]),open:r(e[5]),volume:r(e[6]),time:e[30]??"",change:r(e[31]),changePercent:r(e[32]),high:r(e[33]),low:r(e[34]),amount:r(e[36]),lotSize:u(e[40]),circulatingMarketCap:u(e[46]),totalMarketCap:u(e[47]),currency:e[e.length-3]??"",raw:e}}async getUSQuotes(e){if(!e||e.length===0)return[];let n=e.map(t=>`s_us${t}`);return(await this.request(n.join(","))).filter(t=>t.fields&&t.fields.length>0&&t.fields[0]!=="").map(t=>this.parseUSQuote(t.fields))}parseUSQuote(e){return{marketId:e[0]??"",name:e[1]??"",code:e[2]??"",price:r(e[3]),change:r(e[4]),changePercent:r(e[5]),volume:r(e[6]),amount:r(e[7]),marketCap:u(e[8]),raw:e}}async getFundQuotes(e){if(!e||e.length===0)return[];let n=e.map(t=>`jj${t}`);return(await this.request(n.join(","))).filter(t=>t.fields&&t.fields.length>0&&t.fields[0]!=="").map(t=>this.parseFundQuote(t.fields))}parseFundQuote(e){return{code:e[0]??"",name:e[1]??"",nav:r(e[5]),accNav:r(e[6]),change:r(e[7]),navDate:e[8]??"",raw:e}}async batchRaw(e){return this.request(e)}async getTodayTimeline(e){let n=new AbortController,s=setTimeout(()=>n.abort(),this.timeout);try{let t=await fetch(`${O}?code=${e}`,{signal:n.signal});if(!t.ok)throw new Error(`HTTP error! status: ${t.status}`);let o=await t.json();if(o.code!==0)throw new Error(o.msg||"API error");let a=o.data?.[e];if(!a)return{code:e,date:"",data:[]};let m=a.data?.data||[],d=a.data?.date||"",h=!1;if(m.length>0){let p=m[0].split(" "),c=parseFloat(p[1])||0,g=parseInt(p[2],10)||0,f=parseFloat(p[3])||0;g>0&&c>0&&f/g>c*50&&(h=!0)}let k=m.map(p=>{let c=p.split(" "),g=c[0],f=`${g.slice(0,2)}:${g.slice(2,4)}`,y=parseInt(c[2],10)||0,b=parseFloat(c[3])||0,w=h?y*100:y,P=w>0?b/w:0;return{time:f,price:parseFloat(c[1])||0,volume:w,amount:b,avgPrice:Math.round(P*100)/100}});return{code:e,date:d,data:k}}finally{clearTimeout(s)}}async getAShareCodeList(e=!0){let n=new AbortController,s=setTimeout(()=>n.abort(),this.timeout);try{let t=await fetch(H,{signal:n.signal});if(!t.ok)throw new Error(`HTTP error! status: ${t.status}`);let o=await t.json();return e?o:o.map(a=>a.replace(/^(sh|sz|bj)/,""))}finally{clearTimeout(s)}}async getAllAShareQuotes(e={}){let{batchSize:n=500,concurrency:s=7,onProgress:t}=e,o=await this.getAShareCodeList(),a=N(o,n),m=a.length,d=0,h=a.map(p=>async()=>{let c=await this.getFullQuotes(p);return d++,t&&t(d,m),c});return(await x(h,s)).flat()}async getAllQuotesByCodes(e,n={}){let{batchSize:s=500,concurrency:t=7,onProgress:o}=n,a=N(e,s),m=a.length,d=0,h=a.map(p=>async()=>{let c=await this.getFullQuotes(p);return d++,o&&o(d,m),c});return(await x(h,t)).flat()}async getHistoryKline(e,n={}){let{period:s="daily",adjust:t="hfq",startDate:o="19700101",endDate:a="20500101"}=n,m=e.replace(/^(sh|sz|bj)/,""),d={daily:"101",weekly:"102",monthly:"103"},h={"":"0",qfq:"1",hfq:"2"},k=`${M(m)}.${m}`,p=new URLSearchParams({fields1:"f1,f2,f3,f4,f5,f6",fields2:"f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61,f116",ut:"7eea3edcaed734bea9cbfc24409ed989",klt:d[s],fqt:h[t],secid:k,beg:o,end:a}),c=new AbortController,g=setTimeout(()=>c.abort(),this.timeout);try{let f=await fetch(`${I}?${p.toString()}`,{signal:c.signal});if(!f.ok)throw new Error(`HTTP error! status: ${f.status}`);let b=(await f.json())?.data?.klines;return!Array.isArray(b)||b.length===0?[]:b.map(w=>{let[P,T,v,Q,S,F,j,q,C,R,$]=w.split(",");return{date:P,code:m,open:l(T),close:l(v),high:l(Q),low:l(S),volume:l(F),amount:l(j),amplitude:l(q),changePercent:l(C),change:l(R),turnoverRate:l($)}})}finally{clearTimeout(g)}}async getMinuteKline(e,n={}){let{period:s="1",adjust:t="hfq",startDate:o="1979-09-01 09:32:00",endDate:a="2222-01-01 09:32:00"}=n,m=e.replace(/^(sh|sz|bj)/,""),d=`${M(m)}.${m}`,h=new AbortController,k=setTimeout(()=>h.abort(),this.timeout);try{if(s==="1"){let p=new URLSearchParams({fields1:"f1,f2,f3,f4,f5,f6,f7,f8,f9,f10,f11,f12,f13",fields2:"f51,f52,f53,f54,f55,f56,f57,f58",ut:"7eea3edcaed734bea9cbfc24409ed989",ndays:"5",iscr:"0",secid:d}),c=await fetch(`${E}?${p.toString()}`,{signal:h.signal});if(!c.ok)throw new Error(`HTTP error! status: ${c.status}`);let f=(await c.json())?.data?.trends;if(!Array.isArray(f)||f.length===0)return[];let y=o.replace("T"," ").slice(0,16),b=a.replace("T"," ").slice(0,16);return f.map(w=>{let[P,T,v,Q,S,F,j,q]=w.split(",");return{time:P,open:l(T),close:l(v),high:l(Q),low:l(S),volume:l(F),amount:l(j),avgPrice:l(q)}}).filter(w=>w.time>=y&&w.time<=b)}else{let p={"":"0",qfq:"1",hfq:"2"},c=new URLSearchParams({fields1:"f1,f2,f3,f4,f5,f6",fields2:"f51,f52,f53,f54,f55,f56,f57,f58,f59,f60,f61",ut:"7eea3edcaed734bea9cbfc24409ed989",klt:s,fqt:p[t],secid:d,beg:"0",end:"20500000"}),g=await fetch(`${I}?${c.toString()}`,{signal:h.signal});if(!g.ok)throw new Error(`HTTP error! status: ${g.status}`);let y=(await g.json())?.data?.klines;if(!Array.isArray(y)||y.length===0)return[];let b=o.replace("T"," ").slice(0,16),w=a.replace("T"," ").slice(0,16);return y.map(P=>{let[T,v,Q,S,F,j,q,C,R,$,D]=P.split(",");return{time:T,open:l(v),close:l(Q),high:l(S),low:l(F),changePercent:l(R),change:l($),volume:l(j),amount:l(q),amplitude:l(C),turnoverRate:l(D)}}).filter(P=>P.time>=b&&P.time<=w)}}finally{clearTimeout(k)}}},_=A;export{A as StockSDK,_ as default};
|