Skip to content

Commit

Permalink
Merge pull request #508 from action-hong/master
Browse files Browse the repository at this point in the history
feat: 状态栏增加美股和港股的盈亏显示
  • Loading branch information
giscafer authored Jan 14, 2025
2 parents 601d0db + 6707a25 commit 9ae7277
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 7 deletions.
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

0 comments on commit 9ae7277

Please sign in to comment.