Initial commit: Hermes Agent skills collection
- Trading skills (OKX, dividend, lottery, quantitative) - Creative skills (ASCII art, diagrams, video) - Development skills (GitHub, debugging, TDD) - Research skills (arXiv, blog monitoring) - Productivity skills (email, documents, notes) - MCP integration skills - Custom user skills
This commit is contained in:
@@ -0,0 +1,239 @@
|
||||
"""行情命令模块"""
|
||||
import click
|
||||
from longbridge.openapi import QuoteContext, Period, AdjustType
|
||||
|
||||
from longbridge_cli.config import get_config
|
||||
from longbridge_cli.formatters import print_table, print_json, print_error
|
||||
|
||||
PERIOD_MAP = {
|
||||
"1m": Period.Min_1,
|
||||
"5m": Period.Min_5,
|
||||
"15m": Period.Min_15,
|
||||
"30m": Period.Min_30,
|
||||
"60m": Period.Min_60,
|
||||
"day": Period.Day,
|
||||
"week": Period.Week,
|
||||
"month": Period.Month,
|
||||
"quarter": Period.Quarter,
|
||||
"year": Period.Year,
|
||||
}
|
||||
|
||||
|
||||
@click.command("quote")
|
||||
@click.argument("symbols", nargs=-1, required=True)
|
||||
@click.option("--json", "output_json", is_flag=True, help="以 JSON 格式输出")
|
||||
@click.pass_context
|
||||
def quote_cmd(ctx, symbols, output_json):
|
||||
"""获取实时报价(支持多个标的)
|
||||
|
||||
示例:longbridge quote AAPL.US 700.HK
|
||||
"""
|
||||
try:
|
||||
quote_ctx = QuoteContext(get_config(ctx.obj.get("profile")))
|
||||
resp = quote_ctx.quote(list(symbols))
|
||||
except Exception as e:
|
||||
print_error(str(e))
|
||||
|
||||
if output_json:
|
||||
data = [
|
||||
{
|
||||
"symbol": q.symbol,
|
||||
"last_done": float(q.last_done),
|
||||
"open": float(q.open),
|
||||
"high": float(q.high),
|
||||
"low": float(q.low),
|
||||
"volume": q.volume,
|
||||
"turnover": float(q.turnover),
|
||||
"change_rate": round(float(q.last_done / q.prev_close - 1) * 100, 2) if q.prev_close else None,
|
||||
"prev_close": float(q.prev_close),
|
||||
}
|
||||
for q in resp
|
||||
]
|
||||
print_json(data)
|
||||
else:
|
||||
headers = ["标的", "最新价", "涨跌幅", "开盘", "最高", "最低", "成交量", "成交额"]
|
||||
rows = []
|
||||
for q in resp:
|
||||
change_rate = round(float(q.last_done / q.prev_close - 1) * 100, 2) if q.prev_close else "-"
|
||||
change_str = f"{change_rate:+.2f}%" if isinstance(change_rate, float) else change_rate
|
||||
rows.append([
|
||||
q.symbol,
|
||||
f"{float(q.last_done):.3f}",
|
||||
change_str,
|
||||
f"{float(q.open):.3f}",
|
||||
f"{float(q.high):.3f}",
|
||||
f"{float(q.low):.3f}",
|
||||
f"{q.volume:,}",
|
||||
f"{float(q.turnover):,.0f}",
|
||||
])
|
||||
print_table(headers, rows, title="实时报价")
|
||||
|
||||
|
||||
@click.command("depth")
|
||||
@click.argument("symbol")
|
||||
@click.option("--json", "output_json", is_flag=True, help="以 JSON 格式输出")
|
||||
@click.pass_context
|
||||
def depth_cmd(ctx, symbol, output_json):
|
||||
"""查看盘口(买5卖5)
|
||||
|
||||
示例:longbridge depth 700.HK
|
||||
"""
|
||||
try:
|
||||
quote_ctx = QuoteContext(get_config(ctx.obj.get("profile")))
|
||||
resp = quote_ctx.depth(symbol)
|
||||
except Exception as e:
|
||||
print_error(str(e))
|
||||
|
||||
if output_json:
|
||||
data = {
|
||||
"symbol": symbol,
|
||||
"asks": [{"position": a.position, "price": float(a.price), "volume": a.volume} for a in resp.asks],
|
||||
"bids": [{"position": b.position, "price": float(b.price), "volume": b.volume} for b in resp.bids],
|
||||
}
|
||||
print_json(data)
|
||||
else:
|
||||
headers = ["方向", "档位", "价格", "数量"]
|
||||
rows = []
|
||||
for a in reversed(resp.asks):
|
||||
rows.append(["卖", str(a.position), f"{float(a.price):.3f}", f"{a.volume:,}"])
|
||||
for b in resp.bids:
|
||||
rows.append(["买", str(b.position), f"{float(b.price):.3f}", f"{b.volume:,}"])
|
||||
print_table(headers, rows, title=f"盘口 - {symbol}")
|
||||
|
||||
|
||||
@click.command("trades")
|
||||
@click.argument("symbol")
|
||||
@click.option("--count", default=20, show_default=True, help="返回条数(最多 1000)")
|
||||
@click.option("--json", "output_json", is_flag=True, help="以 JSON 格式输出")
|
||||
@click.pass_context
|
||||
def trades_cmd(ctx, symbol, count, output_json):
|
||||
"""查看最近逐笔成交
|
||||
|
||||
示例:longbridge trades 700.HK --count 20
|
||||
"""
|
||||
try:
|
||||
quote_ctx = QuoteContext(get_config(ctx.obj.get("profile")))
|
||||
resp = quote_ctx.trades(symbol, count)
|
||||
except Exception as e:
|
||||
print_error(str(e))
|
||||
|
||||
if output_json:
|
||||
data = [
|
||||
{
|
||||
"price": float(t.price),
|
||||
"volume": t.volume,
|
||||
"timestamp": t.timestamp.isoformat() if t.timestamp else None,
|
||||
"direction": str(t.trade_type),
|
||||
}
|
||||
for t in resp
|
||||
]
|
||||
print_json(data)
|
||||
else:
|
||||
headers = ["时间", "价格", "数量", "类型"]
|
||||
rows = [
|
||||
[
|
||||
t.timestamp.strftime("%H:%M:%S") if t.timestamp else "-",
|
||||
f"{float(t.price):.3f}",
|
||||
f"{t.volume:,}",
|
||||
str(t.trade_type),
|
||||
]
|
||||
for t in resp
|
||||
]
|
||||
print_table(headers, rows, title=f"逐笔成交 - {symbol}")
|
||||
|
||||
|
||||
@click.command("candlesticks")
|
||||
@click.argument("symbol")
|
||||
@click.argument("period", type=click.Choice(list(PERIOD_MAP.keys())))
|
||||
@click.option("--count", default=30, show_default=True, help="返回K线条数(最多 1000)")
|
||||
@click.option("--json", "output_json", is_flag=True, help="以 JSON 格式输出")
|
||||
@click.pass_context
|
||||
def candlesticks_cmd(ctx, symbol, period, count, output_json):
|
||||
"""查看 K 线数据
|
||||
|
||||
PERIOD 可选:1m 5m 15m 30m 60m day week month quarter year
|
||||
|
||||
示例:longbridge candlesticks AAPL.US day --count 30
|
||||
"""
|
||||
try:
|
||||
quote_ctx = QuoteContext(get_config(ctx.obj.get("profile")))
|
||||
resp = quote_ctx.candlesticks(symbol, PERIOD_MAP[period], count, AdjustType.NoAdjust)
|
||||
except Exception as e:
|
||||
print_error(str(e))
|
||||
|
||||
if output_json:
|
||||
data = [
|
||||
{
|
||||
"timestamp": c.timestamp.isoformat() if c.timestamp else None,
|
||||
"open": float(c.open),
|
||||
"high": float(c.high),
|
||||
"low": float(c.low),
|
||||
"close": float(c.close),
|
||||
"volume": c.volume,
|
||||
"turnover": float(c.turnover),
|
||||
}
|
||||
for c in resp
|
||||
]
|
||||
print_json(data)
|
||||
else:
|
||||
headers = ["时间", "开盘", "最高", "最低", "收盘", "成交量"]
|
||||
rows = [
|
||||
[
|
||||
c.timestamp.strftime("%Y-%m-%d %H:%M") if c.timestamp else "-",
|
||||
f"{float(c.open):.3f}",
|
||||
f"{float(c.high):.3f}",
|
||||
f"{float(c.low):.3f}",
|
||||
f"{float(c.close):.3f}",
|
||||
f"{c.volume:,}",
|
||||
]
|
||||
for c in resp
|
||||
]
|
||||
print_table(headers, rows, title=f"K线 - {symbol} ({period})")
|
||||
|
||||
|
||||
@click.command("info")
|
||||
@click.argument("symbols", nargs=-1, required=True)
|
||||
@click.option("--json", "output_json", is_flag=True, help="以 JSON 格式输出")
|
||||
@click.pass_context
|
||||
def info_cmd(ctx, symbols, output_json):
|
||||
"""查看标的静态基本信息(名称、交易所、类型等)
|
||||
|
||||
示例:longbridge info 700.HK AAPL.US
|
||||
"""
|
||||
try:
|
||||
quote_ctx = QuoteContext(get_config(ctx.obj.get("profile")))
|
||||
resp = quote_ctx.static_info(list(symbols))
|
||||
except Exception as e:
|
||||
print_error(str(e))
|
||||
|
||||
if output_json:
|
||||
data = [
|
||||
{
|
||||
"symbol": s.symbol,
|
||||
"name_cn": s.name_cn,
|
||||
"name_en": s.name_en,
|
||||
"exchange": s.exchange,
|
||||
"currency": s.currency,
|
||||
"lot_size": s.lot_size,
|
||||
"total_shares": s.total_shares,
|
||||
"circulating_shares": s.circulating_shares,
|
||||
"board": str(s.board),
|
||||
}
|
||||
for s in resp
|
||||
]
|
||||
print_json(data)
|
||||
else:
|
||||
headers = ["标的", "中文名", "英文名", "交易所", "币种", "手数", "板块"]
|
||||
rows = [
|
||||
[
|
||||
s.symbol,
|
||||
s.name_cn,
|
||||
s.name_en,
|
||||
s.exchange,
|
||||
s.currency,
|
||||
str(s.lot_size),
|
||||
str(s.board),
|
||||
]
|
||||
for s in resp
|
||||
]
|
||||
print_table(headers, rows, title="标的信息")
|
||||
Reference in New Issue
Block a user