Skip to content

Commit

Permalink
feat: 期货优化调整
Browse files Browse the repository at this point in the history
  • Loading branch information
Chef5 committed Oct 12, 2024
1 parent 73e077c commit dabe029
Show file tree
Hide file tree
Showing 7 changed files with 124 additions and 92 deletions.
63 changes: 38 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,53 +1,44 @@
# Stock Bar

VScode 插件 | A 股 | 港股 | 实时股票数据 | 状态栏实时更新
VScode 插件 | A 股 | 港股 | 期货 | 实时股票数据 | 状态栏实时更新

`Stock Bar`会在开盘期间自动刷新股票数据,并在 VScode 底部状态栏显示股票基本数据,让你在使用 VScode 期间能随时关注到你的股票。

为了隐秘性,`Stock Bar`默认只会显示股价、百分点这样的纯数字,当你将鼠标移上去就可以查看详情。当然为了区分,也可以自定义显示股票的名称(建议使用英文字母,别问我为什么)
为了隐秘性,`Stock Bar`默认只会显示股价、百分点这样的纯数字,当你将鼠标移上去就可以查看详情。当然为了区分,也可以自定义显示股票的名称

![image](https://raw.githubusercontent.com/Chef5/stock-bar/main/stock-bar-plugin.png)

插件已开源,开源地址:[Github](https://github.com/Chef5/stock-bar),欢迎点星星 ⭐️、提 issue 或者 pr

## 启动
## 命令

(ctrl + shift + P) 后运行命令
`Ctrl/Cmd + Shift + P` 打开命令输入面板

- stock watch start 开始显示
- stock watch stop 关闭显示
- Show Stock Bar 显示Stock Bar
- Hide Stock Bar 关闭Stock Bar(后台不再发起更新数据请求)

## 插件配置

修改用户配置,添加你所需要监控的股票代码

```js
// 股票:这是一个数组,你可以直接添加股票代码字符串,也可以添加对象,对象格式如下:
// {
// code: string, // 股票代码:需要添加股市前缀,前缀参考文档下方:前缀说明
// alias: string, // 别名:默认为空,建议使用字母
// }
// 使用字符串时,别名默认为空:["sz000001"] 等价于 [{"code": "sz000001", "alias": ""}]
// 股票配置:数组
"stock-bar.stocks": [
"sh000001",
"sh000001", // 可以直接添加股票代码字符串
{
"code": "sz000001",
"alias": "平安"
"code": "sz000001", // 也可以添加详细配置
"alias": "平安",
"hold_price": 0,
"hold_number": 0
}
],

// 期货: 数组,可以添加期货代码
// {
// code: string, //期货代码, 比如 sa9999, sa2409
// alias: string, // 期货别名,这个可以不填,会自动根据代码获取
// hold_price: number, //持仓价格,即多空单的价格
// hold_number: number //持仓, 正数代表持有多单,负数代表持有空单,当配置了持仓价格和持仓后,
// 会显示持仓盈亏,否则显示当日价格涨跌幅
// }
// 期货配置:数组
"stock-bar.futures": [
{
"code": "sa9999",
"hold_price": 2500,
"code": "cu2409",
"alias": "",
"hold_price": 0,
"hold_number": -1
}
],
Expand All @@ -62,6 +53,25 @@ VScode 插件 | A 股 | 港股 | 实时股票数据 | 状态栏实时更新
"stock-bar.fallColor": ""
```

## 股票配置说明

股票配置可以股票代码字符串,也可以进行一下配置:

- `**code**: string`: 股票代码,需要添加股市前缀,前缀参考文档下方:前缀说明
- `**alias**: string`: 别名,默认为空
- `**hold_price**: number`: 持仓价格,非必填,默认为0
- `**hold_number**: number`: 持仓数量,非必填,默认为0

股票代码字符串时,如:`["sz000001"]` 等价于 `[{"code": "sz000001", "alias": "", "hold_price": 0, "hold_number": 0}]`

## 股票配置说明

- `**code**: string`: 期货代码, 如:`cu2409``sa2409`
- `**alias**: string`: 期货别名
- `**hold_price**: number`: 持仓价格,即多空单的价格
- `**hold_number**: number`: 持仓,正数代表持有多单,负数代表持有空单


## 前缀说明

- sh:沪市,不加前缀的情况下,6 开头的代码默认加上 sh(上证指数:sh000001)
Expand Down Expand Up @@ -95,6 +105,9 @@ VScode 插件 | A 股 | 港股 | 实时股票数据 | 状态栏实时更新
<a href="https://github.com/Liudon">
<img src="https://github.com/Liudon.png?size=100" width="100" height="100" style="border-radius: 50%;" />
</a>
<a href="https://github.com/weibobo">
<img src="https://github.com/weibobo.png?size=100" width="100" height="100" style="border-radius: 50%;" />
</a>
</p>

## 版本许可
Expand Down
11 changes: 7 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@
"sh000001",
{
"code": "sz000001",
"alias": "平安"
"alias": "平安",
"hold_price": 0,
"hold_number": 0
}
],
"description": "股票代码数组,配置需要监控的股票代码,具体配置规则请查看插件详情页"
Expand All @@ -39,7 +41,8 @@
"default": [
{
"code": "sa9999",
"hold_price": 2300,
"alias": "",
"hold_price": 0,
"hold_number": -1
}
],
Expand All @@ -65,11 +68,11 @@
"commands": [
{
"command": "stockbar.start",
"title": "stock watch start"
"title": "Show Stock Bar"
},
{
"command": "stockbar.stop",
"title": "stock watch stop"
"title": "Hide Stock Bar"
}
]
},
Expand Down
6 changes: 2 additions & 4 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ function loadChoiceStocks() {
return new Stock(v);
}
if (typeof v === 'object') {
return new Stock(v.code, v.alias);
return new Stock(v.code, v.alias, v.hold_price, v.hold_number);
}
throw new Error(
'配置格式错误, 查看 https://github.com/Chef5/stock-bar#配置',
Expand All @@ -25,7 +25,6 @@ let timer = null;
let stocks: Stock[];

function restart() {
//console.log('restart');
const interval = Configuration.getUpdateInterval();
if (timer) {
clearInterval(timer);
Expand Down Expand Up @@ -66,7 +65,6 @@ async function ticker() {
}

function stop() {
//console.log('stop');
if (timer) {
clearInterval(timer);
timer = null;
Expand All @@ -75,7 +73,6 @@ function stop() {
}

export function activate(context: vscode.ExtensionContext) {
//console.log('activivate');
stocks = loadChoiceStocks();

const startCmd = vscode.commands.registerCommand('stockbar.start', restart);
Expand All @@ -90,6 +87,7 @@ export function activate(context: vscode.ExtensionContext) {
);
context.subscriptions.push(startCmd);
context.subscriptions.push(stopCmd);
restart(); // 初始默认打开
}

export function deactivate() {
Expand Down
40 changes: 23 additions & 17 deletions src/futures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import axios, { AxiosInstance } from 'axios';
import { FutureOption } from 'stock-bar';
import logger from './logger';
import { keepDecimal } from './utils';

class Provider {
instance: AxiosInstance;
Expand All @@ -17,9 +18,13 @@ class Provider {
try {
const url = `https://fupage.10jqka.com.cn/futgwapi/api/f10/contract/v1/info?code=${code}`;

Check warning on line 19 in src/futures.ts

View workflow job for this annotation

GitHub Actions / lint (16.x)

'url' is assigned a value but never used
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()}`)
])
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();
Expand Down Expand Up @@ -90,22 +95,31 @@ class ProviderSina extends Provider {
'Content-Type': 'application/json',
};
const url = `https://hq.sinajs.cn?list=nf_${code}`;
let ret = (await this.instance.get(url, { headers, responseType:'arraybuffer'})).data;
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; }
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]);
const updown = keepDecimal((current_price ?? 0) - (pre_price ?? 0), 2);
return {
name,
open,
high,
low,
updown,
pre_price,
current_price,
};
Expand All @@ -128,6 +142,10 @@ export class FutureData {
inited = false;
init_times = 0;
price: {
open: number;
high: number;
low: number;
updown: string;
pre_price: number;
current_price: number;
} = null;
Expand Down Expand Up @@ -199,15 +217,3 @@ export default class FutureHandler {
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();
83 changes: 42 additions & 41 deletions src/render.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ 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();

Expand All @@ -24,12 +23,21 @@ function getItemText(item: Stock) {
}

function getTooltipText(item: Stock) {
return (
`【${item.name}】今日行情\n` +
`涨跌:${item.updown} 百分:${keepDecimal(item.percent * 100, 2)}%\n` +
`最高:${item.high} 最低:${item.low}\n` +
`今开:${item.open} 昨收:${item.yestclose}`
);
const hasHold = item.hold_price && item.hold_number;
const tooltips = [
`【${item.name}】今日行情`,
`涨跌:${item.updown} 百分:${keepDecimal(item.percent * 100, 2)}%`,
`最高:${item.high} 最低:${item.low}`,
`今开:${item.open} 昨收:${item.yestclose}`,
];
if (hasHold) {
const balance = Math.round(
(item.price - item.hold_price) * item.hold_number,
);
const balanceStr = balance > 0 ? `+${balance}` : `${balance}`;
tooltips.push(`盈亏:${balanceStr}`);
}
return tooltips.join('\n');
}

/**
Expand Down Expand Up @@ -104,52 +112,45 @@ function syncFutureBarItem(futures: FutureData[]) {
}

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,
};
}

let percentStr = '-';
let balanceStr = '-';
const hasHold = item.hold_price && item.hold_number && item.ratio;
if (item.price) {
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}`;
percentStr = `${keepDecimal(percent * 100, 2)}`;
if (hasHold) {
const balance = Math.round(
(item.price.current_price - item.hold_price) *
item.hold_number *
item.ratio,
);
balanceStr = balance > 0 ? `+${balance}` : `${balance}`;
}
} catch (err) {
logger.error('%O', err);
}

const text = `${item.alias ?? item.name ?? item.code} ${
item.price?.current_price ?? '-'
} ${percentStr}%`;

const tooltips = [
`【${item.name}】今日行情`,
`涨跌:${item.price?.updown} 百分:${percentStr}%`,
`最高:${item.price?.high} 最低:${item.price?.low}`,
`今开:${item.price?.open} 昨收:${item.price?.pre_price}`,
];
if (hasHold) {
tooltips.push(`盈亏:${balanceStr}`);
}

return {
text,
tooltip,
tooltip: tooltips.join('\n'),
};
}

export function renderFutures(futures: FutureData[]) {
//logger.debug('renderFutures', futures);
syncFutureBarItem(futures);
for (const [index, barItem] of futureBars.entries()) {
const { text, tooltip } = formatFuture(futures[index]);
Expand Down
Loading

0 comments on commit dabe029

Please sign in to comment.