diff --git a/.gitignore b/.gitignore
index 0b60dfa..09193d1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,3 +3,4 @@ dist
node_modules
.vscode-test/
*.vsix
+pnpm-lock.yaml
diff --git a/.prettierrc b/.prettierrc
index 854ffbe..a044392 100644
--- a/.prettierrc
+++ b/.prettierrc
@@ -1,5 +1,6 @@
{
"useTabs": true,
"singleQuote": true,
- "trailingComma": "all"
+ "trailingComma": "all",
+ "endOfLine": "auto"
}
diff --git a/README.md b/README.md
index ba759f3..645b974 100644
--- a/README.md
+++ b/README.md
@@ -2,19 +2,26 @@
VScode 插件 | A 股 | 港股 | 实时股票数据 | 状态栏实时更新
-`Stock Bar`会在开盘期间自动刷新股票数据,并在VScode底部状态栏显示股票基本数据,让你在使用VScode期间能随时关注到你的股票。
+`Stock Bar`会在开盘期间自动刷新股票数据,并在 VScode 底部状态栏显示股票基本数据,让你在使用 VScode 期间能随时关注到你的股票。
为了隐秘性,`Stock Bar`默认只会显示股价、百分点这样的纯数字,当你将鼠标移上去就可以查看详情。当然为了区分,也可以自定义显示股票的名称(建议使用英文字母,别问我为什么)
![image](https://raw.githubusercontent.com/Chef5/stock-bar/main/stock-bar-plugin.png)
-插件已开源,开源地址:[Github](https://github.com/Chef5/stock-bar),欢迎点星星⭐️、提issue或者pr
+插件已开源,开源地址:[Github](https://github.com/Chef5/stock-bar),欢迎点星星 ⭐️、提 issue 或者 pr
+
+## 启动
+
+(ctrl + shift + P) 后运行命令:
+
+- stock watch start 开始显示
+- stock watch stop 关闭显示
## 插件配置
修改用户配置,添加你所需要监控的股票代码
-``` js
+```js
// 股票:这是一个数组,你可以直接添加股票代码字符串,也可以添加对象,对象格式如下:
// {
// code: string, // 股票代码:需要添加股市前缀,前缀参考文档下方:前缀说明
@@ -29,6 +36,22 @@ VScode 插件 | A 股 | 港股 | 实时股票数据 | 状态栏实时更新
}
],
+// 期货: 数组,可以添加期货代码
+// {
+// code: string, //期货代码, 比如 sa9999, sa2409
+// alias: string, // 期货别名,这个可以不填,会自动根据代码获取
+// hold_price: number, //持仓价格,即多空单的价格
+// hold_number: number //持仓, 正数代表持有多单,负数代表持有空单,当配置了持仓价格和持仓后,
+// 会显示持仓盈亏,否则显示当日价格涨跌幅
+// }
+"stock-bar.futures": [
+ {
+ "code": "sa9999",
+ "hold_price": 2500,
+ "hold_number": -1
+ }
+],
+
// 更新数据时间间隔,单位:毫秒
"stock-bar.updateInterval": 10000
@@ -41,10 +64,10 @@ VScode 插件 | A 股 | 港股 | 实时股票数据 | 状态栏实时更新
## 前缀说明
-- sh:沪市,不加前缀的情况下,6开头的代码默认加上sh(上证指数:sh000001)
-- sz:深市,不加前缀的情况下,除6开头的代码外,默认加上sz
+- sh:沪市,不加前缀的情况下,6 开头的代码默认加上 sh(上证指数:sh000001)
+- sz:深市,不加前缀的情况下,除 6 开头的代码外,默认加上 sz
- hk:港股,如:阿里巴巴港股 hk09988
-- US_:美股,如:苹果股票 US_AAPL
+- US\_:美股,如:苹果股票 US_AAPL
- hkHSC:工商指数(港股指数)
- hkHSCEI:恒生中国企业指数(港股指数)
- hkHSI:恒生指数(港股指数)
@@ -55,7 +78,7 @@ VScode 插件 | A 股 | 港股 | 实时股票数据 | 状态栏实时更新
- hkGEM:标普香港创业板指(港股指数)
- US_DOWJONES:道琼斯指数(美股指数)
- US_NASDAQ:纳斯达克(美股指数)
-- US_SP500:标普500(美股指数)
+- US_SP500:标普 500(美股指数)
## 更新日志
@@ -63,7 +86,7 @@ VScode 插件 | A 股 | 港股 | 实时股票数据 | 状态栏实时更新
## 贡献者
-感谢这些可爱的贡献者参与开发和维护Stock Bar,让`Stock Bar`更加完美!
+感谢这些可爱的贡献者参与开发和维护 Stock Bar,让`Stock Bar`更加完美!
@@ -80,7 +103,9 @@ VScode 插件 | A 股 | 港股 | 实时股票数据 | 状态栏实时更新
## 源
-> 插件源:`Stock Bar`最初Fork自[stock-watch](https://github.com/TDGarden/stock-watch),现在已对其进行了重大重构。
+> 插件源:`Stock Bar`最初 Fork 自[stock-watch](https://github.com/TDGarden/stock-watch),现在已对其进行了重大重构。
> 股票数据来源:
-> - 新浪
+>
+> - 新浪
+> - 同花顺
diff --git a/package-lock.json b/package-lock.json
index 320c68f..e9a33e3 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "stock-bar",
- "version": "1.0.4",
+ "version": "1.0.6",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "stock-bar",
- "version": "1.0.4",
+ "version": "1.0.6",
"license": "MIT",
"dependencies": {
"axios": "^0.27.2"
diff --git a/package.json b/package.json
index 9e64770..dfb239f 100644
--- a/package.json
+++ b/package.json
@@ -17,7 +17,7 @@
"Other"
],
"activationEvents": [
- "*"
+ "*"
],
"main": "./dist/extension",
"contributes": {
@@ -34,6 +34,17 @@
],
"description": "股票代码数组,配置需要监控的股票代码,具体配置规则请查看插件详情页"
},
+ "stock-bar.futures": {
+ "type": "array",
+ "default": [
+ {
+ "code": "sa9999",
+ "hold_price": 2300,
+ "hold_number": -1
+ }
+ ],
+ "description": "商品期货数组,配置需要监控的商品期货,具体配置规则请查看插件详情页"
+ },
"stock-bar.updateInterval": {
"type": "number",
"default": 10000,
@@ -50,7 +61,17 @@
"description": "股票跌的颜色,默认跟随系统"
}
}
- }
+ },
+ "commands": [
+ {
+ "command": "stockbar.start",
+ "title": "stock watch start"
+ },
+ {
+ "command": "stockbar.stop",
+ "title": "stock watch stop"
+ }
+ ]
},
"scripts": {
"vscode:prepublish": "npm run package",
diff --git a/src/configuration.ts b/src/configuration.ts
index 5811023..d273528 100644
--- a/src/configuration.ts
+++ b/src/configuration.ts
@@ -1,5 +1,5 @@
import * as vscode from 'vscode';
-import { StockOptions } from 'stock-bar';
+import { StockOptions, FutureOptions } from 'stock-bar';
export default class Configuration {
/**
@@ -24,6 +24,16 @@ export default class Configuration {
return stocks as StockOptions;
}
+ static getFutures() {
+ const futures = Configuration.stockBarConfig().get('futures');
+ if (!futures) {
+ return [];
+ }
+ const items = futures as FutureOptions;
+ items.forEach((item) => (item.code = item.code.toUpperCase()));
+ return items;
+ }
+
static getUpdateInterval() {
const updateInterval = Configuration.stockBarConfig().get('updateInterval');
return typeof updateInterval === 'number' ? updateInterval : 10000;
diff --git a/src/extension.ts b/src/extension.ts
index 2faa008..fbc9641 100644
--- a/src/extension.ts
+++ b/src/extension.ts
@@ -2,9 +2,10 @@ import * as vscode from 'vscode';
import logger from './logger';
import Configuration from './configuration';
import { sinaStockProvider } from './provider';
-import { render } from './render';
-import timer from './timer';
+import { render, renderFutures, stopAllRender } from './render';
import Stock from './stock';
+import FutureHandler from './futures';
+import { clearInterval } from 'timers';
function loadChoiceStocks() {
return Configuration.getStocks().map((v) => {
@@ -20,45 +21,75 @@ function loadChoiceStocks() {
});
}
-export function activate(context: vscode.ExtensionContext) {
- let stocks = loadChoiceStocks();
+let timer = null;
+let stocks: Stock[];
- context.subscriptions.push(
- vscode.workspace.onDidChangeConfiguration(() => {
- stocks = loadChoiceStocks();
- }),
- );
+function restart() {
+ //console.log('restart');
+ const interval = Configuration.getUpdateInterval();
+ if (timer) {
+ clearInterval(timer);
+ timer = null;
+ }
+ stocks = loadChoiceStocks();
+ futureHandler.updateConfig(Configuration.getFutures());
- const task: () => any = async () => {
- try {
- // 从云端获取最新状态
- logger.debug('call fetchData');
- const data = await sinaStockProvider.fetch(stocks.map((v) => v.code));
- // 更新本地的数据
- for (const origin of data) {
- const stock = stocks.find((v) => v.code === origin.code);
- if (!stock) {
- continue;
- }
- stock.update(origin);
+ timer = setInterval(ticker, interval);
+ ticker();
+}
+
+const futureHandler = new FutureHandler();
+
+async function ticker() {
+ try {
+ // 从云端获取最新状态
+ logger.debug('call fetchData');
+ const [data, _] = await Promise.all([
+ sinaStockProvider.fetch(stocks.map((v) => v.code)),
+ futureHandler.updateData(),
+ ]);
+ // 更新本地的数据
+ for (const origin of data) {
+ const stock = stocks.find((v) => v.code === origin.code);
+ if (!stock) {
+ continue;
}
- // 渲染内容
- logger.debug('render');
- render(stocks);
- } catch (e) {
- logger.error('%O', e);
+ stock.update(origin);
}
+ // 渲染内容
+ logger.debug('render');
+ render(stocks);
+ renderFutures(futureHandler.futures);
+ } catch (e) {
+ logger.error('%O', e);
+ }
+}
- // 阻塞等待下一个循环
- logger.debug('timer await');
- await timer.await();
+function stop() {
+ //console.log('stop');
+ if (timer) {
+ clearInterval(timer);
+ timer = null;
+ }
+ stopAllRender();
+}
+
+export function activate(context: vscode.ExtensionContext) {
+ //console.log('activivate');
+ stocks = loadChoiceStocks();
- // 继续循环
- return task();
- };
+ const startCmd = vscode.commands.registerCommand('stockbar.start', restart);
+ const stopCmd = vscode.commands.registerCommand('stockbar.stop', stop);
- // 丢进宏任务队列
- setTimeout(task);
+ context.subscriptions.push(
+ vscode.workspace.onDidChangeConfiguration(() => {
+ if (timer) {
+ restart();
+ }
+ }),
+ );
+ context.subscriptions.push(startCmd);
+ context.subscriptions.push(stopCmd);
}
export function deactivate() {
diff --git a/src/futures.ts b/src/futures.ts
new file mode 100644
index 0000000..6592c65
--- /dev/null
+++ b/src/futures.ts
@@ -0,0 +1,213 @@
+// eslint-disable-next-line @typescript-eslint/triple-slash-reference
+///
+
+import axios, { AxiosInstance } from 'axios';
+import { FutureOption } from 'stock-bar';
+import logger from './logger';
+
+class Provider {
+ instance: AxiosInstance;
+ constructor() {
+ this.instance = axios.create({
+ timeout: 8000,
+ });
+ }
+
+ async getBasicInfo(code: string) {
+ try {
+ const url = `https://fupage.10jqka.com.cn/futgwapi/api/f10/contract/v1/info?code=${code}`;
+ const results = await Promise.all([
+ this.instance.get(`https://fupage.10jqka.com.cn/futgwapi/api/f10/contract/v1/info?code=${code.toUpperCase()}`),
+ this.instance.get(`https://fupage.10jqka.com.cn/futgwapi/api/f10/contract/v1/info?code=${code.toLowerCase()}`)
+ ])
+ const data = results[0].data.data || results[1].data.data || {};
+ const name = data.name || '';
+ const tradeUnit = (data.trade_unit || '').trim();
+ let ratio = 0;
+ if (tradeUnit) {
+ const match = tradeUnit.match(/^\d*/);
+ if (match && match.length > 0) {
+ ratio = parseFloat(match[0]) || 0;
+ }
+ }
+ return {
+ code,
+ name,
+ ratio,
+ };
+ } catch (err: unknown) {
+ logger.error('getBasicInfo error %O', err);
+ return null;
+ }
+ }
+
+ async getLatestPrice(code: string) {
+ try {
+ const headers = {
+ Referer: 'https://goodsfu.10jqka.com.cn/',
+ 'Content-Type': 'application/json',
+ };
+ const url = `https://d.10jqka.com.cn/v6/time/qh_${code}/last.js`;
+ const ret = (await this.instance.get(url, { headers })).data;
+ const match = ret.match(/\(({.*})\)/);
+ if (!match) {
+ return null;
+ }
+
+ const js = JSON.parse(match[1]);
+ const keys = Object.keys(js);
+ if (keys.length <= 0) {
+ return null;
+ }
+ const data = js[keys[0]];
+ const pre_price = parseFloat(data['pre']);
+ const allLines = (data['data'] || '').split(';');
+ if (allLines.length <= 0) {
+ return null;
+ }
+ const lastLine = allLines[allLines.length - 1];
+ if (!lastLine) return null;
+ const lineArr = lastLine.split(',');
+ const current_price = parseFloat(lineArr[1]);
+ const name = data['name'] || '';
+ return {
+ name,
+ pre_price,
+ current_price,
+ };
+ } catch (err: unknown) {
+ logger.error('getLastestPrice error %O', err);
+ return null;
+ }
+ }
+}
+
+class ProviderSina extends Provider {
+ async getLatestPrice(code: string) {
+ try {
+ const headers = {
+ Referer: 'https://finance.sina.com.cn',
+ 'Content-Type': 'application/json',
+ };
+ const url = `https://hq.sinajs.cn?list=nf_${code}`;
+ let ret = (await this.instance.get(url, { headers, responseType:'arraybuffer'})).data;
+ ret = new TextDecoder('GBK').decode(ret);
+ const match = ret.match(/\"(.*)\"/);
+ if (!match) {
+ return null;
+ }
+ const arr = match[1].split(',');
+ if (arr.length <= 5) { return null; }
+ const name = arr[0];
+ const open = parseFloat(arr[2]);
+ const high = parseFloat(arr[3]);
+ const low = parseFloat(arr[4]);
+ const current_price = parseFloat(arr[8]);
+ const pre_price = parseFloat(arr[10]);
+ return {
+ name,
+ pre_price,
+ current_price,
+ };
+ } catch (err: unknown) {
+ logger.error('getLastestPrice error %O', err);
+ return null;
+ }
+ }
+}
+
+const provider = new ProviderSina();
+
+export class FutureData {
+ code: string;
+ name = '';
+ alias: string;
+ hold_price = 0;
+ hold_number = 0;
+ ratio = 0;
+ inited = false;
+ init_times = 0;
+ price: {
+ pre_price: number;
+ current_price: number;
+ } = null;
+
+ constructor(option: FutureOption) {
+ this.syncConfig(option);
+ }
+
+ syncConfig(option: FutureOption) {
+ this.code = option.code;
+ this.alias = option.alias || '';
+ this.hold_number = option.hold_number || 0;
+ this.hold_price = option.hold_price || 0;
+ }
+
+ async updateConfig() {
+ if (this.inited) {
+ return;
+ }
+ this.init_times++;
+ const info = await provider.getBasicInfo(this.code);
+ console.log('updateConfig', info);
+ if (info) {
+ this.inited = true;
+ if (!this.name) {
+ this.name = info.name;
+ }
+ this.ratio = info.ratio;
+ return;
+ }
+ if (this.init_times >= 3) {
+ this.inited = true;
+ return;
+ }
+ }
+
+ async updatePrice() {
+ const info = await provider.getLatestPrice(this.code);
+ if (info) {
+ this.price = info;
+ this.name = info.name;
+ }
+ }
+}
+
+export default class FutureHandler {
+ futures: FutureData[] = [];
+
+ updateConfig(options: FutureOption[]) {
+ //logger.debug('future updateConfig');
+ const newFutures = [];
+ for (const option of options) {
+ let future = this.futures.find((item) => item.code == option.code);
+ if (future == null) {
+ future = new FutureData(option);
+ } else {
+ future.syncConfig(option);
+ }
+ newFutures.push(future);
+ }
+ this.futures = newFutures;
+ }
+
+ async updateData() {
+ if (this.futures.length <= 0) {
+ return;
+ }
+ await Promise.all(this.futures.map((item) => item.updateConfig()));
+ await Promise.all(this.futures.map((item) => item.updatePrice()));
+ }
+}
+
+async function testGetBasicInfo() {
+ const data = await provider.getBasicInfo('cu2409');
+ console.log(data);
+}
+
+async function testGetPrice() {
+ const data = await provider.getLatestPrice('CU2409');
+ console.log(data);
+}
+
+testGetBasicInfo();
\ No newline at end of file
diff --git a/src/logger.js b/src/logger.js
new file mode 100644
index 0000000..5e7130d
--- /dev/null
+++ b/src/logger.js
@@ -0,0 +1,59 @@
+"use strict";
+var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
+ if (ar || !(i in from)) {
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
+ ar[i] = from[i];
+ }
+ }
+ return to.concat(ar || Array.prototype.slice.call(from));
+};
+exports.__esModule = true;
+var util_1 = require("util");
+var Logger = /** @class */ (function () {
+ function Logger() {
+ }
+ /**
+ * @private
+ */
+ Logger.prototype.prefix = function (loggerLevel) {
+ return (0, util_1.format)('[%s] [%s]', new Date().toLocaleString(), loggerLevel);
+ };
+ Logger.prototype.fatal = function (msg) {
+ var args = [];
+ for (var _i = 1; _i < arguments.length; _i++) {
+ args[_i - 1] = arguments[_i];
+ }
+ console.error(util_1.format.apply(void 0, __spreadArray(["".concat(this.prefix('fatal'), " ").concat(msg)], args, false)));
+ };
+ Logger.prototype.error = function (msg) {
+ var args = [];
+ for (var _i = 1; _i < arguments.length; _i++) {
+ args[_i - 1] = arguments[_i];
+ }
+ console.error(util_1.format.apply(void 0, __spreadArray(["".concat(this.prefix('error'), " ").concat(msg)], args, false)));
+ };
+ Logger.prototype.warn = function (msg) {
+ var args = [];
+ for (var _i = 1; _i < arguments.length; _i++) {
+ args[_i - 1] = arguments[_i];
+ }
+ console.warn(util_1.format.apply(void 0, __spreadArray(["".concat(this.prefix('warn'), " ").concat(msg)], args, false)));
+ };
+ Logger.prototype.info = function (msg) {
+ var args = [];
+ for (var _i = 1; _i < arguments.length; _i++) {
+ args[_i - 1] = arguments[_i];
+ }
+ console.log(util_1.format.apply(void 0, __spreadArray(["".concat(this.prefix('info'), " ").concat(msg)], args, false)));
+ };
+ Logger.prototype.debug = function (msg) {
+ var args = [];
+ for (var _i = 1; _i < arguments.length; _i++) {
+ args[_i - 1] = arguments[_i];
+ }
+ console.log(util_1.format.apply(void 0, __spreadArray(["".concat(this.prefix('debug'), " ").concat(msg)], args, false)));
+ };
+ return Logger;
+}());
+exports["default"] = new Logger();
diff --git a/src/render.ts b/src/render.ts
index 3c9eb9b..cb27d63 100644
--- a/src/render.ts
+++ b/src/render.ts
@@ -3,6 +3,8 @@ import * as vscode from 'vscode';
import Configuration from './configuration';
import Stock from './stock';
import { calcFixedNumber, keepDecimal } from './utils';
+import { FutureData } from './futures';
+import logger from './logger';
const stockHub = new Map();
@@ -65,3 +67,93 @@ export const render = (stocks: any) => {
stockHub.get(code).barItem.tooltip = getTooltipText(stocks[code]);
}
};
+
+let futureBars: vscode.StatusBarItem[] = [];
+
+export function stopAllRender() {
+ for (const [code, item] of stockHub) {
+ const barItem = item.barItem;
+ barItem.hide();
+ barItem.dispose();
+ }
+ stockHub.clear();
+
+ for (const item of futureBars) {
+ const barItem = item;
+ barItem.hide();
+ barItem.dispose();
+ }
+ futureBars = [];
+}
+
+function syncFutureBarItem(futures: FutureData[]) {
+ const addBars = futures.length - futureBars.length;
+ for (let i = 0; i < -addBars; i++) {
+ const barItem = futureBars[futureBars.length - 1];
+ barItem.dispose();
+ futureBars.pop();
+ }
+
+ for (let i = 0; i < addBars; i++) {
+ const barItem = vscode.window.createStatusBarItem(
+ vscode.StatusBarAlignment.Left,
+ );
+ barItem.show();
+ futureBars.push(barItem);
+ }
+}
+
+function formatFuture(item: FutureData) {
+ const itemName = item.alias || item.name || '';
+ let text = `${item.code} ---`;
+ const tooltip = new vscode.MarkdownString(`**${itemName}** ${item.code}\n\n`);
+
+ try {
+ if (!item.price) {
+ return {
+ text,
+ tooltip,
+ };
+ }
+
+ const percent = item.price.pre_price
+ ? (item.price.current_price - item.price.pre_price) / item.price.pre_price
+ : 0;
+
+ const percentStr = `${keepDecimal(percent * 100, 2)}%`;
+ const balance = Math.round(
+ (item.price.current_price - item.hold_price) *
+ item.hold_number *
+ item.ratio,
+ );
+ tooltip.appendMarkdown(
+ `价格: **${item.price.current_price}** 涨跌: **${percentStr}**\n\n`,
+ );
+
+ const balanceStr = balance > 0 ? `+${balance}` : `${balance}`;
+ console.log(item);
+ if (item.hold_price && item.hold_number && item.ratio) {
+ text = `${item.code} ${item.price.current_price} ${balanceStr}`;
+ tooltip.appendMarkdown(`盈亏: **${balanceStr}**`);
+ } else {
+ text = `${item.code} ${item.price.current_price} ${percentStr}`;
+ }
+ } catch (err) {
+ logger.error('%O', err);
+ }
+
+ return {
+ text,
+ tooltip,
+ };
+}
+
+export function renderFutures(futures: FutureData[]) {
+ //logger.debug('renderFutures', futures);
+ syncFutureBarItem(futures);
+ for (const [index, barItem] of futureBars.entries()) {
+ const { text, tooltip } = formatFuture(futures[index]);
+ barItem.text = text;
+ barItem.tooltip = tooltip;
+ }
+}
diff --git a/src/timer.ts b/src/timer.ts
index 0fd9547..c221423 100644
--- a/src/timer.ts
+++ b/src/timer.ts
@@ -2,14 +2,16 @@ import Configuration from './configuration';
class Timer {
async await() {
- while (true) {
- await this.sleep(Configuration.getUpdateInterval());
+ await this.sleep(Configuration.getUpdateInterval());
- // 工作日工作时间 9:00-11.30 13:00-15:00
- if (this.isWorkDay() && this.isWorkTime()) {
- return true;
- }
- }
+ // while (true) {
+ // await this.sleep(Configuration.getUpdateInterval());
+
+ // //工作日工作时间 9:00-11.30 13:00-15:00
+ // if (this.isWorkDay() && this.isWorkTime()) {
+ // return true;
+ // }
+ // }
}
/**
diff --git a/test/api.http b/test/api.http
new file mode 100644
index 0000000..e80985c
--- /dev/null
+++ b/test/api.http
@@ -0,0 +1,33 @@
+### test futures price
+GET https://finance.pae.baidu.com/selfselect/getstockquotation?all=1&isIndex=false&isBk=false&isBlock=false&isStock=false&isFutures=true&isForeign=false&code=AU888&stockType=ab&newFormat=1&market_type=ab&group=quotation_futures_minute&finClientType=pc
+
+### test futures price
+GET https://finance.pae.baidu.com/selfselect/getstockquotation?all=3&isIndex=false&isStock=false&isFutures=true&code=AU888&stockType=ab&newFormat=1&finClientType=pc&market_type=ab&group=quotation_futures_minute
+
+####
+POST https://finance.pae.baidu.com/selfselect/gettrenddata?all=1
+Content-Type: application/x-www-form-urlencoded
+
+stock=%5B%7B%22code%22%3A%22CU2409%22%2C%22market%22%3A%22ab%22%2C%22type%22%3A%22futures%22%7D%2C%7B%22code%22%3A%22SA409%22%2C%22market%22%3A%22ab%22%2C%22type%22%3A%22futures%22%7D%2C%7B%22code%22%3A%22FG409%22%2C%22market%22%3A%22ab%22%2C%22type%22%3A%22futures%22%7D%2C%7B%22code%22%3A%22JM888%22%2C%22market%22%3A%22ab%22%2C%22type%22%3A%22futures%22%7D%2C%7B%22code%22%3A%22M9888%22%2C%22market%22%3A%22ab%22%2C%22type%22%3A%22futures%22%7D%2C%7B%22code%22%3A%22SM888%22%2C%22market%22%3A%22ab%22%2C%22type%22%3A%22futures%22%7D%5D&finClientType=pc
+
+
+####
+GET https://d.10jqka.com.cn/v6/time/qh_FG2409/last.js
+Referer: https://goodsfu.10jqka.com.cn/
+Content-Type: application/json
+
+
+#### 同花顺
+GET https://fupage.10jqka.com.cn/futgwapi/api/market/basis/v2/trend_data?contract=ag2408&spot_index_id=-1
+
+###
+GET https://fupage.10jqka.com.cn/futgwapi/api/f10/contract/v1/info?code=sa9999
+
+###
+GET https://api.jijinhao.com/sQuoteCenter/realTime.htm?code=JO_165681&_=1718636839611
+Referer: https://www.cngold.org/
+
+###
+GET https://hq.sinajs.cn?list=nf_CU2408
+Referer: https://finance.sina.com.cn
+Content-Type: application/json
\ No newline at end of file
diff --git a/tsconfig.json b/tsconfig.json
index 2c290eb..f6e9fc9 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -16,7 +16,8 @@
"noImplicitAny": false,
"strictBindCallApply": false,
"forceConsistentCasingInFileNames": false,
- "noFallthroughCasesInSwitch": false
+ "noFallthroughCasesInSwitch": false,
+ "typeRoots": ["./types", "./node_modules/@types"]
},
"exclude": ["node_modules", "test", "dist", "**/*spec.ts"]
}
diff --git a/types/stock-bar.d.ts b/types/stock-bar.d.ts
index 09e8b14..e6d0a21 100644
--- a/types/stock-bar.d.ts
+++ b/types/stock-bar.d.ts
@@ -4,8 +4,16 @@ declare module 'stock-bar' {
alias: string;
}
type color = string;
-
- export type StockOptions = (string|StockOption)[];
+
+ export interface FutureOption {
+ code: string;
+ alias?: string;
+ hold_price?: number; //持仓成本
+ hold_number?: number; //持仓, 1代表多,-1代表空
+ }
+
+ export type StockOptions = (string | StockOption)[];
+ export type FutureOptions = FutureOption[];
export type UpdateIntervalOption = number;
export type RiseColorOption = color;
export type FallColorOption = color;