Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: 状态栏增加美股和港股的盈亏显示 #508

Merged
merged 3 commits into from
Jan 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion src/explorer/forexService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,9 @@ import Axios from 'axios';
import { load } from 'cheerio';
import { ExtensionContext } from 'vscode';
import { LeekTreeItem } from '../shared/leekTreeItem';
import { FundInfo, TreeItemType } from '../shared/typed';
import { ForexData, FundInfo, TreeItemType } from '../shared/typed';
import { LeekService } from './leekService';
import globalState from '../globalState';

export class ForexService extends LeekService {
private context: ExtensionContext;
Expand All @@ -19,6 +20,12 @@ export class ForexService extends LeekService {
'韩国元',
];

private forexMap: Record<string, RegExp | ((code: string) => boolean)> = {
'美元': /^usr_/,
'港币': /^hk/
};


constructor(context: ExtensionContext) {
super();
this.context = context;
Expand All @@ -35,6 +42,8 @@ export class ForexService extends LeekService {

const $ = load(html);
const bocForexDataList: LeekTreeItem[] = [];

const forexList: Array<ForexData> = [];
$('table').eq(1).find('tr').each((i, trElement) => {
const rowData: FundInfo = {
percent: '',
Expand Down Expand Up @@ -86,9 +95,21 @@ export class ForexService extends LeekService {
if (rowData.name.length) {
const treeItem = new LeekTreeItem(rowData, this.context);
bocForexDataList.push(treeItem);

const filter = this.forexMap[rowData.name];
if (filter) {
forexList.push({
filter,
...rowData,
});
}
}
});

if (forexList.length > 0) {
globalState.forexList = forexList;
}

bocForexDataList.sort((a, b) => {
return this.priorityList.indexOf(b.info.name) - this.priorityList.indexOf(a.info.name);
});
Expand Down
27 changes: 26 additions & 1 deletion src/explorer/stockService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,13 @@ export default class StockService extends LeekService {
let high = params[6];
let low = params[7];
fixedNumber = calcFixedPriceNumber(open, yestclose, price, high, low);
const profitData = stockPrice[code] || {};
const heldData: HeldData = {};
if (profitData.amount) {
// 表示是持仓股
heldData.heldAmount = profitData.amount;
heldData.heldPrice = profitData.unitPrice;
}
stockItem = {
code,
name: params[0],
Expand All @@ -216,6 +223,7 @@ export default class StockService extends LeekService {
volume: formatNumber(params[10], 2),
amount: '接口无数据',
percent: '',
...heldData
};
type = code.substr(0, 4);
usStockCount += 1;
Expand Down Expand Up @@ -412,9 +420,25 @@ export default class StockService extends LeekService {
return [];
} else {
const stocks = stockData;
const stockPrice: {
[key: string]: {
amount: number;
earnings: number;
name: string;
price: string;
unitPrice: number;
};
} = globalState.stockPrice;
stocks.forEach((item: any) => {
const { open, yestclose, price, high, low, volume, amount, time } = item;
const { open, yestclose, price, high, low, volume, amount, time, code } = item;
const fixedNumber = calcFixedPriceNumber(open, yestclose, price, high, low);
const profitData = stockPrice[code] || {};
const heldData: HeldData = {};
if (profitData.amount) {
// 表示是持仓股
heldData.heldAmount = profitData.amount;
heldData.heldPrice = profitData.unitPrice;
}
const stockItem: any = {
...item,
open: formatNumber(open, fixedNumber, false),
Expand All @@ -426,6 +450,7 @@ export default class StockService extends LeekService {
amount: formatNumber(amount || 0, 2),
percent: '',
time: `${moment(time).format('YYYY-MM-DD HH:mm:ss')}`,
...heldData,
};
hkStockCount += 1;
if (stockItem) {
Expand Down
5 changes: 5 additions & 0 deletions src/globalState.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ExtensionContext } from 'vscode';
import { DEFAULT_LABEL_FORMAT } from './shared/constant';
import { Telemetry } from './shared/telemetry';
import { ForexData } from './shared/typed';

const deviceId = Math.random().toString(16).substr(2) + Math.random().toString(32).substr(2);

Expand Down Expand Up @@ -40,6 +41,8 @@ let fundLists: Array<Array<string>> = [];

let stockPrice = {}; // 缓存数据
let stockPriceCacheDate = '2020-10-30';

let forexList: Array<ForexData> = []; // 外汇信息
export default {
context,
telemetry,
Expand Down Expand Up @@ -74,4 +77,6 @@ export default {
stockPriceCacheDate,

stockHeldTipShow,

forexList
};
12 changes: 12 additions & 0 deletions src/shared/typed.ts
Original file line number Diff line number Diff line change
Expand Up @@ -112,3 +112,15 @@ export type HeldData = {
heldAmount?: number;
heldPrice?: number;
};

export type ForexData = {
name: string;
filter: ((code: string) => boolean) | RegExp;
spotBuyPrice?: number; // 现汇买入价
cashBuyPrice?: number; // 现钞买入价
spotSellPrice?: number; // 现汇卖出价
cashSellPrice?: number; // 现钞卖出价
conversionPrice?: number; // 中行折算价
publishDateTime?: string; // 发布日期:年月日 时分秒
publishTime?: string; // 发布时间:时分秒
};
37 changes: 32 additions & 5 deletions src/statusbar/Profit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { LeekFundConfig } from '../shared/leekConfig';
import { ProfitStatusBarInfo } from '../shared/typed';
import { events, formatDate, toFixed } from '../shared/utils';
import StockService from '../explorer/stockService';
import globalState from '../globalState';

const PREFIX = '💰';

Expand Down Expand Up @@ -110,13 +111,17 @@ export class ProfitStatusBar {
amount: number;
incomeTotal: number | string;
incomeToday: number | string;
incomeTotalCNY: number | string;
incomeTodayCNY: number | string;
percentTotal: string;
};
const stockInfo: StockInfoType[] = [];

const forexList = globalState.forexList;
stockList.forEach((s) => {
let tmp = {} as StockInfoType;
const { id, info } = s;
const { high, low, open, yestclose, percent, price, name, heldAmount, heldPrice } = info;
const { high, low, open, yestclose, percent, price, name, heldAmount, heldPrice, code } = info;
if (id && open && price) {
if (!heldAmount || !heldPrice) {
return false;
Expand All @@ -127,6 +132,26 @@ export class ProfitStatusBar {
// fix #399,在昨日收盘价没有的时候使用今日开盘价
const incomeToday = (heldAmount * (Number(price) - Number(yestclose || open))).toFixed(2);
const percentTotal = ((Number(incomeTotal) / (heldPrice * heldAmount)) * 100).toFixed(2);

let incomeTodayCNY = '';
let incomeTotalCNY = '';

const forex = forexList.find(({ filter }) => {
if (typeof filter === 'function') {
return filter(code);
} else if (filter instanceof RegExp) {
return filter.test(code);
}
});

if (forex) {
if (forex.spotSellPrice) {
// 按现汇卖出价计算
incomeTodayCNY = (forex.spotSellPrice * Number(incomeToday) / 100).toFixed(2);
incomeTotalCNY = (forex.spotSellPrice * Number(incomeTotal) / 100).toFixed(2);
}
}

tmp = {
id,
name,
Expand All @@ -138,17 +163,19 @@ export class ProfitStatusBar {
amount: heldAmount,
incomeTotal,
incomeToday,
incomeTodayCNY,
incomeTotalCNY,
percentTotal,
};
stockInfo.push(tmp);
}
});
const date = formatDate(new Date());
const allIncomeToday = stockInfo.reduce((prev, cur) => {
return prev + Number(cur.incomeToday);
return prev + Number(cur.incomeTodayCNY ? cur.incomeTodayCNY : cur.incomeToday);
}, 0);
const allIncomeTotal = stockInfo.reduce((prev, cur) => {
return prev + Number(cur.incomeTotal);
return prev + Number(cur.incomeTotalCNY ? cur.incomeTotalCNY : cur.incomeTotal);
}, 0);
// Use the year, month, and day variables as needed
this.stockBarItem.text = `${PREFIX} ${toFixed(allIncomeTotal)} | ${toFixed(allIncomeToday)}`;
Expand All @@ -157,9 +184,9 @@ export class ProfitStatusBar {
`「股票收益统计」 ${date}\r\n \r\n` +
stockInfo
.map((v) => {
return `${v.name} 总收益:${v.incomeTotal} (${v.percentTotal}%) 今天${
return `${v.name} 总收益:${v.incomeTotal} ${v.incomeTotalCNY ? `(CNY: ${v.incomeTotalCNY})` : ''} (${v.percentTotal}%) 今天${
Number(v.incomeToday) > 0 ? '盈利' : '亏损'
}:${v.incomeToday} (${v.percent}%) \r\n`;
}:${v.incomeToday} ${v.incomeTodayCNY ? `(CNY: ${v.incomeTodayCNY})` : ''} (${v.percent}%) \r\n`;
})
.join('\r\n-----------------------------\r\n');
this.stockBarItem.show();
Expand Down
Loading