mirror of
https://github.com/0xrsydn/idx-cli.git
synced 2026-11-07 09:45:36 +00:00
feat: corporate actions from the Stockbit session (stocks actions, stocks calendar)
`idx stocks actions SYM [--kind ...]`: one stock's cash and stock
dividends, bonus shares, rights, warrants, splits and reverse splits,
meetings, public exposes and tender offers (`--kind ipo` adds its IPO),
newest first. `idx stocks calendar [--from] [--to] [--kind ...]`: the
market's actions dated in the range (default today and 30 days ahead),
oldest first. MCP: get_corporate_actions, get_corporate_calendar.
Stockbit's `/corpaction/{type}` serves one kind per request; each type has
its own field prefix and list key, so entitlements are read by field
suffix. An action's `date` is the cum date for entitlements, else the
event's first day. Dividends keep their decimals. One request per kind,
cached 6 hours. AUTHERROR without a session.
Fixtures are the 2026-11-03 recordings (market-wide ones trimmed to
October-December). Goldens added; help-stocks and completions-bash gain
the two subcommands, MCP tools.json the two tools (regenerated with
UPDATE_GOLDEN=1). The MCP docs counted 17 tools without stockbit_login;
now 20.
Claude-Session: https://claude.ai/code/session_01RqPPVeVDrnLoP7NUZmLRxY
This commit is contained in:
parent
8a1b29043c
commit
43ff4aa433
55 changed files with 2026 additions and 34 deletions
|
|
@ -4,6 +4,7 @@
|
|||
use idx_core::analysis::bandar::TIERS;
|
||||
use idx_core::api::types::{Interval, Period};
|
||||
use idx_core::broker::types::{BrokerBoard, BrokerInvestor};
|
||||
use idx_core::corporate::types::ActionKind;
|
||||
use idx_core::flow::types::FlowSource;
|
||||
use idx_core::market::{ScreenFilter, ScreenRegion};
|
||||
use schemars::{JsonSchema, Schema, SchemaGenerator, json_schema};
|
||||
|
|
@ -228,6 +229,41 @@ pub struct FlowParams {
|
|||
pub source: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, JsonSchema)]
|
||||
pub struct CorporateActionsParams {
|
||||
/// IDX ticker, e.g. "BBCA".
|
||||
pub symbol: String,
|
||||
/// Kinds to list (default: every kind but "ipo"). Each kind is one request to Stockbit.
|
||||
#[serde(default)]
|
||||
#[schemars(schema_with = "action_kinds_schema")]
|
||||
pub kinds: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, JsonSchema)]
|
||||
pub struct CorporateCalendarParams {
|
||||
/// First day, YYYY-MM-DD (default today).
|
||||
#[serde(default)]
|
||||
pub from: Option<String>,
|
||||
/// Last day, YYYY-MM-DD (default 30 days after `from`; at most 366 days).
|
||||
#[serde(default)]
|
||||
pub to: Option<String>,
|
||||
/// Kinds to list (default: every kind). Each kind is one request to Stockbit.
|
||||
#[serde(default)]
|
||||
#[schemars(schema_with = "action_kinds_schema")]
|
||||
pub kinds: Option<Vec<String>>,
|
||||
}
|
||||
|
||||
/// Parses `kinds`, or `default` when absent.
|
||||
pub fn action_kinds(
|
||||
kinds: Option<Vec<String>>,
|
||||
default: &[ActionKind],
|
||||
) -> Result<Vec<ActionKind>, idx_core::error::IdxError> {
|
||||
match kinds {
|
||||
None => Ok(default.to_vec()),
|
||||
Some(kinds) => kinds.iter().map(|k| k.parse()).collect(),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, JsonSchema)]
|
||||
pub struct ShareholdersParams {
|
||||
/// IDX ticker, e.g. "BBCA".
|
||||
|
|
@ -305,6 +341,11 @@ fn flow_source_schema(_: &mut SchemaGenerator) -> Schema {
|
|||
string_enum(FlowSource::ALL.map(FlowSource::as_str).to_vec())
|
||||
}
|
||||
|
||||
fn action_kinds_schema(_: &mut SchemaGenerator) -> Schema {
|
||||
let kinds: Vec<&str> = ActionKind::ALL.iter().map(|k| k.as_str()).collect();
|
||||
json_schema!({ "type": "array", "items": { "type": "string", "enum": kinds } })
|
||||
}
|
||||
|
||||
fn login_method_schema(_: &mut SchemaGenerator) -> Schema {
|
||||
string_enum(LoginMethod::ALL.map(LoginMethod::as_str).to_vec())
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue