@watsonserve/stock-loader 0.0.1 → 0.0.2-alpha.0
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/build.mjs +28 -0
- package/package.json +9 -7
- package/src/close-time.ts +123 -0
- package/src/dividend-loader.ts +196 -0
- package/src/helper.ts +36 -0
- package/src/history-loader.ts +71 -0
- package/src/index.ts +73 -0
- package/src/price-loader.ts +125 -0
- package/src/web-request.ts +131 -0
- package/tsconfig.json +22 -0
- package/close-time.js +0 -110
- package/dividend-loader.js +0 -148
- package/helper.js +0 -23
- package/history-loader.js +0 -65
- package/index.js +0 -8
- package/price-loader.js +0 -122
- package/types/close-time.d.ts +0 -11
- package/types/dividend-loader.d.ts +0 -14
- package/types/helper.d.ts +0 -15
- package/types/history-loader.d.ts +0 -17
- package/types/index.d.ts +0 -6
- package/types/price-loader.d.ts +0 -16
- package/types/web-request.d.ts +0 -21
- package/web-request.js +0 -115
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { EnMarket } from '@watsonserve/stock-base';
|
|
2
|
-
import WebRequest from './web-request.js';
|
|
3
|
-
export default class HistoryLoader extends WebRequest {
|
|
4
|
-
private __getHKOrUSAHistory;
|
|
5
|
-
private __getSGXHistory;
|
|
6
|
-
loadHistory(fullNc: string): Promise<{
|
|
7
|
-
market: EnMarket;
|
|
8
|
-
nc: string;
|
|
9
|
-
n: string;
|
|
10
|
-
o: number;
|
|
11
|
-
c: any;
|
|
12
|
-
h: number;
|
|
13
|
-
l: number;
|
|
14
|
-
v: any;
|
|
15
|
-
stamp: number;
|
|
16
|
-
}[]>;
|
|
17
|
-
}
|
package/types/index.d.ts
DELETED
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import WebRequest from './web-request.js';
|
|
2
|
-
import { DividendLoader } from './dividend-loader.js';
|
|
3
|
-
export { type IDiv, ttm, sleep, splitFullNc } from './helper.js';
|
|
4
|
-
export declare class StockLoader extends DividendLoader {
|
|
5
|
-
static getInstance(debug?: boolean): Promise<WebRequest>;
|
|
6
|
-
}
|
package/types/price-loader.d.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import { EnMarket, IStock } from '@watsonserve/stock-base';
|
|
2
|
-
import HistoryLoader from './history-loader.js';
|
|
3
|
-
export default class PriceLoader extends HistoryLoader {
|
|
4
|
-
private __loadFx;
|
|
5
|
-
loadFx(): Promise<{
|
|
6
|
-
stamp: number;
|
|
7
|
-
}>;
|
|
8
|
-
protected sgx(): Promise<IStock[]>;
|
|
9
|
-
protected hkex(): Promise<IStock[]>;
|
|
10
|
-
private __sp500;
|
|
11
|
-
protected sp500(): Promise<IStock[]>;
|
|
12
|
-
loadPrice(market: EnMarket): Promise<{
|
|
13
|
-
sts: IStock[];
|
|
14
|
-
stamp: number;
|
|
15
|
-
}>;
|
|
16
|
-
}
|
package/types/web-request.d.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { type Page } from 'playwright';
|
|
2
|
-
export default class WebRequest {
|
|
3
|
-
private static HKEX_TOKEN;
|
|
4
|
-
private static browser?;
|
|
5
|
-
private static context?;
|
|
6
|
-
private static pageCnt;
|
|
7
|
-
private static __promise?;
|
|
8
|
-
protected page?: Page;
|
|
9
|
-
protected isDebug: boolean;
|
|
10
|
-
private static __getInstance;
|
|
11
|
-
protected static getInstance(debug: boolean | undefined, instance: WebRequest): Promise<WebRequest>;
|
|
12
|
-
protected constructor();
|
|
13
|
-
private init;
|
|
14
|
-
private static destroy;
|
|
15
|
-
destroy(): Promise<void>;
|
|
16
|
-
protected fetch(url: string, method?: string, params?: Record<string, any>, headers?: Record<string, any>): Promise<any>;
|
|
17
|
-
protected get(url: string, params?: Record<string, any>, headers?: Record<string, any>): Promise<any>;
|
|
18
|
-
protected goto(pageUrl: string): Promise<import("playwright").Response | null>;
|
|
19
|
-
protected read<T>(key: string): Promise<T>;
|
|
20
|
-
protected _loadHkexToken(): Promise<string>;
|
|
21
|
-
}
|
package/web-request.js
DELETED
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
import { chromium } from 'playwright';
|
|
2
|
-
import { A_DAY_MS } from './close-time.js';
|
|
3
|
-
export default class WebRequest {
|
|
4
|
-
static HKEX_TOKEN = { token: '', t: 0 };
|
|
5
|
-
static browser;
|
|
6
|
-
static context;
|
|
7
|
-
static pageCnt = 0;
|
|
8
|
-
static __promise;
|
|
9
|
-
page;
|
|
10
|
-
isDebug = false;
|
|
11
|
-
static async __getInstance(debug = false) {
|
|
12
|
-
if (WebRequest.context)
|
|
13
|
-
return;
|
|
14
|
-
// 1. 启动 Chromium,禁用 web security(解除 CORS)
|
|
15
|
-
WebRequest.browser = await chromium.launch({
|
|
16
|
-
headless: !debug,
|
|
17
|
-
channel: 'msedge',
|
|
18
|
-
args: [
|
|
19
|
-
'--disable-web-security',
|
|
20
|
-
'--disable-features=IsolateOrigins,site-per-process',
|
|
21
|
-
'--no-sandbox',
|
|
22
|
-
'--disable-setuid-sandbox'
|
|
23
|
-
]
|
|
24
|
-
});
|
|
25
|
-
WebRequest.context = await WebRequest.browser.newContext({});
|
|
26
|
-
}
|
|
27
|
-
static async getInstance(debug = false, instance) {
|
|
28
|
-
if (!WebRequest.__promise)
|
|
29
|
-
WebRequest.__promise = WebRequest.__getInstance(debug);
|
|
30
|
-
await WebRequest.__promise;
|
|
31
|
-
await instance.init(debug);
|
|
32
|
-
WebRequest.pageCnt++;
|
|
33
|
-
return instance;
|
|
34
|
-
}
|
|
35
|
-
constructor() { }
|
|
36
|
-
async init(isDebug) {
|
|
37
|
-
this.isDebug = isDebug;
|
|
38
|
-
this.page = await WebRequest.context.newPage();
|
|
39
|
-
await this.page.goto('about:blank');
|
|
40
|
-
}
|
|
41
|
-
static async destroy() {
|
|
42
|
-
WebRequest.pageCnt--;
|
|
43
|
-
if (0 < WebRequest.pageCnt)
|
|
44
|
-
return;
|
|
45
|
-
await WebRequest.context?.close();
|
|
46
|
-
await WebRequest.browser?.close();
|
|
47
|
-
WebRequest.context = undefined;
|
|
48
|
-
WebRequest.browser = undefined;
|
|
49
|
-
WebRequest.pageCnt = 0;
|
|
50
|
-
WebRequest.__promise = undefined;
|
|
51
|
-
}
|
|
52
|
-
async destroy() {
|
|
53
|
-
await this.page?.close();
|
|
54
|
-
return WebRequest.destroy();
|
|
55
|
-
}
|
|
56
|
-
fetch(url, method = 'GET', params, headers) {
|
|
57
|
-
method = method.toUpperCase();
|
|
58
|
-
let data = '';
|
|
59
|
-
if (params) {
|
|
60
|
-
if (['HEAD', 'GET'].includes(method)) {
|
|
61
|
-
const uri = new URL(url);
|
|
62
|
-
const urlParams = Object.fromEntries(uri.searchParams);
|
|
63
|
-
uri.search = new URLSearchParams(Object.assign(urlParams, params)).toString();
|
|
64
|
-
url = uri.toString();
|
|
65
|
-
}
|
|
66
|
-
else {
|
|
67
|
-
const ct = (headers?.['Content-Type'] || '').split(';')[0];
|
|
68
|
-
switch (ct) {
|
|
69
|
-
case 'application/json':
|
|
70
|
-
data = JSON.stringify(params);
|
|
71
|
-
break;
|
|
72
|
-
default:
|
|
73
|
-
data = new URLSearchParams(params).toString();
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
return this.page.evaluate(async (conf) => {
|
|
78
|
-
const resp = await fetch(conf.url, {
|
|
79
|
-
method: conf.method,
|
|
80
|
-
credentials: 'include', // 如果需要 Cookie
|
|
81
|
-
headers: conf.headers,
|
|
82
|
-
body: conf.data || undefined,
|
|
83
|
-
});
|
|
84
|
-
if (!resp.ok)
|
|
85
|
-
throw new Error(`HTTP ${resp.status}`);
|
|
86
|
-
const ct = resp.headers.get('Content-Type')?.split(';')[0] || '';
|
|
87
|
-
if ('application/json' === ct)
|
|
88
|
-
return resp.json();
|
|
89
|
-
if (ct.startsWith('text/'))
|
|
90
|
-
return resp.text();
|
|
91
|
-
return resp.arrayBuffer();
|
|
92
|
-
}, { method, url, headers, data });
|
|
93
|
-
}
|
|
94
|
-
get(url, params, headers) {
|
|
95
|
-
return this.fetch(url, 'GET', params, headers);
|
|
96
|
-
}
|
|
97
|
-
goto(pageUrl) {
|
|
98
|
-
return this.page.goto(pageUrl);
|
|
99
|
-
}
|
|
100
|
-
read(key) {
|
|
101
|
-
return this.page.evaluate(async (conf) => {
|
|
102
|
-
return window[conf.key];
|
|
103
|
-
}, { key });
|
|
104
|
-
}
|
|
105
|
-
async _loadHkexToken() {
|
|
106
|
-
const expiry = Date.now() - A_DAY_MS;
|
|
107
|
-
if (WebRequest.HKEX_TOKEN?.t > expiry)
|
|
108
|
-
return WebRequest.HKEX_TOKEN.token;
|
|
109
|
-
const doc = await this.get('https://www.hkex.com.hk/Market-Data/Securities-Prices/Equities?sc_lang=zh-HK');
|
|
110
|
-
const token = doc.split('//return "Base64-AES-Encrypted-Token";')[1].split('";')[0].split('"')[1];
|
|
111
|
-
const decodedToken = decodeURIComponent(token);
|
|
112
|
-
WebRequest.HKEX_TOKEN = { token: decodedToken, t: Date.now() };
|
|
113
|
-
return decodedToken;
|
|
114
|
-
}
|
|
115
|
-
}
|