Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions clis/xueqiu/groups.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
site: xueqiu
name: groups
description: 获取雪球自选股分组列表(含模拟组合)
domain: xueqiu.com
browser: true

pipeline:
- navigate: https://xueqiu.com
- evaluate: |
(async () => {
const resp = await fetch('https://stock.xueqiu.com/v5/stock/portfolio/list.json?category=1&size=20', {credentials: 'include'});
if (!resp.ok) throw new Error('HTTP ' + resp.status + ' Hint: Not logged in?');
const d = await resp.json();
if (!d.data || !d.data.stocks) throw new Error('获取失败,可能未登录');

return d.data.stocks.map(g => ({
pid: String(g.id),
name: g.name,
count: g.symbol_count || 0
}));
})()

columns: [pid, name, count]
65 changes: 65 additions & 0 deletions clis/xueqiu/kline.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
site: xueqiu
name: kline
description: 获取雪球股票K线(历史行情)数据
domain: xueqiu.com
browser: true

args:
symbol:
positional: true
type: str
required: true
description: 股票代码,如 SH600519、SZ000858、AAPL
days:
type: int
default: 14
description: 回溯天数(默认14天)

pipeline:
- navigate: https://xueqiu.com

- evaluate: |
(async () => {
const symbol = (${{ args.symbol | json }} || '').toUpperCase();
const days = parseInt(${{ args.days | json }}) || 14;
if (!symbol) throw new Error('Missing argument: symbol');

// begin = now minus days (for count=-N, returns N items ending at begin)
const beginTs = Date.now();
const resp = await fetch('https://stock.xueqiu.com/v5/stock/chart/kline.json?symbol=' + encodeURIComponent(symbol) + '&begin=' + beginTs + '&period=day&type=before&count=-' + days, {credentials: 'include'});
if (!resp.ok) throw new Error('HTTP ' + resp.status + ' Hint: Not logged in?');
const d = await resp.json();

if (!d.data || !d.data.item || d.data.item.length === 0) return [];

const columns = d.data.column || [];
const items = d.data.item || [];
const colIdx = {};
columns.forEach((name, i) => { colIdx[name] = i; });

function fmt(v) { return v == null ? null : v; }

return items.map(row => ({
date: colIdx.timestamp != null ? new Date(row[colIdx.timestamp]).toISOString().split('T')[0] : null,
open: fmt(row[colIdx.open]),
high: fmt(row[colIdx.high]),
low: fmt(row[colIdx.low]),
close: fmt(row[colIdx.close]),
volume: fmt(row[colIdx.volume]),
amount: fmt(row[colIdx.amount]),
chg: fmt(row[colIdx.chg]),
percent: fmt(row[colIdx.percent]),
symbol: symbol
}));
})()

- map:
date: ${{ item.date }}
open: ${{ item.open }}
high: ${{ item.high }}
low: ${{ item.low }}
close: ${{ item.close }}
volume: ${{ item.volume }}
percent: ${{ item.percent }}

columns: [date, open, high, low, close, volume]
18 changes: 9 additions & 9 deletions clis/xueqiu/watchlist.yaml
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
site: xueqiu
name: watchlist
description: 获取雪球自选股列表
description: 获取雪球自选股/模拟组合股票列表
domain: xueqiu.com
browser: true

args:
category:
type: str # using str to prevent parsing issues like 01
default: "1"
description: "分类:1=自选(默认) 2=持仓 3=关注"
pid:
type: str
default: "-1"
description: "分组ID:-1=全部(默认) -4=模拟 -5=沪深 -6=美股 -7=港股 -10=实盘 0=持仓(通过 xueqiu groups 获取)"
limit:
type: int
default: 100
Expand All @@ -18,12 +18,12 @@ pipeline:
- navigate: https://xueqiu.com
- evaluate: |
(async () => {
const category = parseInt(${{ args.category | json }}) || 1;
const resp = await fetch(`https://stock.xueqiu.com/v5/stock/portfolio/stock/list.json?size=100&category=${category}&pid=-1`, {credentials: 'include'});
const pid = ${{ args.pid | json }} || '-1';
const resp = await fetch(`https://stock.xueqiu.com/v5/stock/portfolio/stock/list.json?size=100&category=1&pid=${encodeURIComponent(pid)}`, {credentials: 'include'});
if (!resp.ok) throw new Error('HTTP ' + resp.status + ' Hint: Not logged in?');
const d = await resp.json();
if (!d.data || !d.data.stocks) throw new Error('获取失败,可能未登录');

return d.data.stocks.map(s => ({
symbol: s.symbol,
name: s.name,
Expand All @@ -40,7 +40,7 @@ pipeline:
name: ${{ item.name }}
price: ${{ item.price }}
changePercent: ${{ item.changePercent }}

- limit: ${{ args.limit }}

columns: [symbol, name, price, changePercent]