Skip to content

Commit e7573c2

Browse files
hogan-yuanclaude
andcommitted
cli: Sync macrodata with SDK updates (longbridge/openapi#540)
New SDK changes: - macrodata_indicators() gains country filter (MacrodataCountry enum) - macrodata() gains offset parameter for pagination - Both responses now include count (total records) - null deserialization bug fixed in SDK (name/unit/unit_prefix/info) CLI changes: - Add --country flag (HK/CN/US/EU/JP/SG) for indicator list filtering - --page now applies to both list and history (offset = (page-1) * limit) - JSON output includes top-level count field in both modes - Pretty list output prints total count above the table Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
1 parent b4bee90 commit e7573c2

3 files changed

Lines changed: 72 additions & 25 deletions

File tree

Cargo.lock

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/cli/fundamental.rs

Lines changed: 58 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3382,7 +3382,10 @@ fn print_financial_report_snapshot(data: &Value) {
33823382

33833383
// ── macrodata ────────────────────────────────────────────────────────────────
33843384

3385-
use longbridge::fundamental::{Macrodata, MacrodataIndicator, MacrodataResponse};
3385+
use longbridge::fundamental::{
3386+
Macrodata, MacrodataCountry, MacrodataIndicator, MacrodataIndicatorListResponse,
3387+
MacrodataResponse,
3388+
};
33863389

33873390
fn ml_text(t: &longbridge::fundamental::MultiLanguageText) -> &str {
33883391
if !t.simplified_chinese.is_empty() {
@@ -3394,12 +3397,13 @@ fn ml_text(t: &longbridge::fundamental::MultiLanguageText) -> &str {
33943397
}
33953398
}
33963399

3397-
fn print_macrodata_list(indicators: &[MacrodataIndicator]) {
3398-
if indicators.is_empty() {
3400+
fn print_macrodata_list(resp: &MacrodataIndicatorListResponse) {
3401+
if resp.data.is_empty() {
33993402
println!("No indicators found.");
34003403
return;
34013404
}
3402-
let rows: Vec<Vec<String>> = indicators
3405+
let rows: Vec<Vec<String>> = resp
3406+
.data
34033407
.iter()
34043408
.map(|i| {
34053409
let name = ml_text(&i.name);
@@ -3418,6 +3422,7 @@ fn print_macrodata_list(indicators: &[MacrodataIndicator]) {
34183422
]
34193423
})
34203424
.collect();
3425+
println!("Total: {}", resp.count);
34213426
super::output::print_table(
34223427
&["Code", "Name", "Category", "Country", "Frequency", "Source"],
34233428
rows,
@@ -3528,9 +3533,22 @@ fn macrodata_record_to_json(r: &Macrodata) -> Value {
35283533
})
35293534
}
35303535

3536+
fn parse_country(s: &str) -> Option<MacrodataCountry> {
3537+
match s.to_uppercase().as_str() {
3538+
"HK" => Some(MacrodataCountry::HongKong),
3539+
"CN" => Some(MacrodataCountry::China),
3540+
"US" => Some(MacrodataCountry::UnitedStates),
3541+
"EU" => Some(MacrodataCountry::EuroZone),
3542+
"JP" => Some(MacrodataCountry::Japan),
3543+
"SG" => Some(MacrodataCountry::Singapore),
3544+
_ => None,
3545+
}
3546+
}
3547+
35313548
/// List all macroeconomic indicators, or query historical data for one indicator.
35323549
pub async fn cmd_macrodata(
35333550
code: Option<String>,
3551+
country: Option<String>,
35343552
start: Option<String>,
35353553
end: Option<String>,
35363554
limit: Option<u32>,
@@ -3546,39 +3564,62 @@ pub async fn cmd_macrodata(
35463564
None => {
35473565
let limit_val = limit.unwrap_or(1000);
35483566
let offset = (page.saturating_sub(1)) * limit_val;
3567+
let country_filter = country
3568+
.as_deref()
3569+
.map(|c| {
3570+
parse_country(c).ok_or_else(|| {
3571+
anyhow::anyhow!("Unknown country '{c}'. Use: HK, CN, US, EU, JP, SG")
3572+
})
3573+
})
3574+
.transpose()?;
35493575
if verbose {
3550-
eprintln!("* macrodata_indicators(offset={offset}, limit={limit_val})");
3576+
eprintln!(
3577+
"* macrodata_indicators(country={:?}, offset={offset}, limit={limit_val})",
3578+
country.as_deref().unwrap_or("-")
3579+
);
35513580
}
3552-
let indicators = ctx
3553-
.macrodata_indicators(Some(offset as i32), Some(limit_val as i32))
3581+
let resp = ctx
3582+
.macrodata_indicators(
3583+
country_filter,
3584+
Some(offset.cast_signed()),
3585+
Some(limit_val.cast_signed()),
3586+
)
35543587
.await?;
35553588
match format {
35563589
OutputFormat::Json => {
3557-
let arr: Vec<Value> =
3558-
indicators.iter().map(macrodata_indicator_to_json).collect();
3559-
print_json(&Value::Array(arr));
3590+
let json = serde_json::json!({
3591+
"count": resp.count,
3592+
"list": resp.data.iter().map(macrodata_indicator_to_json).collect::<Vec<_>>(),
3593+
});
3594+
print_json(&json);
35603595
}
3561-
OutputFormat::Pretty => print_macrodata_list(&indicators),
3596+
OutputFormat::Pretty => print_macrodata_list(&resp),
35623597
}
35633598
}
35643599
Some(ref indicator_code) => {
3600+
let limit_val = limit.unwrap_or(20);
3601+
let offset = (page.saturating_sub(1)) * limit_val;
35653602
if verbose {
35663603
eprintln!(
3567-
"* macrodata(code={indicator_code}, start={}, end={}, limit={})",
3604+
"* macrodata(code={indicator_code}, start={}, end={}, offset={offset}, limit={limit_val})",
35683605
start.as_deref().unwrap_or("-"),
35693606
end.as_deref().unwrap_or("-"),
3570-
limit.unwrap_or(20),
35713607
);
35723608
}
35733609
let resp = ctx
3574-
.macrodata(indicator_code.clone(), start, end, limit.map(|l| l as i32))
3610+
.macrodata(
3611+
indicator_code.clone(),
3612+
start,
3613+
end,
3614+
Some(offset.cast_signed()),
3615+
Some(limit_val.cast_signed()),
3616+
)
35753617
.await
35763618
.map_err(|e| {
35773619
let msg = e.to_string();
35783620
if msg.contains("null") || msg.contains("deserialize") {
35793621
anyhow::anyhow!(
3580-
"Indicator code '{}' not found or returned no data",
3581-
indicator_code
3622+
"Indicator code '{indicator_code}' not found or returned no data"
35823623
)
35833624
} else {
35843625
anyhow::Error::from(e)
@@ -3587,6 +3628,7 @@ pub async fn cmd_macrodata(
35873628
match format {
35883629
OutputFormat::Json => {
35893630
let json = serde_json::json!({
3631+
"count": resp.count,
35903632
"info": macrodata_indicator_to_json(&resp.info),
35913633
"data": resp.data.iter().map(macrodata_record_to_json).collect::<Vec<_>>(),
35923634
});

src/cli/mod.rs

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,10 @@ pub enum Commands {
550550
Macrodata {
551551
/// Indicator code (from `longbridge macrodata` list output). Omit to list all indicators.
552552
code: Option<String>,
553+
/// Filter by country (list only).
554+
/// Values: HK, CN, US, EU, JP, SG
555+
#[arg(long, value_name = "COUNTRY")]
556+
country: Option<String>,
553557
/// Filter start date for historical data (YYYY-MM-DD)
554558
#[arg(long)]
555559
start: Option<String>,
@@ -561,7 +565,7 @@ pub enum Commands {
561565
/// With CODE (history): default 20, max 100.
562566
#[arg(long)]
563567
limit: Option<u32>,
564-
/// Page number, 1-based. Only applies to indicator list (without CODE).
568+
/// Page number, 1-based.
565569
#[arg(long, default_value = "1")]
566570
page: u32,
567571
},
@@ -3232,11 +3236,12 @@ pub async fn dispatch(cmd: Commands, format: &OutputFormat, verbose: bool) -> Re
32323236
}
32333237
Commands::Macrodata {
32343238
code,
3239+
country,
32353240
start,
32363241
end,
32373242
limit,
32383243
page,
3239-
} => fundamental::cmd_macrodata(code, start, end, limit, page, format, verbose).await,
3244+
} => fundamental::cmd_macrodata(code, country, start, end, limit, page, format, verbose).await,
32403245
Commands::FinanceCalendar { cmd } => {
32413246
let (event_type, opts, star) = match cmd {
32423247
FinanceCalendarCmd::Report { opts } => ("report", opts, vec![]),

0 commit comments

Comments
 (0)