feat: 初始化 v3 版本

This commit is contained in:
zhangxiangliang 2022-11-19 13:46:55 +08:00
parent 6b760659ad
commit 77b7d04c85
68 changed files with 45 additions and 7716 deletions

View File

@ -1,12 +0,0 @@
# http://editorconfig.org
root = true
[*]
indent_style = space
indent_size = 2
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false

View File

@ -1,14 +0,0 @@
{
"extends": ["taro"],
"rules": {
"semi": ["error", "always"]
},
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaFeatures": {
"jsx": true
},
"useJSXTextNode": true,
"project": "./tsconfig.json"
}
}

4
.gitignore vendored
View File

@ -1,4 +0,0 @@
dist/
.DS_Store
node_modules/
coverage/

2
.npmrc
View File

@ -1,2 +0,0 @@
sign-git-tag=false
message="build: 发布 %s 版本"

View File

@ -1,7 +0,0 @@
language: node_js
node_js:
- 12
before_install:
- yarn install
after_script:
- yarn run coverage

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 20222 ZHANGXIANGLIANG
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

150
README.md
View File

@ -1,151 +1,37 @@
<h1 align="center">股票数据小助手</h1>
<p align="center">
<a href="https://codecov.io/github/jiucaixiaozhu/stock-api?branch=master"><img src="https://img.shields.io/codecov/c/github/jiucaixiaozhu/stock-api/master.svg?sanitize=true" alt="Coverage Status"></a>
<a href="https://npmcharts.com/compare/stock-api?minimal=true"><img src="https://img.shields.io/npm/dm/stock-api.svg?sanitize=true" alt="Downloads"></a>
<a href="https://www.npmjs.com/package/stock-api"><img src="https://img.shields.io/npm/v/stock-api.svg?sanitize=true" alt="Version"></a>
<a href="https://www.npmjs.com/package/stock-api"><img src="https://img.shields.io/npm/l/stock-api.svg?sanitize=true" alt="License"></a>
<a href="https://www.npmjs.com/package/stock-api"><img src="https://img.shields.io/badge/language-typescript-blue" alt="License"></a>
</p>
# 股票数据小助手
## 简介
一款聚焦在 `股票实时数据``周边相关服务`接口小助手
一款聚焦在 `股票实时数据``周边相关服务` 的代码库。
## 股票数据
| 名称 | 接口名 | 搜索股票代码 | 获取股票实时数据 | 获取股票组实时数据 | 官网 |
| :---: | :---: | :---: | :---: | :---: | :---: |
| 网易财经 | netease | [已实现](#搜索股票代码) | [已实现](#获取股票实时数据) | [已实现](#获取股票组实时数据) | [传送门](https://money.163.com/) |
| 雪球 | xueqiu | [已实现](#搜索股票代码) | [已实现](#获取股票实时数据) | [已实现](#获取股票组实时数据) | [传送门](https://xueqiu.com/) |
| 新浪股票 | sina | [已实现](#搜索股票代码) | [已实现](#获取股票实时数据) | [已实现](#获取股票组实时数据) | [传送门](https://finance.sina.com.cn/) |
| 腾讯股票 | tencent | [已实现](#搜索股票代码) | [已实现](#获取股票实时数据) | [已实现](#获取股票组实时数据) | [传送门](http://gu.qq.com/) |
### [网易财经](https://money.163.com)
## 安装
- [] 搜索股票代码
- [] 获取股票实时数据
- [] 获取股票组实时数据
```shell
npm install stock-api
yarn add stock-api
```
### [雪球](https://xueqiu.com)
## 使用
- [] 搜索股票代码
- [] 获取股票实时数据
- [] 获取股票组实时数据
### 接口概览
### [新浪股票](https://finance.sina.com.cn)
* [选择数据源](#选择数据源)
* [搜索股票代码](#搜索股票代码)
* [获取股票实时数据](#获取股票实时数据)
* [获取股票组实时数据](#获取股票组实时数据)
### 股票代码
由于每个交易所数据规则不一样,为了能统一规范对代码定义了规则 `交易所+股票代码`
| 交易所 | 代号 | 实例 |
| --- | --- | --- |
| 上海交易所 | SH | SH000001 |
| 深圳交易所 | SZ | SZ399001 |
| 香港交易所 | HK | HKHSI |
| 美国交易所 | US | USDJI |
### 选择数据源
##### 可选导入
```typescript
import { stocks } from "stock-api";
// 数据源
const sina = stocks.sina;
const xueqiu = stocks.xueqiu;
const netease = stocks.netease;
const tencent = stocks.tencent;
```
### 搜索股票代码
##### 示例
```typescript
import { stocks } from "stock-api";
// 获取股票组实时数据
stocks.sina.searchStocks(["510500"]).then(console.log);
```
##### 输出
```typescript
[{
code: 'SH510500',
name: '500ETF',
percent: 0.028383,
now: 7.174,
low: 6.93,
high: 7.184,
yesterday: 6.976
}]
```
### 获取股票实时数据
##### 示例
```typescript
import { stocks } from "stock-api";
// 获取股票实时数据
stocks.sina.getStock("SH510500").then(console.log);
```
##### 输出
```typescript
{
code: 'SH510500',
name: '500ETF',
percent: 0.028383,
now: 7.174,
low: 6.93,
high: 7.184,
yesterday: 6.976
}
```
### 获取股票组实时数据
##### 示例
```typescript
import { stocks } from "stock-api";
// 获取股票组实时数据
stocks.sina.getStocks(["SH510500"]).then(console.log);
```
##### 输出
```typescript
[{
code: 'SH510500',
name: '500ETF',
percent: 0.028383,
now: 7.174,
low: 6.93,
high: 7.184,
yesterday: 6.976
}]
```
- [] 搜索股票代码
- [] 获取股票实时数据
- [] 获取股票组实时数据
### [腾讯股票](http://gu.qq.com)
- [] 搜索股票代码
- [] 获取股票实时数据
- [] 获取股票组实时数据
## 一起成长
> 韭菜小猪也有暴富梦~
- 在困惑的城市里总少不了并肩同行的 伙伴 让我们一起成长。
- 如果您想让更多人看到文章可以点个 点赞。
- 如果您想激励小二可以到 Github 给个 小星星。

View File

@ -1,22 +0,0 @@
{
"verbose": true,
"testTimeout": 15000,
"transform": {
"^.+\\.(t|j)sx?$": "ts-jest"
},
"testRegex": "(/test/.*|(\\.|/)(test|spec))\\.(jsx?|tsx?)$",
"moduleFileExtensions": [
"ts",
"tsx",
"js",
"jsx",
"json",
"node"
],
"moduleDirectories": ["node_modules", "src"],
"moduleNameMapper": {
"^@stocks/(.*)$": "<rootDir>/src/stocks/$1",
"^@utils/(.*)$": "<rootDir>/src/utils/$1",
"^types/(.*)$": "<rootDir>/types/$1"
}
}

View File

@ -1,47 +1,16 @@
{
"name": "stock-api",
"version": "2.0.5",
"description": "【韭菜小猪】免费股票数据分析相关接口",
"version": "3.0.0",
"description": "免费股票数据分析相关接口",
"keywords": [
"股票",
"数据分析",
"接口"
],
"main": "dist/index.js",
"types": "types/index.d.ts",
"repository": "https://github.com/jiucaixiaozhu/stock-api",
"repository": "https://github.com/zhangxiangliang/stock-api",
"author": "zhangxiangliang",
"license": "MIT",
"files": [
"dist/**/*",
"types/**/*"
],
"scripts": {
"prepublishOnly": "yarn run test",
"prepare": "rm -rf ./dist && yarn run build",
"preversion": "npm test",
"version": "git add -A ./",
"postversion": "git push && git push --tags",
"build": "ttsc",
"watch": "ttsc --watch",
"test": "jest --config jestconfig.json --coverage",
"coverage": "yarn run test && codecov"
},
"devDependencies": {
"@types/jest": "^26.0.5",
"@typescript-eslint/parser": "^3.7.0",
"codecov": "^3.7.2",
"jest": "^26.1.0",
"nyc": "^15.1.0",
"ts-jest": "^26.1.3",
"ttypescript": "^1.5.10",
"typescript": "^3.9.7",
"typescript-transform-paths": "^1.1.14"
},
"dependencies": {
"@types/lodash": "^4.14.159",
"iconv-lite": "^0.6.2",
"lodash": "^4.17.20",
"superagent": "^5.3.1"
}
"dist"
]
}

View File

@ -1,5 +0,0 @@
// Stocks
import stocks from './stocks/index';
export { stocks };
export default { stocks };

View File

@ -1,37 +0,0 @@
// Utils
import { ERROR_UNDEFINED_GET_STOCK, ERROR_UNDEFINED_GET_STOCKS, ERROR_UNDEFINED_SEARCH_STOCK } from "@utils/constant";
// Types
import Stock from "types/utils/stock";
import StockApi from "types/stocks/index";
/**
*
*/
const Base: StockApi = {
/**
*
* @param code
*/
async getStock(code: string): Promise<Stock> {
throw new Error(ERROR_UNDEFINED_GET_STOCK);
},
/**
*
* @param codes
*/
async getStocks(codes: string[]): Promise<Stock[]> {
throw new Error(ERROR_UNDEFINED_GET_STOCKS);
},
/**
*
* @param key
*/
async searchStocks(key: string): Promise<Stock[]> {
throw new Error(ERROR_UNDEFINED_SEARCH_STOCK);
}
};
export default Base;

View File

@ -1,77 +0,0 @@
// Utils
import { COMMON_SH, COMMON_SZ, COMMON_HK, COMMON_US } from "@stocks/base/utils/constant";
import { ERROR_UNDEFINED_API_CODE, ERROR_UNDEFINED_SZ_API_CODE, ERROR_UNDEFINED_SH_API_CODE, ERROR_UNDEFINED_HK_API_CODE, ERROR_UNDEFINED_US_API_CODE, ERROR_API_CODE } from "@utils/constant";
// Types
import ApiCodeTransform from "types/stocks/transforms/api-code";
/**
*
*/
class BaseApiCodeTransform implements ApiCodeTransform {
/**
*
* @param code
*/
public transform(code: string): string {
if (code.indexOf(COMMON_SH) === 0) {
return this.SHTransform(code);
}
if (code.indexOf(COMMON_SZ) === 0) {
return this.SZTransform(code);
}
if (code.indexOf(COMMON_HK) === 0) {
return this.HKTransform(code);
}
if (code.indexOf(COMMON_US) === 0) {
return this.USTransform(code);
}
throw new Error(ERROR_API_CODE);
}
/**
*
* @param codes
*/
public transforms(codes: string[]): string[] {
return codes.map((code) => this.transform(code));
}
/**
*
* @param code
*/
public SZTransform(code: string): string {
throw new Error(ERROR_UNDEFINED_SZ_API_CODE);
}
/**
*
* @param code
*/
public SHTransform(code: string): string {
throw new Error(ERROR_UNDEFINED_SH_API_CODE);
}
/**
*
* @param code
*/
public HKTransform(code: string): string {
throw new Error(ERROR_UNDEFINED_HK_API_CODE);
}
/**
*
* @param code
*/
public USTransform(code: string): string {
throw new Error(ERROR_UNDEFINED_US_API_CODE);
}
}
export default BaseApiCodeTransform;

View File

@ -1,77 +0,0 @@
// Utils
import { ERROR_COMMON_CODE, ERROR_UNDEFINED_SZ_COMMON_CODE, ERROR_UNDEFINED_SH_COMMON_CODE, ERROR_UNDEFINED_HK_COMMON_CODE, ERROR_UNDEFINED_US_COMMON_CODE } from "@utils/constant";
// Types
import CommonCodeTransform from "types/stocks/transforms/common-code";
import { COMMON_SH, COMMON_SZ, COMMON_HK, COMMON_US } from "../utils/constant";
/**
*
*/
class BaseCommonCodeTransform implements CommonCodeTransform {
/**
*
* @param code
*/
public transform(code: string): string {
if (code.indexOf(COMMON_SH) === 0) {
return this.SHTransform(code);
}
if (code.indexOf(COMMON_SZ) === 0) {
return this.SZTransform(code);
}
if (code.indexOf(COMMON_HK) === 0) {
return this.HKTransform(code);
}
if (code.indexOf(COMMON_US) === 0) {
return this.USTransform(code);
}
throw new Error(ERROR_COMMON_CODE);
}
/**
*
* @param codes
*/
public transforms(codes: string[]): string[] {
return codes.map((code) => this.transform(code));
}
/**
*
* @param code
*/
public SZTransform(code: string): string {
throw new Error(ERROR_UNDEFINED_SZ_COMMON_CODE);
}
/**
*
* @param code
*/
public SHTransform(code: string): string {
throw new Error(ERROR_UNDEFINED_SH_COMMON_CODE);
}
/**
*
* @param code
*/
public HKTransform(code: string): string {
throw new Error(ERROR_UNDEFINED_HK_COMMON_CODE);
}
/**
*
* @param code
*/
public USTransform(code: string): string {
throw new Error(ERROR_UNDEFINED_US_COMMON_CODE);
}
}
export default BaseCommonCodeTransform;

View File

@ -1,68 +0,0 @@
// Utils
import { ERROR_UNDEFINED_GET_CODE, ERROR_UNDEFINED_GET_NAME, ERROR_UNDEFINED_GET_NOW, ERROR_UNDEFINED_GET_LOW, ERROR_UNDEFINED_GET_HIGH, ERROR_UNDEFINED_GET_YESTERDAY, ERROR_UNDEFINED_GET_PERCENT, ERROR_UNDEFINED_GET_STOCK } from "@utils/constant";
// Types
import Stock from "types/utils/stock";
/**
*
*/
class BaseStockTransform {
/**
*
*/
getCode(): string {
throw new Error(ERROR_UNDEFINED_GET_CODE);
}
/**
*
*/
getName(): string {
throw new Error(ERROR_UNDEFINED_GET_NAME);
}
/**
*
*/
getNow(): number {
throw new Error(ERROR_UNDEFINED_GET_NOW);
}
/**
*
*/
getLow(): number {
throw new Error(ERROR_UNDEFINED_GET_LOW);
}
/**
*
*/
getHigh(): number {
throw new Error(ERROR_UNDEFINED_GET_HIGH);
}
/**
*
*/
getYesterday(): number {
throw new Error(ERROR_UNDEFINED_GET_YESTERDAY);
}
/**
*
*/
getPercent(): number {
throw new Error(ERROR_UNDEFINED_GET_PERCENT);
}
/**
*
*/
getStock(): Stock {
throw new Error(ERROR_UNDEFINED_GET_STOCK);
}
}
export default BaseStockTransform;

View File

@ -1,6 +0,0 @@
// 默认交易所常量
export const COMMON_SZ = "SZ"; // 深交所相关常量
export const COMMON_SH = "SH"; // 上交所相关常量
export const COMMON_HK = "HK"; // 港交所相关常量
export const COMMON_US = "US"; // 美交所相关常量

View File

@ -1,22 +0,0 @@
// Stocks
import base from "./base";
import sina from "./sina";
import xueqiu from "./xueqiu";
import netease from "./netease";
import tencent from "./tencent";
export {
base,
sina,
xueqiu,
netease,
tencent,
};
export default {
base,
sina,
xueqiu,
netease,
tencent,
};

View File

@ -1,107 +0,0 @@
// NPM
import { uniq } from 'lodash';
// Stocks
import NeteaseStockTransform from "@stocks/netease/transforms/stock";
import NeteaseCommonCodeTransform from "@stocks/netease/transforms/common-code";
// Utils
import fetch from "@utils/fetch";
import { DEFAULT_STOCK } from "@utils/constant";
import { COMMON_SZ, COMMON_SH } from "@stocks/base/utils/constant";
// Types
import Stock from "types/utils/stock";
import StockApi from "types/stocks/index";
import Dictionary from "types/utils/dictionary";
/**
*
*/
const Netease: StockApi = {
/**
*
* @param code
*/
async getStock(code: string): Promise<Stock> {
const transform = (new NeteaseCommonCodeTransform).transform(code);
const url = `https://api.money.126.net/data/feed/${transform},money.api?callback=topstock`;
const res = await fetch.get(url);
const items = JSON.parse(res.body.toString().replace(/\(|\)|;|(topstock)|\s/g, '').replace('{{', '{').replace('}}}', "}}"));
const params = items[transform];
if (!params) {
return { ...DEFAULT_STOCK, code };
}
const data = (new NeteaseStockTransform(code, params));
return data.getStock();
},
/**
*
* @param codes
*/
async getStocks(codes: string[]): Promise<Stock[]> {
codes = uniq(codes.filter(i => i !== ''));
// 无股票时返回空数组
if (codes.length === 0) {
return [];
}
const transforms = (new NeteaseCommonCodeTransform).transforms(codes);
// 数据获取
const url = `https://api.money.126.net/data/feed/${transforms.join(',')},money.api?callback=topstock`;
const res = await fetch.get(url);
// 解析数据
const items = JSON.parse(res.body.toString().replace(/\(|\)|;|(topstock)|\s/g, '').replace('{{', '{').replace('}}}', "}}"));
return codes.map(code => {
const transform = (new NeteaseCommonCodeTransform).transform(code);
const params = items[transform];
if (!params) {
return { ...DEFAULT_STOCK, code };
}
const data = (new NeteaseStockTransform(code, params));
return data.getStock();
});
},
/**
*
* @param key
*/
async searchStocks(key: string): Promise<Stock[]> {
// 数据获取
const url = `https://quotes.money.163.com/stocksearch/json.do?type=&count=5&word=${encodeURIComponent(key)}&callback=topstock`;
const res = await fetch.get(url);
// 解析数据
const row = res.body.toString().replace(/\(|\)|;|(topstock)|\s/g, '').replace('{{', '{').replace('}}}', "}}");
const items: Dictionary<string>[] = JSON.parse(row);
const codes: string[] = items.map(i => {
if (i.tag.includes(COMMON_SZ) || i.type.includes(COMMON_SZ)) {
return COMMON_SZ + i.symbol;
}
if (i.tag.includes(COMMON_SH) || i.type.includes(COMMON_SH)) {
return COMMON_SH + i.symbol;
}
return '';
});
return await Netease.getStocks(uniq(codes.filter(i => i !== '')));
}
}
export default Netease;

View File

@ -1,94 +0,0 @@
// Stocks
import BaseApiCodeTransform from "@stocks/base/transforms/api-code";
// Utils
import { ERROR_API_CODE } from "@utils/constant";
import { COMMON_SH, COMMON_SZ, COMMON_HK, COMMON_US } from "@stocks/base/utils/constant";
import { NETEASE_SZ, NETEASE_SH, NETEASE_HK, NETEASE_US } from "@stocks/netease/utils/constant";
/**
*
*/
class NeteaseApiCodeTransform extends BaseApiCodeTransform {
/**
*
* @param code
*/
public transform(code: string): string {
if (code.indexOf(NETEASE_SZ) === 0) {
return this.SZTransform(code);
}
if (code.indexOf(NETEASE_SH) === 0) {
return this.SHTransform(code);
}
if (code.indexOf(NETEASE_HK) === 0) {
return this.HKTransform(code);
}
if (code.indexOf(NETEASE_US) === 0) {
return this.USTransform(code);
}
throw new Error(ERROR_API_CODE);
}
/**
*
* @param codes
*/
public transforms(codes: string[]): string[] {
return codes.map((code) => this.transform(code));
}
/**
*
* @param code
*/
public SZTransform(code: string): string {
if (code.indexOf(NETEASE_SZ) !== 0) {
throw new Error(ERROR_API_CODE);
}
return COMMON_SZ + code.replace(NETEASE_SZ, "");
}
/**
*
* @param code
*/
public SHTransform(code: string): string {
if (!code.includes(NETEASE_SH)) {
throw new Error(ERROR_API_CODE);
}
return COMMON_SH + code.replace(NETEASE_SH, "");
}
/**
*
* @param code
*/
public HKTransform(code: string): string {
if (!code.includes(NETEASE_HK)) {
throw new Error(ERROR_API_CODE);
}
return COMMON_HK + code.replace(NETEASE_HK, "");
}
/**
*
* @param code
*/
public USTransform(code: string): string {
if (!code.includes(NETEASE_US)) {
throw new Error(ERROR_API_CODE);
}
return COMMON_US + code.replace(NETEASE_US, "");
}
}
export default NeteaseApiCodeTransform;

View File

@ -1,78 +0,0 @@
// Stocks
import BaseCommonCodeTransform from "@stocks/base/transforms/common-code";
// Utils
import { ERROR_COMMON_CODE } from "@utils/constant";
import { COMMON_SH, COMMON_SZ, COMMON_HK, COMMON_US } from "@stocks/base/utils/constant";
import { NETEASE_SZ, NETEASE_SH, NETEASE_HK, NETEASE_US } from "@stocks/netease/utils/constant";
/**
*
*/
class NeteaseCommonCodeTransform extends BaseCommonCodeTransform {
/**
*
* @param code
*/
public transform(code: string): string {
return super.transform(code);
}
/**
*
* @param codes
*/
public transforms(codes: string[]): string[] {
return super.transforms(codes);
}
/**
*
* @param code
*/
public SZTransform(code: string): string {
if (!code.includes(COMMON_SZ)) {
throw new Error(ERROR_COMMON_CODE);
}
return NETEASE_SZ + code.replace(COMMON_SZ, "");
}
/**
*
* @param code
*/
public SHTransform(code: string): string {
if (!code.includes(COMMON_SH)) {
throw new Error(ERROR_COMMON_CODE);
}
return NETEASE_SH + code.replace(COMMON_SH, "");
}
/**
*
* @param code
*/
public HKTransform(code: string): string {
if (!code.includes(COMMON_HK)) {
throw new Error(ERROR_COMMON_CODE);
}
return NETEASE_HK + code.replace(COMMON_HK, "");
}
/**
*
* @param code
*/
public USTransform(code: string): string {
if (!code.includes(COMMON_US)) {
throw new Error(ERROR_COMMON_CODE);
}
return NETEASE_US + code.replace(COMMON_US, "");
}
}
export default NeteaseCommonCodeTransform;

View File

@ -1,88 +0,0 @@
// Stocks
import BaseStockTransform from "@stocks/base/transforms/stock";
// Utils
import { DEFAULT_STRING, DEFAULT_NUMBER } from "@utils/constant";
// Types
import Stock from "types/utils/stock";
import Dictionary from "types/utils/dictionary";
/**
*
*/
class NeteaseStockTransform extends BaseStockTransform {
/**
*
*/
constructor(public code: string, public params: Dictionary<number | string>) {
super();
}
/**
*
*/
getCode(): string {
return String(this.code).toUpperCase();
}
/**
*
*/
getName(): string {
return String(this.params.name || DEFAULT_STRING);
}
/**
*
*/
getNow(): number {
return Number(this.params.price || DEFAULT_NUMBER);
}
/**
*
*/
getLow(): number {
return Number(this.params.low || DEFAULT_NUMBER);
}
/**
*
*/
getHigh(): number {
return Number(this.params.high || DEFAULT_NUMBER);
}
/**
*
*/
getYesterday(): number {
return Number(this.params.yestclose || DEFAULT_NUMBER);
}
/**
*
*/
getPercent(): number {
return this.getNow() ? this.getNow() / this.getYesterday() - 1 : 0;
}
/**
*
*/
getStock(): Stock {
return {
code: this.getCode(),
name: this.getName(),
percent: this.getPercent(),
now: this.getNow(),
low: this.getLow(),
high: this.getHigh(),
yesterday: this.getYesterday(),
};
}
}
export default NeteaseStockTransform;

View File

@ -1,5 +0,0 @@
// 默认交易所常量
export const NETEASE_SZ = "1"; // 深交所相关常量
export const NETEASE_SH = "0"; // 上交所相关常量
export const NETEASE_HK = "hk"; // 港交所相关常量
export const NETEASE_US = "US_"; // 美交所相关常量

View File

@ -1,132 +0,0 @@
// NPM
import { uniq } from 'lodash';
// Stocks
import SinaStockTransform from "@stocks/sina/transforms/stock";
import SinaCommonCodeTransform from "@stocks/sina/transforms/common-code";
// Utils
import fetch from "@utils/fetch";
import iconv from "@utils/iconv";
import { DEFAULT_STOCK } from "@utils/constant";
import { COMMON_SZ, COMMON_SH, COMMON_US, COMMON_HK } from "@stocks/base/utils/constant";
// Types
import Stock from "types/utils/stock";
import StockApi from "types/stocks/index";
/**
*
*/
const Sina: StockApi = {
/**
*
* @param code
*/
async getStock(code: string): Promise<Stock> {
const transform = (new SinaCommonCodeTransform).transform(code);
// 数据获取
const url = `https://hq.sinajs.cn/list=${transform}`;
const res = await fetch.get(url);
const body = iconv.decode(res.body, "gb18030");
const rows = body.split(";\n");
const row = rows[0];
// 数据深解析
const [_, paramsUnformat] = row.split('=');
if (paramsUnformat === '""') {
return { ...DEFAULT_STOCK, code };
}
const params = paramsUnformat.replace('"', '').split(",");
const data = (new SinaStockTransform(code, params));
return data.getStock();
},
/**
*
* @param codes
*/
async getStocks(codes: string[]): Promise<Stock[]> {
codes = uniq(codes.filter(i => i !== ''));
// 无股票时返回空数组
if (codes.length === 0) {
return [];
}
const transforms = (new SinaCommonCodeTransform).transforms(codes);
// 数据获取
const url = `https://hq.sinajs.cn/list=${transforms.join(',')}`;
const res = await fetch.get(url);
const body = iconv.decode(res.body, "gb18030");
const rows = body.split(";\n");
return codes.map((code, index) => {
// 数据深解析
const [_, paramsUnformat] = rows[index].split('=');
if (paramsUnformat === '""') {
return { ...DEFAULT_STOCK, code };
}
const params = paramsUnformat.replace('"', '').split(",");
const data = (new SinaStockTransform(code, params));
return data.getStock();
});
},
/**
*
* @param key
*/
async searchStocks(key: string): Promise<Stock[]> {
// 数据获取
const url = `http://suggest3.sinajs.cn/suggest/type=2&key=${encodeURIComponent(key)}`;
const res = await fetch.get(url);
const body = iconv.decode(res.body, "gb18030");
const rows: string[] = body.replace('var suggestvalue="', '').replace('";', '').split(';');
let codes: string[] = [];
for (let i = 0; i < rows.length; i++) {
let code: string = rows[i].split(',')[0];
if (code.indexOf('us') === 0) {
code = code.replace('us', '');
codes = [...codes, COMMON_US + code];
}
if (code.indexOf('sz') === 0) {
code = code.replace('sz', '');
codes = [...codes, COMMON_SZ + code];
}
if (code.indexOf('sh') === 0) {
code = code.replace('sh', '');
codes = [...codes, COMMON_SH + code];
}
if (code.indexOf('hk') === 0) {
code = code.replace('hk', '');
codes = [...codes, COMMON_HK + code];
}
if (code.indexOf('of') === 0) {
code = code.replace('of', '');
codes = [...codes, COMMON_SZ + code, COMMON_SH + code];
}
}
return await Sina.getStocks(uniq(codes.filter(i => i !== '')));
}
}
export default Sina;

View File

@ -1,94 +0,0 @@
// Stocks
import BaseCommonCodeTransform from "@stocks/base/transforms/common-code";
// Utils
import { ERROR_API_CODE } from "@utils/constant";
import { SINA_SZ, SINA_SH, SINA_HK, SINA_US } from "@stocks/sina/utils/constant";
import { COMMON_SH, COMMON_SZ, COMMON_HK, COMMON_US } from "@stocks/base/utils/constant";
/**
*
*/
class SinaCommonCodeTransform extends BaseCommonCodeTransform {
/**
*
* @param code
*/
public transform(code: string): string {
if (code.indexOf(SINA_SZ) === 0) {
return this.SZTransform(code);
}
if (code.indexOf(SINA_SH) === 0) {
return this.SHTransform(code);
}
if (code.indexOf(SINA_HK) === 0) {
return this.HKTransform(code);
}
if (code.indexOf(SINA_US) === 0) {
return this.USTransform(code);
}
throw new Error(ERROR_API_CODE);
}
/**
*
* @param codes
*/
public transforms(codes: string[]): string[] {
return super.transforms(codes);
}
/**
*
* @param code
*/
public SZTransform(code: string): string {
if (code.indexOf(SINA_SZ) !== 0) {
throw new Error(ERROR_API_CODE);
}
return COMMON_SZ + code.replace(SINA_SZ, "");
}
/**
*
* @param code
*/
public SHTransform(code: string): string {
if (code.indexOf(SINA_SH) !== 0) {
throw new Error(ERROR_API_CODE);
}
return COMMON_SH + code.replace(SINA_SH, "");
}
/**
*
* @param code
*/
public HKTransform(code: string): string {
if (code.indexOf(SINA_HK) !== 0) {
throw new Error(ERROR_API_CODE);
}
return COMMON_HK + code.replace(SINA_HK, "");
}
/**
*
* @param code
*/
public USTransform(code: string): string {
if (code.indexOf(SINA_US) !== 0) {
throw new Error(ERROR_API_CODE);
}
return COMMON_US + code.replace(SINA_US, "").toLowerCase();
}
}
export default SinaCommonCodeTransform;

View File

@ -1,78 +0,0 @@
// Stocks
import BaseCommonCodeTransform from "@stocks/base/transforms/common-code";
// Utils
import { ERROR_COMMON_CODE } from "@utils/constant";
import { SINA_SZ, SINA_SH, SINA_HK, SINA_US } from "@stocks/sina/utils/constant";
import { COMMON_SH, COMMON_SZ, COMMON_HK, COMMON_US } from "@stocks/base/utils/constant";
/**
*
*/
class SinaCommonCodeTransform extends BaseCommonCodeTransform {
/**
*
* @param code
*/
public transform(code: string): string {
return super.transform(code);
}
/**
*
* @param codes
*/
public transforms(codes: string[]): string[] {
return super.transforms(codes);
}
/**
*
* @param code
*/
public SZTransform(code: string): string {
if (code.indexOf(COMMON_SZ) !== 0) {
throw new Error(ERROR_COMMON_CODE);
}
return SINA_SZ + code.replace(COMMON_SZ, "");
}
/**
*
* @param code
*/
public SHTransform(code: string): string {
if (code.indexOf(COMMON_SH) !== 0) {
throw new Error(ERROR_COMMON_CODE);
}
return SINA_SH + code.replace(COMMON_SH, "");
}
/**
*
* @param code
*/
public HKTransform(code: string): string {
if (code.indexOf(COMMON_HK) !== 0) {
throw new Error(ERROR_COMMON_CODE);
}
return SINA_HK + code.replace(COMMON_HK, "");
}
/**
*
* @param code
*/
public USTransform(code: string): string {
if (code.indexOf(COMMON_US) !== 0) {
throw new Error(ERROR_COMMON_CODE);
}
return SINA_US + code.replace(COMMON_US, "").toLowerCase();
}
}
export default SinaCommonCodeTransform;

View File

@ -1,143 +0,0 @@
// Stocks
import BaseStockTransform from "@stocks/base/transforms/stock";
// Utils
import { DEFAULT_STRING, DEFAULT_NUMBER } from "@utils/constant";
import { COMMON_SH, COMMON_SZ, COMMON_HK, COMMON_US } from "@stocks/base/utils/constant";
// Types
import Stock from "types/utils/stock";
/**
*
*/
class SinaStockTransform extends BaseStockTransform {
/**
*
*/
constructor(public code: string, public params: string[]) {
super();
}
/**
*
*/
getCode(): string {
return String(this.code).toUpperCase();
}
/**
*
*/
getName(): string {
switch (this.code.slice(0, 2)) {
case COMMON_SH:
return String(this.params[0] || DEFAULT_STRING);
case COMMON_SZ:
return String(this.params[0] || DEFAULT_STRING);
case COMMON_HK:
return String(this.params[1] || DEFAULT_STRING);
case COMMON_US:
return String(this.params[0] || DEFAULT_STRING);
default:
return DEFAULT_STRING;
}
}
/**
*
*/
getNow(): number {
switch (this.code.slice(0, 2)) {
case COMMON_SH:
return Number(this.params[3] || DEFAULT_NUMBER);
case COMMON_SZ:
return Number(this.params[3] || DEFAULT_NUMBER);
case COMMON_HK:
return Number(this.params[6] || DEFAULT_NUMBER);
case COMMON_US:
return Number(this.params[1] || DEFAULT_NUMBER);
default:
return DEFAULT_NUMBER;
}
}
/**
*
*/
getLow(): number {
switch (this.code.slice(0, 2)) {
case COMMON_SH:
return Number(this.params[5] || DEFAULT_NUMBER);
case COMMON_SZ:
return Number(this.params[5] || DEFAULT_NUMBER);
case COMMON_HK:
return Number(this.params[5] || DEFAULT_NUMBER);
case COMMON_US:
return Number(this.params[7] || DEFAULT_NUMBER);
default:
return DEFAULT_NUMBER;
}
}
/**
*
*/
getHigh(): number {
switch (this.code.slice(0, 2)) {
case COMMON_SH:
return Number(this.params[4] || DEFAULT_NUMBER);
case COMMON_SZ:
return Number(this.params[4] || DEFAULT_NUMBER);
case COMMON_HK:
return Number(this.params[4] || DEFAULT_NUMBER);
case COMMON_US:
return Number(this.params[6] || DEFAULT_NUMBER);
default:
return DEFAULT_NUMBER;
}
}
/**
*
*/
getYesterday(): number {
switch (this.code.slice(0, 2)) {
case COMMON_SH:
return Number(this.params[2] || DEFAULT_NUMBER);
case COMMON_SZ:
return Number(this.params[2] || DEFAULT_NUMBER);
case COMMON_HK:
return Number(this.params[3] || DEFAULT_NUMBER);
case COMMON_US:
return Number(this.params[26] || DEFAULT_NUMBER);
default:
return DEFAULT_NUMBER;
}
}
/**
*
*/
getPercent(): number {
return this.getNow() ? this.getNow() / this.getYesterday() - 1 : 0;
}
/**
*
*/
getStock(): Stock {
return {
code: this.getCode(),
name: this.getName(),
percent: this.getPercent(),
now: this.getNow(),
low: this.getLow(),
high: this.getHigh(),
yesterday: this.getYesterday(),
};
}
}
export default SinaStockTransform;

View File

@ -1,5 +0,0 @@
// 默认交易所常量
export const SINA_SZ = "sz"; // 深交所相关常量
export const SINA_SH = "sh"; // 上交所相关常量
export const SINA_HK = "hk"; // 港交所相关常量
export const SINA_US = "gb_"; // 美交所相关常量

View File

@ -1,117 +0,0 @@
// NPM
import { uniq } from "lodash";
// Stocks
import TencentStockTransform from "@stocks/tencent/transforms/stock";
import TencentCommonCodeTransform from "@stocks/tencent/transforms/common-code";
// Utils
import fetch from "@utils/fetch";
import iconv from "@utils/iconv";
import { DEFAULT_STOCK } from "@utils/constant";
import { COMMON_SH, COMMON_SZ, COMMON_US, COMMON_HK } from "@stocks/base/utils/constant";
// Types
import Stock from "types/utils/stock";
import StockApi from "types/stocks/index";
/**
*
*/
const Tencent: StockApi = {
/**
*
* @param code
*/
async getStock(code: string): Promise<Stock> {
const transform = (new TencentCommonCodeTransform).transform(code);
// 数据获取
const url = `https://qt.gtimg.cn/q=${transform}`;
const res = await fetch.get(url).responseType('blob');
const body = iconv.decode(res.body, "gbk");
const rows = body.split(";\n");
const row = rows[0];
if (!row.includes(transform)) {
return { ...DEFAULT_STOCK, code };
}
// 数据深解析
const [_, paramsUnformat] = row.split('=');
const params = paramsUnformat.replace('"', '').split("~");
const data = (new TencentStockTransform(code, params));
return data.getStock();
},
/**
*
* @param codes
*/
async getStocks(codes: string[]): Promise<Stock[]> {
codes = uniq(codes.filter(i => i !== ''));
// 无股票时返回空数组
if (codes.length === 0) {
return [];
}
const transforms = (new TencentCommonCodeTransform).transforms(codes);
// 数据获取
const url = `https://qt.gtimg.cn/q=${transforms.join(',')}`;
const res = await fetch.get(url).responseType('blob');
const body = iconv.decode(res.body, "gbk");
const rows: string[] = body.split(";\n");
return codes.map((code, index) => {
const transform = (new TencentCommonCodeTransform).transform(code);
if (!rows.find(row => row.includes(transform))) {
return { ...DEFAULT_STOCK, code };
}
// 数据深解析
const [_, paramsUnformat] = rows[index].split('=');
const params = paramsUnformat.replace('"', '').split("~");
const data = (new TencentStockTransform(code, params));
return data.getStock();
})
},
/**
*
* @param key
*/
async searchStocks(key: string): Promise<Stock[]> {
const url = `https://smartbox.gtimg.cn/s3/?v=2&t=all&c=1&q=${encodeURIComponent(key)}`;
const res = await fetch.get(url).responseType('blob');
const body = iconv.decode(res.body, "gbk");
const rows: string[] = body.replace('v_hint="', '').replace('"', "").split('^');
const codes: string[] = rows.map(row => {
const [type, code] = row.split('~');
switch (type) {
case 'sz':
return COMMON_SZ + code;
case 'sh':
return COMMON_SH + code;
case 'hk':
return COMMON_HK + code;
case 'us':
return COMMON_US + code.split('.')[0].toUpperCase();
default:
return '';
}
});
return await Tencent.getStocks(uniq(codes.filter(i => i !== '')));
}
}
export default Tencent;

View File

@ -1,94 +0,0 @@
// Stocks
import BaseApiCodeTransform from "@stocks/base/transforms/api-code";
// Utils
import { ERROR_API_CODE } from "@utils/constant";
import { COMMON_SH, COMMON_SZ, COMMON_HK, COMMON_US } from "@stocks/base/utils/constant";
import { TENCENT_SZ, TENCENT_SH, TENCENT_HK, TENCENT_US } from "@stocks/tencent/utils/constant";
/**
*
*/
class TencentApiCodeTransform extends BaseApiCodeTransform {
/**
*
* @param code
*/
public transform(code: string): string {
if (code.indexOf(TENCENT_SZ) === 0) {
return this.SZTransform(code);
}
if (code.indexOf(TENCENT_SH) === 0) {
return this.SHTransform(code);
}
if (code.indexOf(TENCENT_HK) === 0) {
return this.HKTransform(code);
}
if (code.indexOf(TENCENT_US) === 0) {
return this.USTransform(code);
}
throw new Error(ERROR_API_CODE);
}
/**
*
* @param codes
*/
public transforms(codes: string[]): string[] {
return super.transforms(codes);
}
/**
*
* @param code
*/
public SZTransform(code: string): string {
if (!code.includes(TENCENT_SZ)) {
throw new Error(ERROR_API_CODE);
}
return COMMON_SZ + code.replace(TENCENT_SZ, "");
}
/**
*
* @param code
*/
public SHTransform(code: string): string {
if (!code.includes(TENCENT_SH)) {
throw new Error(ERROR_API_CODE);
}
return COMMON_SH + code.replace(TENCENT_SH, "");
}
/**
*
* @param code
*/
public HKTransform(code: string): string {
if (!code.includes(TENCENT_HK)) {
throw new Error(ERROR_API_CODE);
}
return COMMON_HK + code.replace(TENCENT_HK, "");
}
/**
*
* @param code
*/
public USTransform(code: string): string {
if (!code.includes(TENCENT_US)) {
throw new Error(ERROR_API_CODE);
}
return COMMON_US + code.replace(TENCENT_US, "");
}
}
export default TencentApiCodeTransform;

View File

@ -1,85 +0,0 @@
// Stocks
import BaseCommonCodeTransform from "@stocks/base/transforms/common-code";
// Utils
import { ERROR_COMMON_CODE } from "@utils/constant";
import { COMMON_SH, COMMON_SZ, COMMON_HK, COMMON_US } from "@stocks/base/utils/constant";
import { TENCENT_SZ, TENCENT_SH, TENCENT_HK, TENCENT_US } from "@stocks/tencent/utils/constant";
/**
*
*/
class TencentCommonCodeTransform extends BaseCommonCodeTransform {
/**
*
*/
constructor() {
super();
}
/**
*
* @param code
*/
public transform(code: string): string {
return super.transform(code);
}
/**
*
* @param codes
*/
public transforms(codes: string[]): string[] {
return super.transforms(codes);
}
/**
*
* @param code
*/
public SZTransform(code: string): string {
if (!code.includes(COMMON_SZ)) {
throw new Error(ERROR_COMMON_CODE);
}
return TENCENT_SZ + code.replace(COMMON_SZ, "");
}
/**
*
* @param code
*/
public SHTransform(code: string): string {
if (!code.includes(COMMON_SH)) {
throw new Error(ERROR_COMMON_CODE);
}
return TENCENT_SH + code.replace(COMMON_SH, "");
}
/**
*
* @param code
*/
public HKTransform(code: string): string {
if (!code.includes(COMMON_HK)) {
throw new Error(ERROR_COMMON_CODE);
}
return TENCENT_HK + code.replace(COMMON_HK, "").toUpperCase();
}
/**
*
* @param code
*/
public USTransform(code: string): string {
if (!code.includes(COMMON_US)) {
throw new Error(ERROR_COMMON_CODE);
}
return TENCENT_US + code.replace(COMMON_US, "").toUpperCase();
}
}
export default TencentCommonCodeTransform;

View File

@ -1,87 +0,0 @@
// Stocks
import BaseStockTransform from "@stocks/base/transforms/stock";
// Utils
import { DEFAULT_STRING, DEFAULT_NUMBER } from "@utils/constant";
// Types
import Stock from "types/utils/stock";
/**
*
*/
class TencentStockTransform extends BaseStockTransform {
/**
*
*/
constructor(public code: string, public params: string[]) {
super();
}
/**
*
*/
getCode(): string {
return String(this.code).toUpperCase();
}
/**
*
*/
getName(): string {
return String(this.params[1] || DEFAULT_STRING);
}
/**
*
*/
getNow(): number {
return Number(this.params[3] || DEFAULT_NUMBER);
}
/**
*
*/
getLow(): number {
return Number(this.params[34] || DEFAULT_NUMBER);
}
/**
*
*/
getHigh(): number {
return Number(this.params[33] || DEFAULT_NUMBER);
}
/**
*
*/
getYesterday(): number {
return Number(this.params[4] || DEFAULT_NUMBER);
}
/**
*
*/
getPercent(): number {
return this.getNow() ? this.getNow() / this.getYesterday() - 1 : 0;
}
/**
*
*/
getStock(): Stock {
return {
code: this.getCode(),
name: this.getName(),
percent: this.getPercent(),
now: this.getNow(),
low: this.getLow(),
high: this.getHigh(),
yesterday: this.getYesterday(),
};
}
}
export default TencentStockTransform;

View File

@ -1,5 +0,0 @@
// 默认交易所常量
export const TENCENT_SZ = "sz"; // 深交所相关常量
export const TENCENT_SH = "sh"; // 上交所相关常量
export const TENCENT_HK = "hk"; // 港交所相关常量
export const TENCENT_US = "us"; // 美交所相关常量

View File

@ -1,151 +0,0 @@
// NPM
import { uniq } from 'lodash';
// Stocks
import XueqiuStockTransform from "@stocks/xueqiu/transforms/stock";
import XueqiuCommonCodeTransform from "@stocks/xueqiu/transforms/common-code";
// Utils
import fetch from "@utils/fetch";
import { DEFAULT_STOCK } from "@utils/constant";
import { COMMON_SZ, COMMON_SH, COMMON_HK, COMMON_US } from '@stocks/base/utils/constant';
// Types
import Stock from "types/utils/stock";
import StockApi from "types/stocks/index";
import Dictionary from "types/utils/dictionary";
let token: string = '';
/**
*
*/
const Xueqiu: StockApi & { getToken(): Promise<string> } = {
/**
* Token
*/
async getToken(): Promise<string> {
if (token !== '') return token;
const res = await fetch.get('https://xueqiu.com/');
const cookies: string[] = res.headers['set-cookie'];
const param: string = cookies.filter(key => key.includes('xq_a_token'))[0] || '';
token = param.split(';')[0] || '';
return token;
},
/**
*
* @param code
*/
async getStock(code: string): Promise<Stock> {
const token = await this.getToken();
const transform = (new XueqiuCommonCodeTransform).transform(code);
// 数据获取
const url = `https://stock.xueqiu.com/v5/stock/quote.json?symbol=${transform}`;
const res = await fetch.get(url).set('Cookie', token);
const body = JSON.parse(res.text);
const row: Dictionary<number | string> = body.data.quote;
// 数据深解析
const params = row;
const data = (new XueqiuStockTransform(code, params));
return params ? data.getStock() : { ...DEFAULT_STOCK, code };
},
/**
*
* @param codes
*/
async getStocks(codes: string[]): Promise<Stock[]> {
codes = uniq(codes.filter(i => i !== ''));
// 无股票时返回空数组
if (codes.length === 0) {
return [];
}
const token = await this.getToken();
const transforms = (new XueqiuCommonCodeTransform).transforms(codes);
// 数据获取
const url = `https://stock.xueqiu.com/v5/stock/batch/quote.json?symbol=${transforms.join(',')}`;
const res = await fetch.get(url).set('Cookie', token);
const body = JSON.parse(res.text);
const rows: Dictionary<Dictionary<number | string>>[] = body.data.items;
return codes.map(code => {
// 数据深解析
const transform = (new XueqiuCommonCodeTransform).transform(code);
const params = rows.find(i => {
if (!i.quote) {
return false;
}
if (i.market.region === 'US') {
return i.quote.code === transform;
}
if (i.market.region === 'CN') {
return i.quote.symbol === transform;
}
if (i.market.region === 'HK') {
return i.market.region + i.quote.code === transform;
}
}) || null;
if (!params) {
return { ...DEFAULT_STOCK, code };
}
const data = (new XueqiuStockTransform(code, params.quote));
return data.getStock();
});
},
/**
*
* @param key
*/
async searchStocks(key: string): Promise<Stock[]> {
const token = await this.getToken();
// 数据获取
const url = `https://xueqiu.com/stock/search.json?code=${encodeURIComponent(key)}`;
const res = await fetch.get(url).set('Cookie', token);
const body = JSON.parse(res.text);
const rows: Dictionary<string>[] = body.stocks;
let codes: string[] = [];
for (let i = 0; i < rows.length; i++) {
let code: string = rows[i].code;
if (code.indexOf('SZ') === 0) {
code = code.replace('SZ', '');
codes = [...codes, COMMON_SZ + code];
continue;
}
if (code.indexOf('SH') === 0) {
code = code.replace('SH', '');
codes = [...codes, COMMON_SH + code];
continue;
}
codes = [...codes, COMMON_HK + code, COMMON_US + code];
}
return await Xueqiu.getStocks(uniq(codes.filter(i => i !== '')));
}
}
export default Xueqiu;

View File

@ -1,90 +0,0 @@
// Stocks
import BaseApiCodeTransform from "@stocks/base/transforms/api-code";
// Utils
import { ERROR_API_CODE } from "@utils/constant";
import { COMMON_SH, COMMON_SZ, COMMON_HK, COMMON_US } from "@stocks/base/utils/constant";
import { XUEQIU_SZ, XUEQIU_SH, XUEQIU_HK, XUEQIU_US } from "@stocks/xueqiu/utils/constant";
/**
*
*/
class XueqiuApiCodeTransform extends BaseApiCodeTransform {
/**
*
* @param code
*/
public transform(code: string): string {
if (code.includes(XUEQIU_SZ)) {
return this.SZTransform(code);
}
if (code.includes(XUEQIU_SH)) {
return this.SHTransform(code);
}
if (code.includes(XUEQIU_HK)) {
return this.HKTransform(code);
}
return this.USTransform(code);
}
/**
*
* @param codes
*/
public transforms(codes: string[]): string[] {
return super.transforms(codes);
}
/**
*
* @param code
*/
public SZTransform(code: string): string {
if (!code.includes(XUEQIU_SZ)) {
throw new Error(ERROR_API_CODE);
}
return COMMON_SZ + code.replace(XUEQIU_SZ, "");
}
/**
*
* @param code
*/
public SHTransform(code: string): string {
if (!code.includes(XUEQIU_SH)) {
throw new Error(ERROR_API_CODE);
}
return COMMON_SH + code.replace(XUEQIU_SH, "");
}
/**
*
* @param code
*/
public HKTransform(code: string): string {
if (!code.includes(XUEQIU_HK)) {
throw new Error(ERROR_API_CODE);
}
return COMMON_HK + code.replace(XUEQIU_HK, "");
}
/**
*
* @param code
*/
public USTransform(code: string): string {
if (code.includes(XUEQIU_SZ) || code.includes(XUEQIU_SH) || code.includes(XUEQIU_HK)) {
throw new Error(ERROR_API_CODE);
}
return COMMON_US + code.replace(XUEQIU_US, "");
}
}
export default XueqiuApiCodeTransform;

View File

@ -1,78 +0,0 @@
// Stocks
import BaseCommonCodeTransform from "@stocks/base/transforms/common-code";
// Utils
import { ERROR_COMMON_CODE } from "@utils/constant";
import { COMMON_SH, COMMON_SZ, COMMON_HK, COMMON_US } from "@stocks/base/utils/constant";
import { XUEQIU_SZ, XUEQIU_SH, XUEQIU_HK, XUEQIU_US } from "@stocks/xueqiu/utils/constant";
/**
*
*/
class XueqiuCommonCodeTransform extends BaseCommonCodeTransform {
/**
*
* @param code
*/
public transform(code: string): string {
return super.transform(code);
}
/**
*
* @param codes
*/
public transforms(codes: string[]): string[] {
return super.transforms(codes);
}
/**
*
* @param code
*/
public SZTransform(code: string): string {
if (!code.includes(COMMON_SZ)) {
throw new Error(ERROR_COMMON_CODE);
}
return XUEQIU_SZ + code.replace(COMMON_SZ, "");
}
/**
*
* @param code
*/
public SHTransform(code: string): string {
if (!code.includes(COMMON_SH)) {
throw new Error(ERROR_COMMON_CODE);
}
return XUEQIU_SH + code.replace(COMMON_SH, "");
}
/**
*
* @param code
*/
public HKTransform(code: string): string {
if (!code.includes(COMMON_HK)) {
throw new Error(ERROR_COMMON_CODE);
}
return XUEQIU_HK + code.replace(COMMON_HK, "");
}
/**
*
* @param code
*/
public USTransform(code: string): string {
if (!code.includes(COMMON_US)) {
throw new Error(ERROR_COMMON_CODE);
}
return XUEQIU_US + code.replace(COMMON_US, "");
}
}
export default XueqiuCommonCodeTransform;

View File

@ -1,88 +0,0 @@
// Stocks
import BaseStockTransform from "@stocks/base/transforms/stock";
// Utils
import { DEFAULT_STRING, DEFAULT_NUMBER } from "@utils/constant";
// Types
import Stock from "types/utils/stock";
import Dictionary from "types/utils/dictionary";
/**
*
*/
class XueqiuStockTransform extends BaseStockTransform {
/**
*
*/
constructor(public code: string, public params: Dictionary<number | string>) {
super();
}
/**
*
*/
getCode(): string {
return String(this.code).toUpperCase();
}
/**
*
*/
getName(): string {
return String(this.params.name || DEFAULT_STRING);
}
/**
*
*/
getNow(): number {
return Number(this.params.current || DEFAULT_NUMBER);
}
/**
*
*/
getLow(): number {
return Number(this.params.low || DEFAULT_NUMBER);
}
/**
*
*/
getHigh(): number {
return Number(this.params.high || DEFAULT_NUMBER);
}
/**
*
*/
getYesterday(): number {
return Number(this.params.last_close || DEFAULT_NUMBER);
}
/**
*
*/
getPercent(): number {
return this.getNow() ? this.getNow() / this.getYesterday() - 1 : 0;
}
/**
*
*/
getStock(): Stock {
return {
code: this.getCode(),
name: this.getName(),
percent: this.getPercent(),
now: this.getNow(),
low: this.getLow(),
high: this.getHigh(),
yesterday: this.getYesterday(),
};
}
}
export default XueqiuStockTransform;

View File

@ -1,5 +0,0 @@
// 默认交易所常量
export const XUEQIU_SZ = "SZ"; // 深交所相关常量
export const XUEQIU_SH = "SH"; // 上交所相关常量
export const XUEQIU_HK = "HK"; // 港交所相关常量
export const XUEQIU_US = ""; // 美交所相关常量

View File

@ -1,44 +0,0 @@
// 默认股票名称常量
export const DEFAULT_NUMBER = 0;
export const DEFAULT_STRING = "---";
// 默认错误提示常量
export const ERROR_API_CODE = "请检查股票代码是否正确";
export const ERROR_COMMON_CODE = "请检查统一代码是否正确";
export const ERROR_UNDEFINED_GET_STOCK = "未实现获取股票数据";
export const ERROR_UNDEFINED_GET_STOCKS = "未实现获取股票数据组";
export const ERROR_UNDEFINED_SEARCH_STOCK = "未实现搜索股票代码";
export const ERROR_UNDEFINED_COMMON_CODE = "未实现统一代码转换股票代码";
export const ERROR_UNDEFINED_SZ_COMMON_CODE = "未实现深交所统一代码转换股票代码";
export const ERROR_UNDEFINED_SH_COMMON_CODE = "未实现上交所统一代码转换股票代码";
export const ERROR_UNDEFINED_HK_COMMON_CODE = "未实现港交所统一代码转换股票代码";
export const ERROR_UNDEFINED_US_COMMON_CODE = "未实现美交所统一代码转换股票代码";
export const ERROR_UNDEFINED_API_CODE = "未实现股票代码转换统一代码";
export const ERROR_UNDEFINED_API_CODES = "未实现股票代码组转换统一代码组";
export const ERROR_UNDEFINED_SZ_API_CODE = "未实现深交所股票代码转换统一代码";
export const ERROR_UNDEFINED_SH_API_CODE = "未实现上交所股票代码转换统一代码";
export const ERROR_UNDEFINED_HK_API_CODE = "未实现港交所股票代码转换统一代码";
export const ERROR_UNDEFINED_US_API_CODE = "未实现美交所股票代码转换统一代码";
export const ERROR_UNDEFINED_GET_CODE = '未实现获取代码';
export const ERROR_UNDEFINED_GET_NAME = '未实现获取名称';
export const ERROR_UNDEFINED_GET_NOW = '未实现获取现价';
export const ERROR_UNDEFINED_GET_LOW = '未实现获取最低价';
export const ERROR_UNDEFINED_GET_HIGH = '未实现获取最高价';
export const ERROR_UNDEFINED_GET_PERCENT = '未实现获取涨跌';
export const ERROR_UNDEFINED_GET_YESTERDAY = '未实现获取昨日收盘价';
// 默认股票数据常量
export const DEFAULT_STOCK = {
code: DEFAULT_STRING,
name: DEFAULT_STRING,
percent: DEFAULT_NUMBER,
now: DEFAULT_NUMBER,
low: DEFAULT_NUMBER,
high: DEFAULT_NUMBER,
yesterday: DEFAULT_NUMBER,
};

View File

@ -1,3 +0,0 @@
const superagent = require('superagent');
export default superagent;

View File

@ -1,3 +0,0 @@
const iconv = require("iconv-lite");
export default iconv;

View File

@ -1,28 +0,0 @@
// Stock
const Base = require("stocks/base").default;
describe("【基础】股票代码接口", () => {
const {
ERROR_UNDEFINED_GET_STOCK,
ERROR_UNDEFINED_GET_STOCKS,
ERROR_UNDEFINED_SEARCH_STOCK,
} = require("utils/constant");
it("需要获取的股票代码", async () => {
await expect(Base.getStock("SZ000000"))
.rejects
.toThrow(new Error(ERROR_UNDEFINED_GET_STOCK));
});
it("需要获取的股票代码组", async () => {
await expect(Base.getStocks(["SZ000000"]))
.rejects
.toThrow(new Error(ERROR_UNDEFINED_GET_STOCKS));
});
it("搜索股票代码", async () => {
await expect(Base.searchStocks("510500"))
.rejects
.toThrow(new Error(ERROR_UNDEFINED_SEARCH_STOCK));
});
});

View File

@ -1,66 +0,0 @@
// Stock
const BaseApiCodeTransform = require("stocks/base/transforms/api-code").default;
describe("【基础】股票代码转换统一代码", () => {
const {
ERROR_API_CODE,
ERROR_UNDEFINED_SZ_API_CODE,
ERROR_UNDEFINED_SH_API_CODE,
ERROR_UNDEFINED_HK_API_CODE,
ERROR_UNDEFINED_US_API_CODE
} = require("utils/constant");
it("深交所股票代码转换统一代码", async () => {
expect(() => (new BaseApiCodeTransform()).SZTransform("SZ000000"))
.toThrow(new Error(ERROR_UNDEFINED_SZ_API_CODE));
});
it("上交所股票代码转换统一代码", async () => {
expect(() => (new BaseApiCodeTransform()).SHTransform("SH000000"))
.toThrow(new Error(ERROR_UNDEFINED_SH_API_CODE));
});
it("港交所股票代码转换统一代码", async () => {
expect(() => new BaseApiCodeTransform().HKTransform("HK000000"))
.toThrow(new Error(ERROR_UNDEFINED_HK_API_CODE));
});
it("美交所股票代码转换统一代码", async () => {
expect(() => (new BaseApiCodeTransform()).USTransform("US000000"))
.toThrow(new Error(ERROR_UNDEFINED_US_API_CODE));
});
it("交易所股票代码转换统一代码", async () => {
expect(() => (new BaseApiCodeTransform()).transform("000000"))
.toThrow(new Error(ERROR_API_CODE));
expect(() => (new BaseApiCodeTransform()).transform("SZ000000"))
.toThrow(new Error(ERROR_UNDEFINED_SZ_API_CODE));
expect(() => (new BaseApiCodeTransform()).transform("SH000000"))
.toThrow(new Error(ERROR_UNDEFINED_SH_API_CODE));
expect(() => (new BaseApiCodeTransform()).transform("HK000000"))
.toThrow(new Error(ERROR_UNDEFINED_HK_API_CODE));
expect(() => (new BaseApiCodeTransform()).transform("US000000"))
.toThrow(new Error(ERROR_UNDEFINED_US_API_CODE));
});
it("交易所股票代码组转换统一代码组", async () => {
expect(() => (new BaseApiCodeTransform()).transforms(["000000"]))
.toThrow(new Error(ERROR_API_CODE));
expect(() => (new BaseApiCodeTransform()).transforms(["SZ000000"]))
.toThrow(new Error(ERROR_UNDEFINED_SZ_API_CODE));
expect(() => (new BaseApiCodeTransform()).transforms(["SH000000"]))
.toThrow(new Error(ERROR_UNDEFINED_SH_API_CODE));
expect(() => (new BaseApiCodeTransform()).transforms(["HK000000"]))
.toThrow(new Error(ERROR_UNDEFINED_HK_API_CODE));
expect(() => (new BaseApiCodeTransform()).transforms(["US000000"]))
.toThrow(new Error(ERROR_UNDEFINED_US_API_CODE));
});
});

View File

@ -1,66 +0,0 @@
// Stock
const BaseCommonCodeTransform = require("stocks/base/transforms/common-code").default;
describe("【基础】统一代码转换股票代码", () => {
const {
ERROR_COMMON_CODE,
ERROR_UNDEFINED_SZ_COMMON_CODE,
ERROR_UNDEFINED_SH_COMMON_CODE,
ERROR_UNDEFINED_HK_COMMON_CODE,
ERROR_UNDEFINED_US_COMMON_CODE
} = require("utils/constant");
it("深交所统一代码转换股票代码", async () => {
expect(() => (new BaseCommonCodeTransform()).SZTransform("SZ000000"))
.toThrow(new Error(ERROR_UNDEFINED_SZ_COMMON_CODE));
});
it("上交所统一代码转换股票代码", async () => {
expect(() => (new BaseCommonCodeTransform()).SHTransform("SH000000"))
.toThrow(new Error(ERROR_UNDEFINED_SH_COMMON_CODE));
});
it("港交所统一代码转换股票代码", async () => {
expect(() => new BaseCommonCodeTransform().HKTransform("HK000000"))
.toThrow(new Error(ERROR_UNDEFINED_HK_COMMON_CODE));
});
it("美交所统一代码转换股票代码", async () => {
expect(() => (new BaseCommonCodeTransform()).USTransform("US000000"))
.toThrow(new Error(ERROR_UNDEFINED_US_COMMON_CODE));
});
it("交易所统一代码转换股票代码", async () => {
expect(() => (new BaseCommonCodeTransform()).transform("000000"))
.toThrow(new Error(ERROR_COMMON_CODE));
expect(() => (new BaseCommonCodeTransform()).transform("SZ000000"))
.toThrow(new Error(ERROR_UNDEFINED_SZ_COMMON_CODE));
expect(() => (new BaseCommonCodeTransform()).transform("SH000000"))
.toThrow(new Error(ERROR_UNDEFINED_SH_COMMON_CODE));
expect(() => (new BaseCommonCodeTransform()).transform("HK000000"))
.toThrow(new Error(ERROR_UNDEFINED_HK_COMMON_CODE));
expect(() => (new BaseCommonCodeTransform()).transform("US000000"))
.toThrow(new Error(ERROR_UNDEFINED_US_COMMON_CODE));
});
it("交易所统一代码组转换股票代码组", async () => {
expect(() => (new BaseCommonCodeTransform()).transforms(["000000"]))
.toThrow(new Error(ERROR_COMMON_CODE));
expect(() => (new BaseCommonCodeTransform()).transforms(["SZ000000"]))
.toThrow(new Error(ERROR_UNDEFINED_SZ_COMMON_CODE));
expect(() => (new BaseCommonCodeTransform()).transforms(["SH000000"]))
.toThrow(new Error("未实现上交所统一代码转换股票代码"));
expect(() => (new BaseCommonCodeTransform()).transforms(["HK000000"]))
.toThrow(new Error(ERROR_UNDEFINED_HK_COMMON_CODE));
expect(() => (new BaseCommonCodeTransform()).transforms(["US000000"]))
.toThrow(new Error(ERROR_UNDEFINED_US_COMMON_CODE));
});
});

View File

@ -1,55 +0,0 @@
// Stock
const BaseStockTransform = require("stocks/base/transforms/stock").default;
describe("【基础】股票数据转换测试", () => {
const {
ERROR_UNDEFINED_GET_CODE,
ERROR_UNDEFINED_GET_NAME,
ERROR_UNDEFINED_GET_NOW,
ERROR_UNDEFINED_GET_LOW,
ERROR_UNDEFINED_GET_HIGH,
ERROR_UNDEFINED_GET_STOCK,
ERROR_UNDEFINED_GET_PERCENT,
ERROR_UNDEFINED_GET_YESTERDAY,
} = require("utils/constant");
it("获取股票代码", async () => {
expect(() => (new BaseStockTransform()).getCode())
.toThrow(new Error(ERROR_UNDEFINED_GET_CODE));
});
it("获取股票名称", async () => {
expect(() => (new BaseStockTransform()).getName())
.toThrow(new Error(ERROR_UNDEFINED_GET_NAME));
});
it("获取股票现价", async () => {
expect(() => (new BaseStockTransform()).getNow())
.toThrow(new Error(ERROR_UNDEFINED_GET_NOW));
});
it("获取股票最低价", async () => {
expect(() => (new BaseStockTransform()).getLow())
.toThrow(new Error(ERROR_UNDEFINED_GET_LOW));
});
it("获取股票最高价", async () => {
expect(() => (new BaseStockTransform()).getHigh())
.toThrow(new Error(ERROR_UNDEFINED_GET_HIGH));
});
it("获取股票昨日收盘价", async () => {
expect(() => (new BaseStockTransform()).getYesterday())
.toThrow(new Error(ERROR_UNDEFINED_GET_YESTERDAY));
});
it("获取股票涨跌", async () => {
expect(() => (new BaseStockTransform()).getPercent())
.toThrow(new Error(ERROR_UNDEFINED_GET_PERCENT));
});
it("获取股票数据", async () => {
expect(() => (new BaseStockTransform()).getStock())
.toThrow(new Error(ERROR_UNDEFINED_GET_STOCK));
});
});

View File

@ -1,38 +0,0 @@
// Stock
const Netease = require("stocks/netease").default;
describe("【网易】股票代码接口", () => {
it("需要获取的股票代码", async () => {
await expect(Netease.getStock("SH510500"))
.resolves
.toMatchObject({ code: "SH510500", name: "500ETF" });
await expect(Netease.getStock("SZ510500"))
.resolves
.toMatchObject({ code: "SZ510500", name: "---" });
});
it("需要获取的股票代码组", async () => {
await expect(Netease.getStocks(["SH510500"]))
.resolves
.toEqual(expect.arrayContaining([expect.objectContaining({ code: "SH510500", name: "500ETF" })]));
await expect(Netease.getStocks(["SZ510500"]))
.resolves
.toEqual(expect.arrayContaining([expect.objectContaining({ code: "SZ510500", name: "---" })]));
await expect(Netease.getStocks([]))
.resolves
.toEqual([]);
});
it("搜索股票代码", async () => {
await expect(Netease.searchStocks("格力电器"))
.resolves
.toEqual(expect.arrayContaining([expect.objectContaining({ code: "SZ000651", name: "格力电器" })]));
await expect(Netease.searchStocks("贵州茅台"))
.resolves
.toEqual(expect.arrayContaining([expect.objectContaining({ code: "SH600519", name: "贵州茅台" })]));
});
});

View File

@ -1,74 +0,0 @@
// Stock
const NeteaseApiCodeTransform = require("stocks/netease/transforms/api-code").default;
describe("【网易】股票代码转换统一代码", () => {
const {
ERROR_API_CODE,
} = require("utils/constant");
it("深交所股票代码转换统一代码", async () => {
expect(() => (new NeteaseApiCodeTransform()).SZTransform("STOCKAPI"))
.toThrow(new Error(ERROR_API_CODE));
expect((new NeteaseApiCodeTransform()).SZTransform("1000000"))
.toBe("SZ000000");
});
it("上交所股票代码转换统一代码", async () => {
expect(() => (new NeteaseApiCodeTransform()).SHTransform("STOCKAPI"))
.toThrow(new Error(ERROR_API_CODE));
expect((new NeteaseApiCodeTransform()).SHTransform("0000000"))
.toBe("SH000000");
});
it("港交所股票代码转换统一代码", async () => {
expect(() => (new NeteaseApiCodeTransform()).HKTransform("STOCKAPI"))
.toThrow(new Error(ERROR_API_CODE));
expect((new NeteaseApiCodeTransform()).HKTransform("hk000000"))
.toBe("HK000000");
});
it("美交所股票代码转换统一代码", async () => {
expect(() => (new NeteaseApiCodeTransform()).USTransform("STOCKAPI"))
.toThrow(new Error(ERROR_API_CODE));
expect((new NeteaseApiCodeTransform()).USTransform("US_000000"))
.toBe("US000000");
});
it("交易所股票代码转换统一代码", async () => {
expect((new NeteaseApiCodeTransform()).transform("1000000"))
.toBe("SZ000000");
expect((new NeteaseApiCodeTransform()).transform("0000000"))
.toBe("SH000000");
expect((new NeteaseApiCodeTransform()).transform("hk000000"))
.toBe("HK000000");
expect((new NeteaseApiCodeTransform()).transform("US_000000"))
.toBe("US000000");
expect(() => (new NeteaseApiCodeTransform()).transform("STOCKAPI"))
.toThrow(new Error(ERROR_API_CODE));
});
it("交易所股票代码组转换统一代码组", async () => {
expect((new NeteaseApiCodeTransform()).transforms(["1000000"]))
.toStrictEqual(["SZ000000"]);
expect((new NeteaseApiCodeTransform()).transforms(["0000000"]))
.toStrictEqual(["SH000000"]);
expect((new NeteaseApiCodeTransform()).transforms(["hk000000"]))
.toStrictEqual(["HK000000"]);
expect((new NeteaseApiCodeTransform()).transforms(["US_000000"]))
.toStrictEqual(["US000000"]);
expect(() => (new NeteaseApiCodeTransform()).transforms(["STOCKAPI"]))
.toThrow(new Error(ERROR_API_CODE));
});
});

View File

@ -1,74 +0,0 @@
// Stock
const NeteaseCommonCodeTransform = require("stocks/netease/transforms/common-code").default;
describe("【网易】统一代码转换股票代码", () => {
const {
ERROR_COMMON_CODE,
} = require("utils/constant");
it("深交所统一代码转换股票代码", async () => {
expect(() => (new NeteaseCommonCodeTransform()).SZTransform("STOCKAPI"))
.toThrow(new Error(ERROR_COMMON_CODE));
expect((new NeteaseCommonCodeTransform()).SZTransform("SZ000000"))
.toBe("1000000");
});
it("上交所统一代码转换股票代码", async () => {
expect(() => (new NeteaseCommonCodeTransform()).SHTransform("STOCKAPI"))
.toThrow(new Error(ERROR_COMMON_CODE));
expect((new NeteaseCommonCodeTransform()).SHTransform("SH000000"))
.toBe("0000000");
});
it("港交所统一代码转换股票代码", async () => {
expect(() => (new NeteaseCommonCodeTransform()).HKTransform("STOCKAPI"))
.toThrow(new Error(ERROR_COMMON_CODE));
expect((new NeteaseCommonCodeTransform()).HKTransform("HK000000"))
.toBe("hk000000");
});
it("美交所统一代码转换股票代码", async () => {
expect(() => (new NeteaseCommonCodeTransform()).USTransform("STOCKAPI"))
.toThrow(new Error(ERROR_COMMON_CODE));
expect((new NeteaseCommonCodeTransform()).USTransform("US000000"))
.toBe("US_000000");
});
it("交易所统一代码转换股票代码", async () => {
expect((new NeteaseCommonCodeTransform()).transform("SZ000000"))
.toBe("1000000");
expect((new NeteaseCommonCodeTransform()).transform("SH000000"))
.toBe("0000000");
expect((new NeteaseCommonCodeTransform()).transform("HK000000"))
.toBe("hk000000");
expect((new NeteaseCommonCodeTransform()).transform("US000000"))
.toBe("US_000000");
expect(() => (new NeteaseCommonCodeTransform()).transform("STOCKAPI"))
.toThrow(new Error(ERROR_COMMON_CODE));
});
it("交易所统一代码组转换股票代码组", async () => {
expect((new NeteaseCommonCodeTransform()).transforms(["SZ000000"]))
.toStrictEqual(["1000000"]);
expect((new NeteaseCommonCodeTransform()).transforms(["SH000000"]))
.toStrictEqual(["0000000"]);
expect((new NeteaseCommonCodeTransform()).transforms(["HK000000"]))
.toStrictEqual(["hk000000"]);
expect((new NeteaseCommonCodeTransform()).transforms(["US000000"]))
.toStrictEqual(["US_000000"]);
expect(() => (new NeteaseCommonCodeTransform()).transforms(["STOCKAPI"]))
.toThrow(new Error(ERROR_COMMON_CODE));
});
});

View File

@ -1,50 +0,0 @@
// Stock
const NeteaseStockTransform = require("stocks/netease/transforms/stock").default;
describe("【网易】股票数据转换测试", () => {
const code = 'SH510500';
const body = `topstock({"0510500":{"code": "0510500", "precloseiopv": 7.152, "percent": 0.010491, "high": 7.28, "askvol3": 32300, "askvol2": 88400, "askvol5": 19000, "askvol4": 572800, "iopv": 7.226, "price": 7.224, "open": 7.147, "bid5": 7.22, "bid4": 7.221, "bid3": 7.222, "bid2": 7.223, "bid1": 7.224, "low": 7.085, "updown": 0.075, "type": "SH", "symbol": "510500", "status": 0, "ask4": 7.228, "bidvol3": 37000, "bidvol2": 32900, "bidvol1": 6300, "update": "2020/07/31 15:59:59", "bidvol5": 14300, "bidvol4": 28600, "yestclose": 7.149, "askvol1": 389300, "ask5": 7.229, "volume": 272478144, "ask1": 7.225, "name": "500ETF", "ask3": 7.227, "ask2": 7.226, "arrow": "\u2191", "time": "2020/07/31 15:59:58", "turnover": 1964297124} });`;
const items = JSON.parse(body.replace(/\(|\)|;|(topstock)/g, ''));
const params = items['0510500'];
it("获取股票代码", async () => {
expect(new NeteaseStockTransform(code, params).getCode())
.toBe('SH510500');
});
it("获取股票名称", async () => {
expect(new NeteaseStockTransform(code, params).getName())
.toBe('500ETF');
});
it("获取股票现价", async () => {
expect(new NeteaseStockTransform(code, params).getNow())
.toBe(7.224);
});
it("获取股票最低价", async () => {
expect(new NeteaseStockTransform(code, params).getLow())
.toBe(7.085);
});
it("获取股票最高价", async () => {
expect(new NeteaseStockTransform(code, params).getHigh())
.toBe(7.28);
});
it("获取股票昨日收盘价", async () => {
expect(new NeteaseStockTransform(code, params).getYesterday())
.toBe(7.149);
});
it("获取股票涨跌", async () => {
expect(new NeteaseStockTransform(code, params).getPercent())
.toBe(7.224 / 7.149 - 1);
});
it("获取股票数据", async () => {
expect(new NeteaseStockTransform(code, params).getStock())
.toStrictEqual({ "code": "SH510500", "high": 7.28, "low": 7.085, "name": "500ETF", "now": 7.224, "percent": 7.224 / 7.149 - 1, "yesterday": 7.149 });
});
});

View File

@ -1,44 +0,0 @@
// Stock
const Sina = require("stocks/sina").default;
describe("【新浪】股票代码接口", () => {
it("需要获取的股票代码", async () => {
await expect(Sina.getStock("SH510500"))
.resolves
.toMatchObject({ code: "SH510500", name: "500ETF" });
await expect(Sina.getStock("SZ510500"))
.resolves
.toMatchObject({ code: "SZ510500", name: "---" });
});
it("需要获取的股票代码组", async () => {
await expect(Sina.getStocks(["SH510500"]))
.resolves
.toEqual(expect.arrayContaining([expect.objectContaining({ code: "SH510500", name: "500ETF" })]));
await expect(Sina.getStocks(["SZ510500"]))
.resolves
.toEqual(expect.arrayContaining([expect.objectContaining({ code: "SZ510500", name: "---" })]));
await expect(Sina.getStocks([]))
.resolves
.toEqual([]);
});
it("搜索股票代码", async () => {
await expect(Sina.searchStocks("格力电器"))
.resolves
.toEqual(expect.arrayContaining([expect.objectContaining({ code: "SZ000651", name: "格力电器" })]));
await expect(Sina.searchStocks("贵州茅台"))
.resolves
.toEqual(expect.arrayContaining([expect.objectContaining({ code: "SH600519", name: "贵州茅台" })]));
await expect(Sina.searchStocks("安踏体育"))
.resolves
.toEqual(expect.arrayContaining([
expect.objectContaining({ code: "HK02020", name: "安踏体育" }),
expect.objectContaining({ code: "USANPDF", name: "安踏" }),
]));
});
});

View File

@ -1,74 +0,0 @@
// Stock
const SinaApiCodeTransform = require("stocks/sina/transforms/api-code").default;
describe("【新浪】股票代码转换统一代码", () => {
const {
ERROR_API_CODE,
} = require("utils/constant");
it("深交所股票代码转换统一代码", async () => {
expect(() => (new SinaApiCodeTransform()).SZTransform("STOCKAPI"))
.toThrow(new Error(ERROR_API_CODE));
expect((new SinaApiCodeTransform()).SZTransform("sz000000"))
.toBe("SZ000000");
});
it("上交所股票代码转换统一代码", async () => {
expect(() => (new SinaApiCodeTransform()).SHTransform("STOCKAPI"))
.toThrow(new Error(ERROR_API_CODE));
expect((new SinaApiCodeTransform()).SHTransform("sh000000"))
.toBe("SH000000");
});
it("港交所股票代码转换统一代码", async () => {
expect(() => (new SinaApiCodeTransform()).HKTransform("STOCKAPI"))
.toThrow(new Error(ERROR_API_CODE));
expect((new SinaApiCodeTransform()).HKTransform("hk000000"))
.toBe("HK000000");
});
it("美交所股票代码转换统一代码", async () => {
expect(() => (new SinaApiCodeTransform()).USTransform("STOCKAPI"))
.toThrow(new Error(ERROR_API_CODE));
expect((new SinaApiCodeTransform()).USTransform("gb_000000"))
.toBe("US000000");
});
it("交易所股票代码转换统一代码", async () => {
expect((new SinaApiCodeTransform()).transform("sz000000"))
.toBe("SZ000000");
expect((new SinaApiCodeTransform()).transform("sh000000"))
.toBe("SH000000");
expect((new SinaApiCodeTransform()).transform("hk000000"))
.toBe("HK000000");
expect((new SinaApiCodeTransform()).transform("gb_000000"))
.toBe("US000000");
expect(() => (new SinaApiCodeTransform()).transform("STOCKAPI"))
.toThrow(new Error(ERROR_API_CODE));
});
it("交易所股票代码转换统一代码", async () => {
expect((new SinaApiCodeTransform()).transforms(["sz000000"]))
.toStrictEqual(["SZ000000"]);
expect((new SinaApiCodeTransform()).transforms(["sh000000"]))
.toStrictEqual(["SH000000"]);
expect((new SinaApiCodeTransform()).transforms(["hk000000"]))
.toStrictEqual(["HK000000"]);
expect((new SinaApiCodeTransform()).transforms(["gb_000000"]))
.toStrictEqual(["US000000"]);
expect(() => (new SinaApiCodeTransform()).transforms(["STOCKAPI"]))
.toThrow(new Error(ERROR_API_CODE));
});
});

View File

@ -1,74 +0,0 @@
// Stock
const SinaCommonCodeTransform = require("stocks/sina/transforms/common-code").default;
describe("【新浪】统一代码转换股票代码", () => {
const {
ERROR_COMMON_CODE,
} = require("utils/constant");
it("深交所统一代码转换股票代码", async () => {
expect(() => (new SinaCommonCodeTransform()).SZTransform("000000"))
.toThrow(new Error(ERROR_COMMON_CODE));
expect((new SinaCommonCodeTransform()).SZTransform("SZ000000"))
.toBe("sz000000");
});
it("上交所统一代码转换股票代码", async () => {
expect(() => (new SinaCommonCodeTransform()).SHTransform("000000"))
.toThrow(new Error(ERROR_COMMON_CODE));
expect((new SinaCommonCodeTransform()).SHTransform("SH000000"))
.toBe("sh000000");
});
it("港交所统一代码转换股票代码", async () => {
expect(() => (new SinaCommonCodeTransform()).HKTransform("000000"))
.toThrow(new Error(ERROR_COMMON_CODE));
expect((new SinaCommonCodeTransform()).HKTransform("HK000000"))
.toBe("hk000000");
});
it("美交所统一代码转换股票代码", async () => {
expect(() => (new SinaCommonCodeTransform()).USTransform("000000"))
.toThrow(new Error(ERROR_COMMON_CODE));
expect((new SinaCommonCodeTransform()).USTransform("US000000"))
.toBe("gb_000000");
});
it("交易所统一代码转换股票代码", async () => {
expect((new SinaCommonCodeTransform()).transform("SZ000000"))
.toBe("sz000000");
expect((new SinaCommonCodeTransform()).transform("SH000000"))
.toBe("sh000000");
expect((new SinaCommonCodeTransform()).transform("HK000000"))
.toBe("hk000000");
expect((new SinaCommonCodeTransform()).transform("US000000"))
.toBe("gb_000000");
expect(() => (new SinaCommonCodeTransform()).transform("000000"))
.toThrow(new Error(ERROR_COMMON_CODE));
});
it("交易所统一代码组转换股票代码组", async () => {
expect((new SinaCommonCodeTransform()).transforms(["SZ000000"]))
.toStrictEqual(["sz000000"]);
expect((new SinaCommonCodeTransform()).transforms(["SH000000"]))
.toStrictEqual(["sh000000"]);
expect((new SinaCommonCodeTransform()).transforms(["HK000000"]))
.toStrictEqual(["hk000000"]);
expect((new SinaCommonCodeTransform()).transforms(["US000000"]))
.toStrictEqual(["gb_000000"]);
expect(() => (new SinaCommonCodeTransform()).transforms(["000000"]))
.toThrow(new Error(ERROR_COMMON_CODE));
});
});

View File

@ -1,86 +0,0 @@
// Stock
const SinaStockTransform = require("stocks/sina/transforms/stock").default;
describe("【新浪】股票数据转换测试", () => {
// 上交所相关代码
const SHCode = 'SH510500';
const SHBody = `var hq_str_sh510500="500ETF,7.147,7.149,7.224,7.280,7.085,7.224,7.225,272478144,1964297124.000,6300,7.224,32900,7.223,37000,7.222,28600,7.221,14300,7.220,389300,7.225,88400,7.226,32300,7.227,572800,7.228,19000,7.229,2020-07-31,15:00:00,00,";`
const SHRow = SHBody.split(";\n")[0];
const SHParams = SHRow.split('=').reverse()[0].replace('"', '').split(",");
// 深交所
const SZCode = 'SZ399001';
const SZBody = `var hq_str_sz399001="深证成指,13464.207,13466.854,13637.883,13748.034,13399.859,0.000,0.000,48559923962,650202505377.656,0,0.000,0,0.000,0,0.000,0,0.000,0,0.000,0,0.000,0,0.000,0,0.000,0,0.000,0,0.000,2020-07-31,15:00:03,00";`;
const SZRow = SZBody.split(";\n")[0];
const SZParams = SZRow.split('=').reverse()[0].replace('"', '').split(",");
// 港交所
const HKCode = 'HKHSI';
const HKBody = `var hq_str_hkHSI="Hang Seng Index,恒生指数,24747.29,24710.59,24938.85,24534.79,24595.35,-115.24,-0.47,0.000,0.000,119153830,0,0.000,0.00,29174.92,21139.26,2020/07/31,16:08";`;
const HKRow = HKBody.split(";\n")[0];
const HKParams = HKRow.split('=').reverse()[0].replace('"', '').split(",");
// 美交所
const USCode = 'USDJI';
const USBody = `var hq_str_gb_dji="道琼斯,26428.3203,0.44,2020-08-01 05:07:40,114.6700,26409.3301,26440.0195,26013.5898,29568.5703,18213.6504,491372564,397524206,0,0.00,--,0.00,0.00,0.00,0.00,0,0,0.0000,0.00,0.0000,,Jul 31 05:07PM EDT,26313.6504,0,1,2020";`;
const USRow = USBody.split(";\n")[0];
const USParams = USRow.split('=').reverse()[0].replace('"', '').split(",");
it("获取股票代码", async () => {
expect(new SinaStockTransform(SHCode, SHParams).getCode()).toBe("SH510500");
expect(new SinaStockTransform(SZCode, SZParams).getCode()).toBe("SZ399001");
expect(new SinaStockTransform(HKCode, HKParams).getCode()).toBe("HKHSI");
expect(new SinaStockTransform(USCode, USParams).getCode()).toBe("USDJI");
expect(new SinaStockTransform("000000", []).getCode()).toBe("000000");
});
it("获取股票名称", async () => {
expect(new SinaStockTransform(SHCode, SHParams).getName()).toBe('500ETF');
expect(new SinaStockTransform(SZCode, SZParams).getName()).toBe('深证成指');
expect(new SinaStockTransform(HKCode, HKParams).getName()).toBe('恒生指数');
expect(new SinaStockTransform(USCode, USParams).getName()).toBe("道琼斯");
});
it("获取股票现价", async () => {
expect(new SinaStockTransform(SHCode, SHParams).getNow()).toBe(7.224);
expect(new SinaStockTransform(SZCode, SZParams).getNow()).toBe(13637.883);
expect(new SinaStockTransform(HKCode, HKParams).getNow()).toBe(24595.35);
expect(new SinaStockTransform(USCode, USParams).getNow()).toBe(26428.3203);
});
it("获取股票最低价", async () => {
expect(new SinaStockTransform(SHCode, SHParams).getLow()).toBe(7.085);
expect(new SinaStockTransform(SZCode, SZParams).getLow()).toBe(13399.859);
expect(new SinaStockTransform(HKCode, HKParams).getLow()).toBe(24534.79);
expect(new SinaStockTransform(USCode, USParams).getLow()).toBe(26013.5898);
});
it("获取股票最高价", async () => {
expect(new SinaStockTransform(SHCode, SHParams).getHigh()).toBe(7.28);
expect(new SinaStockTransform(SZCode, SZParams).getHigh()).toBe(13748.034);
expect(new SinaStockTransform(HKCode, HKParams).getHigh()).toBe(24938.85);
expect(new SinaStockTransform(USCode, USParams).getHigh()).toBe(26440.0195);
});
it("获取股票昨日收盘价", async () => {
expect(new SinaStockTransform(SHCode, SHParams).getYesterday()).toBe(7.149);
expect(new SinaStockTransform(SZCode, SZParams).getYesterday()).toBe(13466.854);
expect(new SinaStockTransform(HKCode, HKParams).getYesterday()).toBe(24710.59);
expect(new SinaStockTransform(USCode, USParams).getYesterday()).toBe(26313.6504);
});
it("获取股票涨跌", async () => {
expect(new SinaStockTransform(SHCode, SHParams).getPercent()).toBe(7.224 / 7.149 - 1);
expect(new SinaStockTransform(SZCode, SZParams).getPercent()).toBe(13637.883 / 13466.854 - 1);
expect(new SinaStockTransform(HKCode, HKParams).getPercent()).toBe(24595.35 / 24710.59 - 1);
expect(new SinaStockTransform(USCode, USParams).getPercent()).toBe(26428.3203 / 26313.6504 - 1);
});
it("获取股票数据", async () => {
expect(new SinaStockTransform(SHCode, SHParams).getStock()).toStrictEqual({ code: "SH510500", name: "500ETF", percent: 7.224 / 7.149 - 1, now: 7.224, low: 7.085, high: 7.28, yesterday: 7.149 });
expect(new SinaStockTransform(SZCode, SZParams).getStock()).toStrictEqual({ code: 'SZ399001', name: '深证成指', percent: 13637.883 / 13466.854 - 1, now: 13637.883, low: 13399.859, high: 13748.034, yesterday: 13466.854 });
expect(new SinaStockTransform(HKCode, HKParams).getStock()).toStrictEqual({ code: 'HKHSI', name: '恒生指数', percent: 24595.35 / 24710.59 - 1, now: 24595.35, low: 24534.79, high: 24938.85, yesterday: 24710.59 });
expect(new SinaStockTransform(USCode, USParams).getStock()).toStrictEqual({ code: 'USDJI', name: '道琼斯', percent: 26428.3203 / 26313.6504 - 1, now: 26428.3203, low: 26013.5898, high: 26440.0195, yesterday: 26313.6504 });
});
});

View File

@ -1,49 +0,0 @@
// Stock
const Tencent = require("stocks/tencent").default;
describe("【腾讯】股票代码接口", () => {
const {
ERROR_UNDEFINED_SEARCH_STOCK,
} = require("utils/constant");
it("需要获取的股票代码", async () => {
await expect(Tencent.getStock("SH510500"))
.resolves
.toMatchObject({ code: "SH510500", name: "500ETF" });
await expect(Tencent.getStock("SZ510500"))
.resolves
.toMatchObject({ code: "SZ510500", name: "---" });
});
it("需要获取的股票代码组", async () => {
await expect(Tencent.getStocks(["SH510500"]))
.resolves
.toEqual(expect.arrayContaining([expect.objectContaining({ code: "SH510500", name: "500ETF" })]));
await expect(Tencent.getStocks(["SZ510500"]))
.resolves
.toEqual(expect.arrayContaining([expect.objectContaining({ code: "SZ510500", name: "---" })]));
await expect(Tencent.getStocks([]))
.resolves
.toEqual([]);
});
it("搜索股票代码", async () => {
await expect(Tencent.searchStocks("格力电器"))
.resolves
.toEqual(expect.arrayContaining([expect.objectContaining({ code: "SZ000651", name: "格力电器" })]));
await expect(Tencent.searchStocks("贵州茅台"))
.resolves
.toEqual(expect.arrayContaining([expect.objectContaining({ code: "SH600519", name: "贵州茅台" })]));
await expect(Tencent.searchStocks("安踏体育"))
.resolves
.toEqual(expect.arrayContaining([
expect.objectContaining({ code: "HK02020", name: "安踏体育" }),
expect.objectContaining({ code: "USANPDY", name: "安踏体育" }),
]));
});
});

View File

@ -1,74 +0,0 @@
// Stock
const TencentApiCodeTransform = require("stocks/tencent/transforms/api-code").default;
describe("【腾讯】股票代码转换统一代码", () => {
const {
ERROR_API_CODE,
} = require("utils/constant");
it("深交所股票代码转换统一代码", async () => {
expect(() => (new TencentApiCodeTransform()).SZTransform("STOCKAPI"))
.toThrow(new Error(ERROR_API_CODE));
expect((new TencentApiCodeTransform()).SZTransform("sz000000"))
.toBe("SZ000000");
});
it("上交所股票代码转换统一代码", async () => {
expect(() => (new TencentApiCodeTransform()).SHTransform("STOCKAPI"))
.toThrow(new Error(ERROR_API_CODE));
expect((new TencentApiCodeTransform()).SHTransform("sh000000"))
.toBe("SH000000");
});
it("港交所股票代码转换统一代码", async () => {
expect(() => (new TencentApiCodeTransform()).HKTransform("STOCKAPI"))
.toThrow(new Error(ERROR_API_CODE));
expect((new TencentApiCodeTransform()).HKTransform("hk000000"))
.toBe("HK000000");
});
it("美交所股票代码转换统一代码", async () => {
expect(() => (new TencentApiCodeTransform()).USTransform("STOCKAPI"))
.toThrow(new Error(ERROR_API_CODE));
expect((new TencentApiCodeTransform()).USTransform("us000000"))
.toBe("US000000");
});
it("交易所股票代码转换统一代码", async () => {
expect((new TencentApiCodeTransform()).transform("sz000000"))
.toBe("SZ000000");
expect((new TencentApiCodeTransform()).transform("sh000000"))
.toBe("SH000000");
expect((new TencentApiCodeTransform()).transform("hk000000"))
.toBe("HK000000");
expect((new TencentApiCodeTransform()).transform("us000000"))
.toBe("US000000");
expect(() => (new TencentApiCodeTransform()).transform("STOCKAPI"))
.toThrow(new Error(ERROR_API_CODE));
});
it("交易所股票代码组转换统一代码组", async () => {
expect((new TencentApiCodeTransform()).transforms(["sz000000"]))
.toStrictEqual(["SZ000000"]);
expect((new TencentApiCodeTransform()).transforms(["sh000000"]))
.toStrictEqual(["SH000000"]);
expect((new TencentApiCodeTransform()).transforms(["hk000000"]))
.toStrictEqual(["HK000000"]);
expect((new TencentApiCodeTransform()).transforms(["us000000"]))
.toStrictEqual(["US000000"]);
expect(() => (new TencentApiCodeTransform()).transforms(["STOCKAPI"]))
.toThrow(new Error(ERROR_API_CODE));
});
});

View File

@ -1,74 +0,0 @@
// Stock
const TencentCommonCodeTransform = require("stocks/tencent/transforms/common-code").default;
describe("【腾讯】统一代码转换股票代码", () => {
const {
ERROR_COMMON_CODE,
} = require("utils/constant");
it("深交所统一代码转换股票代码", async () => {
expect(() => (new TencentCommonCodeTransform()).SZTransform("000000"))
.toThrow(new Error(ERROR_COMMON_CODE));
expect((new TencentCommonCodeTransform()).SZTransform("SZ000000"))
.toBe("sz000000");
});
it("上交所统一代码转换股票代码", async () => {
expect(() => (new TencentCommonCodeTransform()).SHTransform("000000"))
.toThrow(new Error(ERROR_COMMON_CODE));
expect((new TencentCommonCodeTransform()).SHTransform("SH000000"))
.toBe("sh000000");
});
it("港交所统一代码转换股票代码", async () => {
expect(() => (new TencentCommonCodeTransform()).HKTransform("000000"))
.toThrow(new Error(ERROR_COMMON_CODE));
expect((new TencentCommonCodeTransform()).HKTransform("HK000000"))
.toBe("hk000000");
});
it("美交所统一代码转换股票代码", async () => {
expect(() => (new TencentCommonCodeTransform()).USTransform("000000"))
.toThrow(new Error(ERROR_COMMON_CODE));
expect((new TencentCommonCodeTransform()).USTransform("US000000"))
.toBe("us000000");
});
it("交易所统一代码转换股票代码", async () => {
expect((new TencentCommonCodeTransform()).transform("SZ000000"))
.toBe("sz000000");
expect((new TencentCommonCodeTransform()).transform("SH000000"))
.toBe("sh000000");
expect((new TencentCommonCodeTransform()).transform("HK000000"))
.toBe("hk000000");
expect((new TencentCommonCodeTransform()).transform("US000000"))
.toBe("us000000");
expect(() => (new TencentCommonCodeTransform()).transform("000000"))
.toThrow(new Error(ERROR_COMMON_CODE));
});
it("交易所统一代码组转换股票代码组", async () => {
expect((new TencentCommonCodeTransform()).transforms(["SZ000000"]))
.toStrictEqual(["sz000000"]);
expect((new TencentCommonCodeTransform()).transforms(["SH000000"]))
.toStrictEqual(["sh000000"]);
expect((new TencentCommonCodeTransform()).transforms(["HK000000"]))
.toStrictEqual(["hk000000"]);
expect((new TencentCommonCodeTransform()).transforms(["US000000"]))
.toStrictEqual(["us000000"]);
expect(() => (new TencentCommonCodeTransform()).transforms(["000000"]))
.toThrow(new Error(ERROR_COMMON_CODE));
});
});

View File

@ -1,54 +0,0 @@
// Stock
const TencentStockTransform = require("stocks/tencent/transforms/stock").default;
describe("【腾讯】股票数据转换测试", () => {
const code = 'SH510500';
const body = `v_sh510500="1~500ETF~510500~7.224~7.149~7.147~2724781~1351032~1373749~7.224~63~7.223~329~7.222~370~7.221~286~7.220~143~7.225~3893~7.226~884~7.227~323~7.228~5728~7.229~190~~20200731154041~0.075~1.05~7.280~7.085~7.224/2724781/1964297124~2724781~196430~~~~7.280~7.085~2.73~~~0.00~7.864~6.434~1.20~-9827~7.209~~~~~~196429.7124~0.0000~0~ ~ETF~26.51~~~~";`
const rows = body.split(";\n");
const row = rows[0];
const [_, paramsUnformat] = row.split('=');
const params = paramsUnformat.replace('"', '').split("~");
it("获取股票代码", async () => {
expect(new TencentStockTransform(code, params).getCode())
.toBe('SH510500');
});
it("获取股票名称", async () => {
expect(new TencentStockTransform(code, params).getName())
.toBe('500ETF');
});
it("获取股票现价", async () => {
expect(new TencentStockTransform(code, params).getNow())
.toBe(7.224);
});
it("获取股票最低价", async () => {
expect(new TencentStockTransform(code, params).getLow())
.toBe(7.085);
});
it("获取股票最高价", async () => {
expect(new TencentStockTransform(code, params).getHigh())
.toBe(7.28);
});
it("获取股票昨日收盘价", async () => {
expect(new TencentStockTransform(code, params).getYesterday())
.toBe(7.149);
});
it("获取股票涨跌", async () => {
expect(new TencentStockTransform(code, params).getPercent())
.toBe(7.224 / 7.149 - 1);
});
it("获取股票数据", async () => {
expect(new TencentStockTransform(code, params).getStock())
.toStrictEqual({ "code": "SH510500", "high": 7.28, "low": 7.085, "name": "500ETF", "now": 7.224, "percent": 7.224 / 7.149 - 1, "yesterday": 7.149 });
});
});

View File

@ -1,51 +0,0 @@
// Stock
const Xueqiu = require("stocks/xueqiu").default;
describe("【雪球】股票代码接口", () => {
it("获取 Token", async () => {
await expect(Xueqiu.getToken())
.resolves
.toContain('xq_a_token');
});
it("需要获取的股票代码", async () => {
await expect(Xueqiu.getStock("SH510500"))
.resolves
.toMatchObject({ code: "SH510500", name: "中证500ETF" });
await expect(Xueqiu.getStock("SZ510500"))
.resolves
.toMatchObject({ code: "SZ510500", name: "---" });
});
it("需要获取的股票代码组", async () => {
await expect(Xueqiu.getStocks(["SH510500"]))
.resolves
.toEqual(expect.arrayContaining([expect.objectContaining({ code: "SH510500", name: "中证500ETF" })]));
await expect(Xueqiu.getStocks(["SZ510500"]))
.resolves
.toEqual(expect.arrayContaining([expect.objectContaining({ code: "SZ510500", name: "---" })]));
await expect(Xueqiu.getStocks([]))
.resolves
.toEqual([]);
});
it("搜索股票代码", async () => {
await expect(Xueqiu.searchStocks("格力电器"))
.resolves
.toEqual(expect.arrayContaining([expect.objectContaining({ code: "SZ000651", name: "格力电器" })]));
await expect(Xueqiu.searchStocks("贵州茅台"))
.resolves
.toEqual(expect.arrayContaining([expect.objectContaining({ code: "SH600519", name: "贵州茅台" })]));
await expect(Xueqiu.searchStocks("安踏体育"))
.resolves
.toEqual(expect.arrayContaining([
expect.objectContaining({ code: "HK02020", name: "安踏体育" }),
expect.objectContaining({ code: "USANPDY", name: "安踏体育ADR" }),
]));
});
});

View File

@ -1,68 +0,0 @@
// Stock
const XueqiuApiCodeTransform = require("stocks/xueqiu/transforms/api-code").default;
describe("【雪球】股票代码转换统一代码", () => {
const {
ERROR_API_CODE,
} = require("utils/constant");
it("深交所股票代码转换统一代码", async () => {
expect(() => (new XueqiuApiCodeTransform()).SZTransform("000000"))
.toThrow(new Error(ERROR_API_CODE));
expect((new XueqiuApiCodeTransform()).SZTransform("SZ000000"))
.toBe("SZ000000");
});
it("上交所股票代码转换统一代码", async () => {
expect(() => (new XueqiuApiCodeTransform()).SHTransform("000000"))
.toThrow(new Error(ERROR_API_CODE));
expect((new XueqiuApiCodeTransform()).SHTransform("SH000000"))
.toBe("SH000000");
});
it("港交所股票代码转换统一代码", async () => {
expect(() => (new XueqiuApiCodeTransform()).HKTransform("000000"))
.toThrow(new Error(ERROR_API_CODE));
expect((new XueqiuApiCodeTransform()).HKTransform("HK000000"))
.toBe("HK000000");
});
it("美交所股票代码转换统一代码", async () => {
expect(() => (new XueqiuApiCodeTransform()).USTransform("SZ000000"))
.toThrow(new Error(ERROR_API_CODE));
expect((new XueqiuApiCodeTransform()).USTransform("000000"))
.toBe("US000000");
});
it("交易所股票代码转换统一代码", async () => {
expect((new XueqiuApiCodeTransform()).transform("SZ000000"))
.toBe("SZ000000");
expect((new XueqiuApiCodeTransform()).transform("SH000000"))
.toBe("SH000000");
expect((new XueqiuApiCodeTransform()).transform("HK000000"))
.toBe("HK000000");
expect((new XueqiuApiCodeTransform()).transform("000000"))
.toBe("US000000");
});
it("交易所股票代码组转换统一代码组", async () => {
expect((new XueqiuApiCodeTransform()).transforms(["SZ000000"]))
.toStrictEqual(["SZ000000"]);
expect((new XueqiuApiCodeTransform()).transforms(["SH000000"]))
.toStrictEqual(["SH000000"]);
expect((new XueqiuApiCodeTransform()).transforms(["HK000000"]))
.toStrictEqual(["HK000000"]);
expect((new XueqiuApiCodeTransform()).transforms(["000000"]))
.toStrictEqual(["US000000"]);
});
});

View File

@ -1,74 +0,0 @@
// Stock
const XueqiuCommonCodeTransform = require("stocks/xueqiu/transforms/common-code").default;
describe("【雪球】统一代码转换股票代码", () => {
const {
ERROR_COMMON_CODE,
} = require("utils/constant");
it("深交所统一代码转换股票代码", async () => {
expect(() => (new XueqiuCommonCodeTransform()).SZTransform("000000"))
.toThrow(new Error(ERROR_COMMON_CODE));
expect((new XueqiuCommonCodeTransform()).SZTransform("SZ000000"))
.toBe("SZ000000");
});
it("上交所统一代码转换股票代码", async () => {
expect(() => (new XueqiuCommonCodeTransform()).SHTransform("000000"))
.toThrow(new Error(ERROR_COMMON_CODE));
expect((new XueqiuCommonCodeTransform()).SHTransform("SH000000"))
.toBe("SH000000");
});
it("港交所统一代码转换股票代码", async () => {
expect(() => (new XueqiuCommonCodeTransform()).HKTransform("000000"))
.toThrow(new Error(ERROR_COMMON_CODE));
expect((new XueqiuCommonCodeTransform()).HKTransform("HK000000"))
.toBe("HK000000");
});
it("美交所统一代码转换股票代码", async () => {
expect(() => (new XueqiuCommonCodeTransform()).USTransform("000000"))
.toThrow(new Error(ERROR_COMMON_CODE));
expect((new XueqiuCommonCodeTransform()).USTransform("US000000"))
.toBe("000000");
});
it("交易所统一代码转换股票代码", async () => {
expect((new XueqiuCommonCodeTransform()).transform("SZ000000"))
.toBe("SZ000000");
expect((new XueqiuCommonCodeTransform()).transform("SH000000"))
.toBe("SH000000");
expect((new XueqiuCommonCodeTransform()).transform("HK000000"))
.toBe("HK000000");
expect((new XueqiuCommonCodeTransform()).transform("US000000"))
.toBe("000000");
expect(() => (new XueqiuCommonCodeTransform()).transform("000000"))
.toThrow(new Error(ERROR_COMMON_CODE));
});
it("交易所统一代码组转换股票代码组", async () => {
expect((new XueqiuCommonCodeTransform()).transforms(["SZ000000"]))
.toStrictEqual(["SZ000000"]);
expect((new XueqiuCommonCodeTransform()).transforms(["SH000000"]))
.toStrictEqual(["SH000000"]);
expect((new XueqiuCommonCodeTransform()).transforms(["HK000000"]))
.toStrictEqual(["HK000000"]);
expect((new XueqiuCommonCodeTransform()).transforms(["US000000"]))
.toStrictEqual(["000000"]);
expect(() => (new XueqiuCommonCodeTransform()).transforms(["000000"]))
.toThrow(new Error(ERROR_COMMON_CODE));
});
});

View File

@ -1,50 +0,0 @@
// Stock
const XueqiuStockTransform = require("stocks/xueqiu/transforms/stock").default;
describe("【雪球】股票数据转换测试", () => {
const code = 'SH510500';
const body = `{"data":{"market":{"status_id":8,"region":"CN","status":"休市","time_zone":"Asia/Shanghai","time_zone_desc":null},"quote":{"symbol":"SH510500","code":"510500","avg_price":6.982,"delayed":0,"type":13,"percent":0.5,"tick_size":0.001,"float_shares":null,"amplitude":null,"current":7.224,"high":7.28,"current_year_percent":22.38,"float_market_capital":null,"issue_date":1363276800000,"low": 7.085,"sub_type":"EBS","market_capital":4.25501735904E10,"currency":"CNY","lot_size":100,"lock_set":null,"timestamp":1595207715950,"amount":null,"chg":0.035,"last_close":7.149,"volume":null,"turnover_rate":null,"name":"中证500ETF","exchange":"SH","time":1595207715000,"total_shares":6094267200,"open":null,"status":1},"others":{"pankou_ratio":null,"cyb_switch":false},"tags":[{"description":"融","value":6},{"description":"空","value":7}]},"error_code":0,"error_description":""}`
const params = JSON.parse(body).data.quote;
it("获取股票代码", async () => {
expect(new XueqiuStockTransform(code, params).getCode())
.toBe('SH510500');
});
it("获取股票名称", async () => {
expect(new XueqiuStockTransform(code, params).getName())
.toBe('中证500ETF');
});
it("获取股票现价", async () => {
expect(new XueqiuStockTransform(code, params).getNow())
.toBe(7.224);
});
it("获取股票最低价", async () => {
expect(new XueqiuStockTransform(code, params).getLow())
.toBe(7.085);
});
it("获取股票最高价", async () => {
expect(new XueqiuStockTransform(code, params).getHigh())
.toBe(7.28);
});
it("获取股票昨日收盘价", async () => {
expect(new XueqiuStockTransform(code, params).getYesterday())
.toBe(7.149);
});
it("获取股票涨跌", async () => {
expect(new XueqiuStockTransform(code, params).getPercent())
.toBe(7.224 / 7.149 - 1);
});
it("获取股票数据", async () => {
expect(new XueqiuStockTransform(code, params).getStock())
.toStrictEqual({ "code": "SH510500", "high": 7.28, "low": 7.085, "name": "中证500ETF", "now": 7.224, "percent": 7.224 / 7.149 - 1, "yesterday": 7.149 });
});
});

View File

@ -1,39 +0,0 @@
{
"compilerOptions": {
"baseUrl": "src",
"rootDir": "src",
"target": "es5",
"outDir": "dist",
"module": "commonjs",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"paths": {
"types/*": [
"../types/*"
],
"@stocks/*": [
"stocks/*"
],
"@utils/*": [
"utils/*"
],
"@interfaces/*": [
"interfaces/*"
]
},
"plugins": [
{
"transform": "typescript-transform-paths"
}
]
},
"include": [
"src/**/*.ts"
],
"exclude": [
"node_modules/**",
"dist/**"
]
}

21
types/index.d.ts vendored
View File

@ -1,21 +0,0 @@
import StockApi from './stocks/index';
export declare const stocks: {
base: StockApi,
netease: StockApi,
sina: StockApi,
tencent: StockApi,
xueqiu: StockApi,
};
export declare const root: {
stocks: {
base: StockApi,
netease: StockApi,
sina: StockApi,
tencent: StockApi,
xueqiu: StockApi,
},
};
export default root;

View File

@ -1,23 +0,0 @@
import Stock from '../utils/stock';
export interface StockApi {
/**
*
* @param code
*/
getStock(code: string): Promise<Stock>;
/**
*
* @param codes
*/
getStocks(codes: string[]): Promise<Stock[]>;
/**
*
* @param key
*/
searchStocks(key: string): Promise<Stock[]>;
}
export default StockApi;

View File

@ -1,10 +0,0 @@
export interface ApiCodeTransform {
transform(code: string): string;
transforms(codes: string[]): string[];
SZTransform(code: string): string;
SHTransform(code: string): string;
HKTransform(code: string): string;
USTransform(code: string): string;
}
export default ApiCodeTransform;

View File

@ -1,10 +0,0 @@
export interface CommonCodeTransform {
transform(code: string): string;
transforms(codes: string[]): string[];
SZTransform(code: string): string;
SHTransform(code: string): string;
HKTransform(code: string): string;
USTransform(code: string): string;
}
export default CommonCodeTransform;

View File

@ -1,48 +0,0 @@
// Types
import Stock from "../../utils/stock";
/**
*
*/
export interface StockTransform {
/**
*
*/
getCode(): string;
/**
*
*/
getName(): string;
/**
*
*/
getNow(): number;
/**
*
*/
getLow(): number;
/**
*
*/
getHigh(): number;
/**
*
*/
getYesterday(): number;
/**
*
*/
getPercent(): number;
/**
*
*/
getStock(): Stock;
}
export default StockTransform;

View File

@ -1,3 +0,0 @@
export type Dictionary<T, K extends string | number = string> = { [key in K]: T };
export default Dictionary;

View File

@ -1,12 +0,0 @@
export interface Stock {
name: string;
code: string;
now: number;
low: number;
high: number;
percent: number;
yesterday: number;
}
export default Stock;

4131
yarn.lock

File diff suppressed because it is too large Load Diff