mirror of
https://github.com/0xrsydn/idx-cli.git
synced 2026-11-07 01:35:36 +00:00
`idx stocks flow SYMBOL` shows what foreign investors bought and sold of a stock, session by session, from IDX's own daily trading summary: foreign buy, sell and net volume, net value at the session's average price, and the share of value traded outside the regular board, with range totals. Latest 10 sessions by default (--days, at most 60) or --from/--to. The MCP server exposes it as get_foreign_flow. - api/idx: pure parser for GetStockSummary (rows dated another session are dropped) and a provider over curl-impersonate's profile fallback with a 30 s limit; Cloudflare passes only some fingerprints. - flow: each session is cached whole by date, so other stocks' flows for the same sessions need no request. Weekends are never requested. - Idx::idx_code is shared by broker and flow for the .JK-only check. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01V3syn2fN2LNo5pvTSqc6eh
67 lines
1.6 KiB
Rust
67 lines
1.6 KiB
Rust
//! idx-core: retrieval and analysis of Indonesian (IDX) market, financial, and
|
|
//! investor data, shared by the `idx` CLI and other frontends.
|
|
//! See docs/DESIGN.md.
|
|
|
|
pub mod analysis;
|
|
pub mod api;
|
|
pub mod broker;
|
|
pub mod cache;
|
|
mod client;
|
|
pub mod config;
|
|
pub mod curl_impersonate;
|
|
pub mod error;
|
|
pub mod financial;
|
|
pub mod flow;
|
|
#[cfg(feature = "ownership")]
|
|
pub mod investor;
|
|
pub mod market;
|
|
#[cfg(feature = "ownership")]
|
|
pub mod ownership;
|
|
pub mod text;
|
|
|
|
pub use client::{CachePolicy, Fetched, Idx};
|
|
|
|
pub mod runtime {
|
|
use std::fmt::Display;
|
|
use std::sync::atomic::{AtomicBool, Ordering};
|
|
|
|
static QUIET: AtomicBool = AtomicBool::new(false);
|
|
static JSON: AtomicBool = AtomicBool::new(false);
|
|
|
|
pub fn set_quiet(quiet: bool) {
|
|
QUIET.store(quiet, Ordering::Relaxed);
|
|
}
|
|
|
|
pub fn is_quiet() -> bool {
|
|
QUIET.load(Ordering::Relaxed)
|
|
}
|
|
|
|
/// In JSON mode diagnostics are JSON lines, so stderr stays
|
|
/// machine-readable alongside a JSON error.
|
|
pub fn set_json(json: bool) {
|
|
JSON.store(json, Ordering::Relaxed);
|
|
}
|
|
|
|
fn emit(level: &str, message: impl Display) {
|
|
if is_quiet() {
|
|
return;
|
|
}
|
|
if JSON.load(Ordering::Relaxed) {
|
|
let line = serde_json::json!({ "level": level, "message": message.to_string() });
|
|
eprintln!("{line}");
|
|
} else {
|
|
eprintln!(
|
|
"{level}: {}",
|
|
crate::text::terminal_safe(&message.to_string())
|
|
);
|
|
}
|
|
}
|
|
|
|
pub fn info(message: impl Display) {
|
|
emit("info", message);
|
|
}
|
|
|
|
pub fn warn(message: impl Display) {
|
|
emit("warning", message);
|
|
}
|
|
}
|