From 286e89c9edfcad6a44503584c94fa81aedc273b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A2=81=E7=AB=A0=E6=B4=AA?= Date: Fri, 22 May 2026 19:35:27 +0800 Subject: [PATCH 01/26] feat(screener): migrate to /v1/quote/ai/screener/* endpoints - All five screener paths updated to /v1/quote/ai/screener/* prefix - screener_recommend_strategies and screener_user_strategies gain a required `market` query parameter across Rust, Python, Node.js, Java, C - screener_strategy(id) switches from ?id= query param to /{id} path param - Blocking wrapper, all language bindings, Python .pyi stubs, and C header updated Co-Authored-By: Claude Sonnet 4.6 (1M context) --- CHANGELOG.md | 6 +++ c/csrc/include/longbridge.h | 2 + c/src/screener_context/context.rs | 13 +++++-- java/src/screener_context.rs | 12 ++++-- nodejs/src/screener/context.rs | 10 +++-- python/pysrc/longbridge/openapi.pyi | 6 ++- python/src/screener/context.rs | 11 ++++-- python/src/screener/context_async.rs | 10 +++-- rust/src/blocking/screener.rs | 14 +++++-- rust/src/screener/context.rs | 57 ++++++++++++++++++---------- 10 files changed, 96 insertions(+), 45 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e7b058502..ff48d5cf3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + +### Changed + +- **Screener:** all endpoints migrated to `/v1/quote/ai/screener/*`; `screener_recommend_strategies` and `screener_user_strategies` now require a `market` parameter; `screener_strategy(id)` uses a path parameter instead of a query parameter + ## [4.2.0] ### Added diff --git a/c/csrc/include/longbridge.h b/c/csrc/include/longbridge.h index 5cfcd77ac..cb8db05c0 100644 --- a/c/csrc/include/longbridge.h +++ b/c/csrc/include/longbridge.h @@ -10193,6 +10193,7 @@ void lb_screener_context_release(const struct lb_screener_context_t *ctx); * Returns `CScreenerRecommendStrategiesResponse`. */ void lb_screener_context_recommend_strategies(const struct lb_screener_context_t *ctx, + const char *market, lb_async_callback_t callback, void *userdata); @@ -10201,6 +10202,7 @@ void lb_screener_context_recommend_strategies(const struct lb_screener_context_t * Returns `CScreenerUserStrategiesResponse`. */ void lb_screener_context_user_strategies(const struct lb_screener_context_t *ctx, + const char *market, lb_async_callback_t callback, void *userdata); diff --git a/c/src/screener_context/context.rs b/c/src/screener_context/context.rs index 4a027ebee..82c7e8188 100644 --- a/c/src/screener_context/context.rs +++ b/c/src/screener_context/context.rs @@ -38,14 +38,16 @@ pub unsafe extern "C" fn lb_screener_context_release(ctx: *const CScreenerContex #[unsafe(no_mangle)] pub unsafe extern "C" fn lb_screener_context_recommend_strategies( ctx: *const CScreenerContext, + market: *const c_char, callback: CAsyncCallback, userdata: *mut c_void, ) { let ctx_inner = (*ctx).ctx.clone(); + let market = cstr_to_rust(market); execute_async(callback, ctx, userdata, async move { let resp: CCow = CCow::new(CScreenerRecommendStrategiesResponseOwned::from( - ctx_inner.screener_recommend_strategies().await?, + ctx_inner.screener_recommend_strategies(market).await?, )); Ok(resp) }); @@ -56,14 +58,17 @@ pub unsafe extern "C" fn lb_screener_context_recommend_strategies( #[unsafe(no_mangle)] pub unsafe extern "C" fn lb_screener_context_user_strategies( ctx: *const CScreenerContext, + market: *const c_char, callback: CAsyncCallback, userdata: *mut c_void, ) { let ctx_inner = (*ctx).ctx.clone(); + let market = cstr_to_rust(market); execute_async(callback, ctx, userdata, async move { - let resp: CCow = CCow::new( - CScreenerUserStrategiesResponseOwned::from(ctx_inner.screener_user_strategies().await?), - ); + let resp: CCow = + CCow::new(CScreenerUserStrategiesResponseOwned::from( + ctx_inner.screener_user_strategies(market).await?, + )); Ok(resp) }); } diff --git a/java/src/screener_context.rs b/java/src/screener_context.rs index c6b66330d..903c92cb7 100644 --- a/java/src/screener_context.rs +++ b/java/src/screener_context.rs @@ -2,14 +2,14 @@ use std::sync::Arc; use jni::{ JNIEnv, - objects::{JClass, JObject}, + objects::{JClass, JObject, JString}, }; use longbridge::{Config, ScreenerContext}; use crate::{ async_util, error::jni_result, - types::{JavaInteger, get_field}, + types::{FromJValue, JavaInteger, get_field}, }; struct ContextObj { @@ -41,12 +41,14 @@ pub unsafe extern "system" fn Java_com_longbridge_SdkNative_screenerContextRecom mut env: JNIEnv, _class: JClass, context: i64, + market: JString, callback: JObject, ) { jni_result(&mut env, (), |env| { let context = &*(context as *const ContextObj); + let market: String = FromJValue::from_jvalue(env, market.into())?; async_util::execute(env, callback, async move { - let resp = context.ctx.screener_recommend_strategies().await?; + let resp = context.ctx.screener_recommend_strategies(market).await?; Ok(resp) })?; Ok(()) @@ -58,12 +60,14 @@ pub unsafe extern "system" fn Java_com_longbridge_SdkNative_screenerContextUserS mut env: JNIEnv, _class: JClass, context: i64, + market: JString, callback: JObject, ) { jni_result(&mut env, (), |env| { let context = &*(context as *const ContextObj); + let market: String = FromJValue::from_jvalue(env, market.into())?; async_util::execute(env, callback, async move { - let resp = context.ctx.screener_user_strategies().await?; + let resp = context.ctx.screener_user_strategies(market).await?; Ok(resp) })?; Ok(()) diff --git a/nodejs/src/screener/context.rs b/nodejs/src/screener/context.rs index b5b16fbbd..fb9a43fdd 100644 --- a/nodejs/src/screener/context.rs +++ b/nodejs/src/screener/context.rs @@ -25,10 +25,11 @@ impl ScreenerContext { #[napi] pub async fn screener_recommend_strategies( &self, + market: String, ) -> Result { Ok(self .ctx - .screener_recommend_strategies() + .screener_recommend_strategies(market) .await .map_err(ErrorNewType)? .into()) @@ -36,10 +37,13 @@ impl ScreenerContext { /// Get the current user's saved screener strategies #[napi] - pub async fn screener_user_strategies(&self) -> Result { + pub async fn screener_user_strategies( + &self, + market: String, + ) -> Result { Ok(self .ctx - .screener_user_strategies() + .screener_user_strategies(market) .await .map_err(ErrorNewType)? .into()) diff --git a/python/pysrc/longbridge/openapi.pyi b/python/pysrc/longbridge/openapi.pyi index aa3b1cb2d..68678db85 100644 --- a/python/pysrc/longbridge/openapi.pyi +++ b/python/pysrc/longbridge/openapi.pyi @@ -10570,11 +10570,11 @@ class ScreenerContext: def __init__(self, config: Config) -> None: ... - def screener_recommend_strategies(self) -> ScreenerRecommendStrategiesResponse: + def screener_recommend_strategies(self, market: str) -> ScreenerRecommendStrategiesResponse: """Get recommended built-in screener strategies.""" ... - def screener_user_strategies(self) -> ScreenerUserStrategiesResponse: + def screener_user_strategies(self, market: str) -> ScreenerUserStrategiesResponse: """Get the current user's saved screener strategies.""" ... @@ -10605,12 +10605,14 @@ class AsyncScreenerContext: def screener_recommend_strategies( self, + market: str, ) -> Awaitable[ScreenerRecommendStrategiesResponse]: """Get recommended built-in screener strategies. Returns awaitable.""" ... def screener_user_strategies( self, + market: str, ) -> Awaitable[ScreenerUserStrategiesResponse]: """Get the current user's saved screener strategies. Returns awaitable.""" ... diff --git a/python/src/screener/context.rs b/python/src/screener/context.rs index 4030702f7..9c1f0fcc6 100644 --- a/python/src/screener/context.rs +++ b/python/src/screener/context.rs @@ -21,19 +21,22 @@ impl ScreenerContext { } /// Get recommended built-in screener strategies. - fn screener_recommend_strategies(&self) -> PyResult { + fn screener_recommend_strategies( + &self, + market: String, + ) -> PyResult { Ok(self .ctx - .screener_recommend_strategies() + .screener_recommend_strategies(market) .map_err(ErrorNewType)? .into()) } /// Get the current user's saved screener strategies. - fn screener_user_strategies(&self) -> PyResult { + fn screener_user_strategies(&self, market: String) -> PyResult { Ok(self .ctx - .screener_user_strategies() + .screener_user_strategies(market) .map_err(ErrorNewType)? .into()) } diff --git a/python/src/screener/context_async.rs b/python/src/screener/context_async.rs index ddd026999..ce428cffc 100644 --- a/python/src/screener/context_async.rs +++ b/python/src/screener/context_async.rs @@ -22,11 +22,11 @@ impl AsyncScreenerContext { } /// Get recommended built-in screener strategies. Returns awaitable. - fn screener_recommend_strategies(&self, py: Python<'_>) -> PyResult> { + fn screener_recommend_strategies(&self, py: Python<'_>, market: String) -> PyResult> { let ctx = self.ctx.clone(); pyo3_async_runtimes::tokio::future_into_py(py, async move { Ok(ScreenerRecommendStrategiesResponse::from( - ctx.screener_recommend_strategies() + ctx.screener_recommend_strategies(market) .await .map_err(ErrorNewType)?, )) @@ -35,11 +35,13 @@ impl AsyncScreenerContext { } /// Get the current user's saved screener strategies. Returns awaitable. - fn screener_user_strategies(&self, py: Python<'_>) -> PyResult> { + fn screener_user_strategies(&self, py: Python<'_>, market: String) -> PyResult> { let ctx = self.ctx.clone(); pyo3_async_runtimes::tokio::future_into_py(py, async move { Ok(ScreenerUserStrategiesResponse::from( - ctx.screener_user_strategies().await.map_err(ErrorNewType)?, + ctx.screener_user_strategies(market) + .await + .map_err(ErrorNewType)?, )) }) .map(|b| b.unbind()) diff --git a/rust/src/blocking/screener.rs b/rust/src/blocking/screener.rs index b5cbd3e1b..37765b96b 100644 --- a/rust/src/blocking/screener.rs +++ b/rust/src/blocking/screener.rs @@ -35,15 +35,21 @@ impl ScreenerContextSync { } /// Get recommended built-in screener strategies - pub fn screener_recommend_strategies(&self) -> Result { + pub fn screener_recommend_strategies( + &self, + market: impl Into + Send + 'static, + ) -> Result { self.rt - .call(|ctx| async move { ctx.screener_recommend_strategies().await }) + .call(|ctx| async move { ctx.screener_recommend_strategies(market).await }) } /// Get the current user's saved screener strategies - pub fn screener_user_strategies(&self) -> Result { + pub fn screener_user_strategies( + &self, + market: impl Into + Send + 'static, + ) -> Result { self.rt - .call(|ctx| async move { ctx.screener_user_strategies().await }) + .call(|ctx| async move { ctx.screener_user_strategies(market).await }) } /// Get detail for one screener strategy by ID diff --git a/rust/src/screener/context.rs b/rust/src/screener/context.rs index d17746aaf..1ea061d0b 100644 --- a/rust/src/screener/context.rs +++ b/rust/src/screener/context.rs @@ -46,7 +46,7 @@ impl ScreenerContext { self.0.log_subscriber.clone() } - async fn get(&self, path: &'static str, query: Q) -> Result + async fn get(&self, path: &str, query: Q) -> Result where R: DeserializeOwned + Send + Sync + 'static, Q: Serialize + Send + Sync, @@ -63,7 +63,7 @@ impl ScreenerContext { .0) } - async fn post(&self, path: &'static str, body: B) -> Result + async fn post(&self, path: &str, body: B) -> Result where R: DeserializeOwned + Send + Sync + 'static, B: std::fmt::Debug + Serialize + Send + Sync + 'static, @@ -84,14 +84,22 @@ impl ScreenerContext { /// Get recommended built-in screener strategies. /// - /// Path: `GET /v1/quote/screener/strategies/recommend` + /// Path: `GET /v1/quote/ai/screener/strategies/recommend` pub async fn screener_recommend_strategies( &self, + market: impl Into, ) -> Result { #[derive(Serialize)] - struct Empty {} + struct Query { + market: String, + } let raw: serde_json::Value = self - .get("/v1/quote/screener/strategies/recommend", Empty {}) + .get( + "/v1/quote/ai/screener/strategies/recommend", + Query { + market: market.into(), + }, + ) .await?; Ok(ScreenerRecommendStrategiesResponse { data: raw }) } @@ -100,12 +108,22 @@ impl ScreenerContext { /// Get the current user's saved screener strategies. /// - /// Path: `GET /v1/quote/screener/strategies/mine` - pub async fn screener_user_strategies(&self) -> Result { + /// Path: `GET /v1/quote/ai/screener/strategies/mine` + pub async fn screener_user_strategies( + &self, + market: impl Into, + ) -> Result { #[derive(Serialize)] - struct Empty {} + struct Query { + market: String, + } let raw: serde_json::Value = self - .get("/v1/quote/screener/strategies/mine", Empty {}) + .get( + "/v1/quote/ai/screener/strategies/mine", + Query { + market: market.into(), + }, + ) .await?; Ok(ScreenerUserStrategiesResponse { data: raw }) } @@ -114,15 +132,12 @@ impl ScreenerContext { /// Get detail for one screener strategy by ID. /// - /// Path: `GET /v1/quote/screener/strategy?id=` + /// Path: `GET /v1/quote/ai/screener/strategy/{id}` pub async fn screener_strategy(&self, id: i64) -> Result { + let path = format!("/v1/quote/ai/screener/strategy/{id}"); #[derive(Serialize)] - struct Query { - id: i64, - } - let raw: serde_json::Value = self - .get("/v1/quote/screener/strategy", Query { id }) - .await?; + struct Empty {} + let raw: serde_json::Value = self.get(&path, Empty {}).await?; Ok(ScreenerStrategyResponse { data: raw }) } @@ -130,7 +145,7 @@ impl ScreenerContext { /// Search / screen securities using a strategy. /// - /// Path: `POST /v1/quote/screener/search` + /// Path: `POST /v1/quote/ai/screener/search` /// /// When `strategy_id` is `Some`, it is included in the request body. /// When `None`, only `market`, `page`, and `size` are sent (custom @@ -152,7 +167,7 @@ impl ScreenerContext { } let raw: serde_json::Value = self .post( - "/v1/quote/screener/search", + "/v1/quote/ai/screener/search", Body { market: market.into(), strategy_id, @@ -168,11 +183,13 @@ impl ScreenerContext { /// Get all available screener indicator definitions. /// - /// Path: `GET /v1/quote/screener/indicators` + /// Path: `GET /v1/quote/ai/screener/indicators` pub async fn screener_indicators(&self) -> Result { #[derive(Serialize)] struct Empty {} - let raw: serde_json::Value = self.get("/v1/quote/screener/indicators", Empty {}).await?; + let raw: serde_json::Value = self + .get("/v1/quote/ai/screener/indicators", Empty {}) + .await?; Ok(ScreenerIndicatorsResponse { data: raw }) } } From 16d720063f3090f207cafad662890a20bde87725 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A2=81=E7=AB=A0=E6=B4=AA?= Date: Fri, 22 May 2026 19:52:35 +0800 Subject: [PATCH 02/26] =?UTF-8?q?fix:=20rename=20Recommended=20=E2=86=92?= =?UTF-8?q?=20Preset=20in=20screener=5Frecommend=5Fstrategies=20doc=20stri?= =?UTF-8?q?ngs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- python/pysrc/longbridge/openapi.pyi | 2 +- rust/src/screener/context.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/python/pysrc/longbridge/openapi.pyi b/python/pysrc/longbridge/openapi.pyi index 68678db85..66e5e5145 100644 --- a/python/pysrc/longbridge/openapi.pyi +++ b/python/pysrc/longbridge/openapi.pyi @@ -10571,7 +10571,7 @@ class ScreenerContext: def __init__(self, config: Config) -> None: ... def screener_recommend_strategies(self, market: str) -> ScreenerRecommendStrategiesResponse: - """Get recommended built-in screener strategies.""" + """Get preset built-in screener strategies.""" ... def screener_user_strategies(self, market: str) -> ScreenerUserStrategiesResponse: diff --git a/rust/src/screener/context.rs b/rust/src/screener/context.rs index 1ea061d0b..b221954b2 100644 --- a/rust/src/screener/context.rs +++ b/rust/src/screener/context.rs @@ -82,7 +82,7 @@ impl ScreenerContext { // ── screener_recommend_strategies ───────────────────────────── - /// Get recommended built-in screener strategies. + /// Get preset built-in screener strategies. /// /// Path: `GET /v1/quote/ai/screener/strategies/recommend` pub async fn screener_recommend_strategies( From df281cbff5d2730324f0a3fe82761b8503f31c8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A2=81=E7=AB=A0=E6=B4=AA?= Date: Fri, 22 May 2026 20:03:49 +0800 Subject: [PATCH 03/26] =?UTF-8?q?fix(screener):=20fix=20async=20pyi=20docs?= =?UTF-8?q?tring=20=E2=80=94=20'recommended'=20=E2=86=92=20'preset'?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- python/pysrc/longbridge/openapi.pyi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/pysrc/longbridge/openapi.pyi b/python/pysrc/longbridge/openapi.pyi index 66e5e5145..d6e9b2f1a 100644 --- a/python/pysrc/longbridge/openapi.pyi +++ b/python/pysrc/longbridge/openapi.pyi @@ -10607,7 +10607,7 @@ class AsyncScreenerContext: self, market: str, ) -> Awaitable[ScreenerRecommendStrategiesResponse]: - """Get recommended built-in screener strategies. Returns awaitable.""" + """Get preset built-in screener strategies. Returns awaitable.""" ... def screener_user_strategies( From a8a4070c131fbeeb8babe16c4643eeb34d55e748 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A2=81=E7=AB=A0=E6=B4=AA?= Date: Fri, 22 May 2026 20:36:45 +0800 Subject: [PATCH 04/26] feat(market): strip ib_ prefix from rank_categories keys; auto-add ib_ in rank_list --- rust/src/market/context.rs | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/rust/src/market/context.rs b/rust/src/market/context.rs index 4edba7306..e0a27b470 100644 --- a/rust/src/market/context.rs +++ b/rust/src/market/context.rs @@ -391,9 +391,27 @@ impl MarketContext { pub async fn rank_categories(&self) -> Result { #[derive(Serialize)] struct Empty {} - let raw: serde_json::Value = self + let mut raw: serde_json::Value = self .get("/v1/quote/market/rank/categories", Empty {}) .await?; + // Strip the "ib_" prefix from all key fields so callers get clean keys + // that can be passed back to rank_list without the prefix. + if let Some(tags) = raw["first_tags"].as_array_mut() { + for tag in tags.iter_mut() { + if let Some(k) = tag["key"].as_str() { + let stripped = k.strip_prefix("ib_").unwrap_or(k).to_string(); + tag["key"] = serde_json::Value::String(stripped); + } + if let Some(subs) = tag["second_tags"].as_array_mut() { + for sub in subs.iter_mut() { + if let Some(sk) = sub["key"].as_str() { + let stripped = sk.strip_prefix("ib_").unwrap_or(sk).to_string(); + sub["key"] = serde_json::Value::String(stripped); + } + } + } + } + } Ok(RankCategoriesResponse { data: raw }) } @@ -413,11 +431,18 @@ impl MarketContext { delay_bmp: &'static str, need_article: &'static str, } + let key_str = key.into(); + // Add "ib_" prefix if the caller passed a clean key (without it). + let api_key = if key_str.starts_with("ib_") { + key_str + } else { + format!("ib_{key_str}") + }; let raw: serde_json::Value = self .get( "/v1/quote/market/rank/list", Query { - key: key.into(), + key: api_key, delay_bmp: "false", need_article: if need_article { "true" } else { "false" }, }, From 6b1446e044e97593f8f2620b696fa5f1436b01f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A2=81=E7=AB=A0=E6=B4=AA?= Date: Sat, 23 May 2026 15:18:40 +0800 Subject: [PATCH 05/26] feat(screener): strip filter_ prefix, build tech_values, fix Mode A strategy parsing - screener_strategy: strip filter_ from filter.filters[].key in response - screener_indicators: strip filter_ from groups[].indicators[].key and build tech_values map from tech_indicators before returning - screener_search: Mode A now fetches strategy from AI endpoint (/v1/quote/ai/screener/strategy/{id}), derives market from response, and sends filter.filters[] with DEFAULT_RETURNS; Mode B accepts "KEY:MIN:MAX" condition strings; response items[].indicators[].key has filter_ stripped; page is now 0-indexed - Add conditions/show params to all SDK bindings (Python, Node.js, C, Java) Co-Authored-By: Claude Sonnet 4.6 (1M context) --- CHANGELOG.md | 2 + c/src/screener_context/context.rs | 2 +- java/src/screener_context.rs | 2 +- nodejs/src/screener/context.rs | 16 +- python/pysrc/longbridge/openapi.pyi | 35 +++- python/src/screener/context.rs | 6 +- python/src/screener/context_async.rs | 7 +- rust/src/blocking/screener.rs | 5 +- rust/src/screener/context.rs | 239 ++++++++++++++++++++++++--- 9 files changed, 276 insertions(+), 38 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ff48d5cf3..0f85ad429 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - **Screener:** all endpoints migrated to `/v1/quote/ai/screener/*`; `screener_recommend_strategies` and `screener_user_strategies` now require a `market` parameter; `screener_strategy(id)` uses a path parameter instead of a query parameter +- **Screener:** `screener_strategy` and `screener_indicators` now strip the `filter_` prefix from response keys before returning; `screener_indicators` additionally builds `tech_values` from `tech_indicators` +- **Screener:** `screener_search` gains `conditions` and `show` parameters; Mode A fetches the strategy via AI endpoint and derives `market` from the response; Mode B accepts `"KEY:MIN:MAX"` condition strings; response `items[].indicators[].key` values have `filter_` stripped; `page` is now 0-indexed and defaults to 0 ## [4.2.0] diff --git a/c/src/screener_context/context.rs b/c/src/screener_context/context.rs index 82c7e8188..cb3c44579 100644 --- a/c/src/screener_context/context.rs +++ b/c/src/screener_context/context.rs @@ -115,7 +115,7 @@ pub unsafe extern "C" fn lb_screener_context_search( let resp: CCow = CCow::new(CScreenerSearchResponseOwned::from( ctx_inner - .screener_search(market, strategy_id, page, size) + .screener_search(market, strategy_id, vec![], vec![], page, size) .await?, )); Ok(resp) diff --git a/java/src/screener_context.rs b/java/src/screener_context.rs index 903c92cb7..2482094d1 100644 --- a/java/src/screener_context.rs +++ b/java/src/screener_context.rs @@ -111,7 +111,7 @@ pub unsafe extern "system" fn Java_com_longbridge_SdkNative_screenerContextSearc async_util::execute(env, callback, async move { let resp = context .ctx - .screener_search(market, strategy_id, page, size) + .screener_search(market, strategy_id, vec![], vec![], page, size) .await?; Ok(resp) })?; diff --git a/nodejs/src/screener/context.rs b/nodejs/src/screener/context.rs index fb9a43fdd..5c14f3a1e 100644 --- a/nodejs/src/screener/context.rs +++ b/nodejs/src/screener/context.rs @@ -60,18 +60,30 @@ impl ScreenerContext { .into()) } - /// Search / screen securities using a strategy + /// Search / screen securities using a strategy or custom conditions. + /// + /// When `strategyId` is given (Mode A), the strategy is fetched from the AI + /// endpoint and its filters drive the search. The market is taken from the + /// strategy response. + /// + /// When `strategyId` is `null` / `undefined` (Mode B), `conditions` must be + /// `"KEY:MIN:MAX"` strings and `market` is used directly. + /// + /// `filter_` is stripped from every `items[].indicators[].key` in the + /// response before it is returned. #[napi] pub async fn screener_search( &self, market: String, strategy_id: Option, + #[napi(ts_arg_type = "string[]")] conditions: Vec, + #[napi(ts_arg_type = "string[]")] show: Vec, page: u32, size: u32, ) -> Result { Ok(self .ctx - .screener_search(market, strategy_id, page, size) + .screener_search(market, strategy_id, conditions, show, page, size) .await .map_err(ErrorNewType)? .into()) diff --git a/python/pysrc/longbridge/openapi.pyi b/python/pysrc/longbridge/openapi.pyi index d6e9b2f1a..74dab75e7 100644 --- a/python/pysrc/longbridge/openapi.pyi +++ b/python/pysrc/longbridge/openapi.pyi @@ -10586,10 +10586,23 @@ class ScreenerContext: self, market: str, strategy_id: Optional[int] = None, - page: int = 1, + conditions: List[str] = [], + show: List[str] = [], + page: int = 0, size: int = 20, ) -> ScreenerSearchResponse: - """Search / screen securities using a strategy.""" + """Search / screen securities using a strategy or custom conditions. + + When *strategy_id* is given (Mode A), the strategy is fetched from the AI + endpoint and its filters are forwarded to the search request. The + ``market`` is taken from the strategy response. + + When *strategy_id* is ``None`` (Mode B), *conditions* must be provided as + ``"KEY:MIN:MAX"`` strings and *market* is used directly. + + ``filter_`` is stripped from every ``items[].indicators[].key`` in the + response before it is returned. + """ ... def screener_indicators(self) -> ScreenerIndicatorsResponse: @@ -10627,10 +10640,24 @@ class AsyncScreenerContext: self, market: str, strategy_id: Optional[int] = None, - page: int = 1, + conditions: List[str] = [], + show: List[str] = [], + page: int = 0, size: int = 20, ) -> Awaitable[ScreenerSearchResponse]: - """Search / screen securities using a strategy. Returns awaitable.""" + """Search / screen securities using a strategy or custom conditions. + Returns awaitable. + + When *strategy_id* is given (Mode A), the strategy is fetched from the AI + endpoint and its filters are forwarded to the search request. The + ``market`` is taken from the strategy response. + + When *strategy_id* is ``None`` (Mode B), *conditions* must be provided as + ``"KEY:MIN:MAX"`` strings and *market* is used directly. + + ``filter_`` is stripped from every ``items[].indicators[].key`` in the + response before it is returned. + """ ... def screener_indicators(self) -> Awaitable[ScreenerIndicatorsResponse]: diff --git a/python/src/screener/context.rs b/python/src/screener/context.rs index 9c1f0fcc6..279500995 100644 --- a/python/src/screener/context.rs +++ b/python/src/screener/context.rs @@ -47,17 +47,19 @@ impl ScreenerContext { } /// Search / screen securities using a strategy. - #[pyo3(signature = (market, strategy_id = None, page = 1, size = 20))] + #[pyo3(signature = (market, strategy_id = None, conditions = vec![], show = vec![], page = 0, size = 20))] fn screener_search( &self, market: String, strategy_id: Option, + conditions: Vec, + show: Vec, page: u32, size: u32, ) -> PyResult { Ok(self .ctx - .screener_search(market, strategy_id, page, size) + .screener_search(market, strategy_id, conditions, show, page, size) .map_err(ErrorNewType)? .into()) } diff --git a/python/src/screener/context_async.rs b/python/src/screener/context_async.rs index ce428cffc..c3b3e9d9e 100644 --- a/python/src/screener/context_async.rs +++ b/python/src/screener/context_async.rs @@ -59,19 +59,22 @@ impl AsyncScreenerContext { } /// Search / screen securities using a strategy. Returns awaitable. - #[pyo3(signature = (market, strategy_id = None, page = 1, size = 20))] + #[allow(clippy::too_many_arguments)] + #[pyo3(signature = (market, strategy_id = None, conditions = vec![], show = vec![], page = 0, size = 20))] fn screener_search( &self, py: Python<'_>, market: String, strategy_id: Option, + conditions: Vec, + show: Vec, page: u32, size: u32, ) -> PyResult> { let ctx = self.ctx.clone(); pyo3_async_runtimes::tokio::future_into_py(py, async move { Ok(ScreenerSearchResponse::from( - ctx.screener_search(market, strategy_id, page, size) + ctx.screener_search(market, strategy_id, conditions, show, page, size) .await .map_err(ErrorNewType)?, )) diff --git a/rust/src/blocking/screener.rs b/rust/src/blocking/screener.rs index 37765b96b..81beeb93b 100644 --- a/rust/src/blocking/screener.rs +++ b/rust/src/blocking/screener.rs @@ -63,11 +63,14 @@ impl ScreenerContextSync { &self, market: impl Into + Send + 'static, strategy_id: Option, + conditions: Vec, + show: Vec, page: u32, size: u32, ) -> Result { self.rt.call(move |ctx| async move { - ctx.screener_search(market, strategy_id, page, size).await + ctx.screener_search(market, strategy_id, conditions, show, page, size) + .await }) } diff --git a/rust/src/screener/context.rs b/rust/src/screener/context.rs index b221954b2..979542688 100644 --- a/rust/src/screener/context.rs +++ b/rust/src/screener/context.rs @@ -133,50 +133,179 @@ impl ScreenerContext { /// Get detail for one screener strategy by ID. /// /// Path: `GET /v1/quote/ai/screener/strategy/{id}` + /// + /// The `filter_` prefix is stripped from every `filters[].key` before + /// returning so callers see clean keys like `pettm` instead of + /// `filter_pettm`. pub async fn screener_strategy(&self, id: i64) -> Result { let path = format!("/v1/quote/ai/screener/strategy/{id}"); #[derive(Serialize)] struct Empty {} - let raw: serde_json::Value = self.get(&path, Empty {}).await?; + let mut raw: serde_json::Value = self.get(&path, Empty {}).await?; + // Strip filter_ prefix from filter.filters[].key + if let Some(filters) = raw["filter"]["filters"].as_array_mut() { + for f in filters.iter_mut() { + if let Some(k) = f["key"].as_str() { + let stripped = k.strip_prefix("filter_").unwrap_or(k).to_string(); + f["key"] = serde_json::Value::String(stripped); + } + } + } Ok(ScreenerStrategyResponse { data: raw }) } // ── screener_search ─────────────────────────────────────────── - /// Search / screen securities using a strategy. + /// Default return columns always included in a screener search request. + const DEFAULT_RETURNS: &'static [&'static str] = &[ + "filter_prevclose", + "filter_prevchg", + "filter_marketcap", + "filter_salesgrowthyoy", + "filter_pettm", + "filter_pbmrq", + "filter_industry", + ]; + + /// Search / screen securities using a strategy or custom conditions. /// /// Path: `POST /v1/quote/ai/screener/search` /// - /// When `strategy_id` is `Some`, it is included in the request body. - /// When `None`, only `market`, `page`, and `size` are sent (custom - /// filter support is out of scope for this SDK). + /// ## Mode A — strategy ID given + /// + /// When `strategy_id` is `Some`, the strategy is fetched from + /// `GET /v1/quote/ai/screener/strategy/{id}` and its `filter.filters[]` + /// are forwarded to the search endpoint together with + /// [`DEFAULT_RETURNS`]. The `market` is taken from the strategy + /// response (falls back to `"US"` if absent or `"-"`). + /// + /// ## Mode B — custom conditions + /// + /// When `strategy_id` is `None` and `conditions` is non-empty each + /// element is either a `"KEY:MIN:MAX"` string **or** a JSON object with + /// `key`, `min`, `max`, and optional `tech_values` fields. The + /// supplied `market` is used directly. `DEFAULT_RETURNS` plus every + /// condition key are added to the `returns` list. + /// + /// The `filter_` prefix is stripped from every `items[].indicators[].key` + /// in the response before it is returned to the caller. + /// + /// `page` is 0-indexed. pub async fn screener_search( &self, market: impl Into, strategy_id: Option, + conditions: Vec, + show: Vec, page: u32, size: u32, ) -> Result { - #[derive(Debug, Serialize)] - struct Body { - market: String, - #[serde(skip_serializing_if = "Option::is_none")] - strategy_id: Option, - page: u32, - size: u32, + let market: String = market.into(); + + // ── build filters and effective market ────────────────────────────── + let (effective_market, filters) = if let Some(sid) = strategy_id { + // Mode A: fetch strategy from AI endpoint + let path = format!("/v1/quote/ai/screener/strategy/{sid}"); + #[derive(Serialize)] + struct Empty {} + let strategy: serde_json::Value = self.get(&path, Empty {}).await?; + + let mkt_val = strategy["market"].as_str().unwrap_or("US").to_uppercase(); + let mkt = if mkt_val.is_empty() || mkt_val == "-" { + "US".to_string() + } else { + mkt_val + }; + + let mut filters: Vec = Vec::new(); + if let Some(f) = strategy["filter"]["filters"].as_array() { + for ind in f { + let key = ind["key"].as_str().unwrap_or("").to_string(); + if key.is_empty() { + continue; + } + let min = ind["min"].as_str().unwrap_or("").to_string(); + let max = ind["max"].as_str().unwrap_or("").to_string(); + let tech_values = if ind["tech_values"].is_object() { + ind["tech_values"].clone() + } else { + serde_json::json!({}) + }; + filters.push(serde_json::json!({ + "key": key, + "min": min, + "max": max, + "tech_values": tech_values, + })); + } + } + (mkt, filters) + } else { + // Mode B: custom conditions ("KEY:MIN:MAX" strings) + let filters: Vec = conditions + .iter() + .filter_map(|cond| { + let parts: Vec<&str> = cond.splitn(3, ':').collect(); + if parts.is_empty() || parts[0].is_empty() { + return None; + } + let key = parts[0].to_string(); + let min = parts.get(1).copied().unwrap_or("").to_string(); + let max = parts.get(2).copied().unwrap_or("").to_string(); + Some(serde_json::json!({ + "key": key, + "min": min, + "max": max, + "tech_values": {}, + })) + }) + .collect(); + (market, filters) + }; + + // ── build returns list ─────────────────────────────────────────────── + let mut returns: Vec = Self::DEFAULT_RETURNS + .iter() + .map(|s| s.to_string()) + .collect(); + // add keys from filters (with filter_ prefix for the API) + for f in &filters { + if let Some(k) = f["key"].as_str() { + let api_key = if k.starts_with("filter_") { + k.to_string() + } else { + format!("filter_{k}") + }; + if !returns.contains(&api_key) { + returns.push(api_key); + } + } } - let raw: serde_json::Value = self - .post( - "/v1/quote/ai/screener/search", - Body { - market: market.into(), - strategy_id, - page, - size, - }, - ) - .await?; - Ok(ScreenerSearchResponse { data: raw }) + // add extra columns requested by the caller + for s in &show { + let api_key = if s.starts_with("filter_") { + s.clone() + } else { + format!("filter_{s}") + }; + if !returns.contains(&api_key) { + returns.push(api_key); + } + } + + // ── POST request ──────────────────────────────────────────────────── + let body = serde_json::json!({ + "market": effective_market, + "filters": filters, + "returns": returns, + "page": page, + "size": size, + }); + + let raw: serde_json::Value = self.post("/v1/quote/ai/screener/search", body).await?; + Ok(ScreenerSearchResponse { + data: strip_filter_prefix_from_search_results(raw), + }) } // ── screener_indicators ─────────────────────────────────────── @@ -184,12 +313,72 @@ impl ScreenerContext { /// Get all available screener indicator definitions. /// /// Path: `GET /v1/quote/ai/screener/indicators` + /// + /// Post-processing applied before returning: + /// - `filter_` prefix is stripped from every `groups[].indicators[].key` + /// - `tech_values` is built from `tech_indicators`: `{tech_key: [{value, + /// label}]}` pub async fn screener_indicators(&self) -> Result { #[derive(Serialize)] struct Empty {} - let raw: serde_json::Value = self + let mut raw: serde_json::Value = self .get("/v1/quote/ai/screener/indicators", Empty {}) .await?; + if let Some(groups) = raw["groups"].as_array_mut() { + for group in groups.iter_mut() { + if let Some(indicators) = group["indicators"].as_array_mut() { + for ind in indicators.iter_mut() { + // Strip filter_ prefix from key + if let Some(k) = ind["key"].as_str() { + let stripped = k.strip_prefix("filter_").unwrap_or(k).to_string(); + ind["key"] = serde_json::Value::String(stripped); + } + // Build tech_values from tech_indicators + if let Some(tech_inds) = ind["tech_indicators"].as_array().cloned() { + let tv: serde_json::Map = tech_inds + .iter() + .filter_map(|ti| { + let key = ti["tech_key"].as_str()?.to_string(); + let opts: Vec = ti["tech_items"] + .as_array() + .unwrap_or(&vec![]) + .iter() + .map(|item| { + serde_json::json!({ + "value": item["item_value"].as_str().unwrap_or(""), + "label": item["item_name"].as_str().unwrap_or(""), + }) + }) + .collect(); + Some((key, serde_json::Value::Array(opts))) + }) + .collect(); + if !tv.is_empty() { + ind["tech_values"] = serde_json::Value::Object(tv); + } + } + } + } + } + } Ok(ScreenerIndicatorsResponse { data: raw }) } } + +/// Strip `filter_` prefix from every `items[].indicators[].key` in a raw +/// screener search result. +fn strip_filter_prefix_from_search_results(mut raw: serde_json::Value) -> serde_json::Value { + if let Some(items) = raw["items"].as_array_mut() { + for item in items.iter_mut() { + if let Some(indicators) = item["indicators"].as_array_mut() { + for ind in indicators.iter_mut() { + if let Some(k) = ind["key"].as_str() { + let stripped = k.strip_prefix("filter_").unwrap_or(k).to_string(); + ind["key"] = serde_json::Value::String(stripped); + } + } + } + } + } + raw +} From 75e33aeb887cbf6ff7d258fe9d387b7a46c0bccb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A2=81=E7=AB=A0=E6=B4=AA?= Date: Sat, 23 May 2026 15:26:13 +0800 Subject: [PATCH 06/26] fix(cpp): add market param to screener_recommend/user_strategies C++ bindings The C functions gained a 'market' param; remove conflicting forward decls (already declared in longbridge.h) and add market to hpp/cpp signatures. Co-Authored-By: Claude Sonnet 4.6 (1M context) --- cpp/include/screener_context.hpp | 8 +++++--- cpp/src/screener_context.cpp | 11 +++++------ 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/cpp/include/screener_context.hpp b/cpp/include/screener_context.hpp index 843bb0fc5..2c6adb121 100644 --- a/cpp/include/screener_context.hpp +++ b/cpp/include/screener_context.hpp @@ -24,11 +24,13 @@ class ScreenerContext static ScreenerContext create(const Config& config); - /// Get recommended built-in screener strategies (raw JSON string) - void screener_recommend_strategies(AsyncCallback callback) const; + /// Get preset screener strategies for a given market (raw JSON string) + void screener_recommend_strategies(const std::string& market, + AsyncCallback callback) const; /// Get the current user's saved screener strategies (raw JSON string) - void screener_user_strategies(AsyncCallback callback) const; + void screener_user_strategies(const std::string& market, + AsyncCallback callback) const; /// Get detail for one screener strategy by ID (raw JSON string) void screener_strategy(int64_t id, AsyncCallback callback) const; diff --git a/cpp/src/screener_context.cpp b/cpp/src/screener_context.cpp index 46054aacb..886438b2e 100644 --- a/cpp/src/screener_context.cpp +++ b/cpp/src/screener_context.cpp @@ -8,8 +8,7 @@ extern "C" { const lb_screener_context_t* lb_screener_context_new(const lb_config_t* config); void lb_screener_context_retain(const lb_screener_context_t* ctx); void lb_screener_context_release(const lb_screener_context_t* ctx); -void lb_screener_context_recommend_strategies(const lb_screener_context_t*, lb_async_callback_t, void*); -void lb_screener_context_user_strategies(const lb_screener_context_t*, lb_async_callback_t, void*); +// Declarations already present in longbridge.h (with market param) — no need to redeclare. void lb_screener_context_strategy(const lb_screener_context_t*, int64_t, lb_async_callback_t, void*); void lb_screener_context_search(const lb_screener_context_t*, const char*, int64_t, bool, uint32_t, uint32_t, lb_async_callback_t, void*); void lb_screener_context_indicators(const lb_screener_context_t*, lb_async_callback_t, void*); @@ -39,12 +38,12 @@ ScreenerContext ScreenerContext::create(const Config& config) { else{(*cb)(AsyncResult(sctx,std::move(status),nullptr));} \ }, new AsyncCallback(callback)) -void ScreenerContext::screener_recommend_strategies(AsyncCallback callback) const { - S_JSON(lb_screener_context_recommend_strategies, lb_screener_recommend_strategies_response_t, ctx_); +void ScreenerContext::screener_recommend_strategies(const std::string& market, AsyncCallback callback) const { + S_JSON(lb_screener_context_recommend_strategies, lb_screener_recommend_strategies_response_t, ctx_, market.c_str()); } -void ScreenerContext::screener_user_strategies(AsyncCallback callback) const { - S_JSON(lb_screener_context_user_strategies, lb_screener_user_strategies_response_t, ctx_); +void ScreenerContext::screener_user_strategies(const std::string& market, AsyncCallback callback) const { + S_JSON(lb_screener_context_user_strategies, lb_screener_user_strategies_response_t, ctx_, market.c_str()); } void ScreenerContext::screener_strategy(int64_t id, AsyncCallback callback) const { From e7f941ea972781e6c91d5a91a2ee0edaf2fe12ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A2=81=E7=AB=A0=E6=B4=AA?= Date: Sat, 23 May 2026 15:43:44 +0800 Subject: [PATCH 07/26] feat(screener): typed ScreenerCondition for Mode B, fix Java market param, fix C++ signatures - Add ScreenerCondition struct (Rust/Python/Node.js) for typed screener_search Mode B conditions instead of KEY:MIN:MAX strings - Python: ScreenerCondition pyclass with key/min/max/tech_values(JSON string) - Node.js: ScreenerCondition napi object with same fields - Java: add market param to getRecommendStrategies/getUserStrategies and SdkNative - C++: add market param to screener_recommend/user_strategies hpp/cpp Co-Authored-By: Claude Sonnet 4.6 (1M context) --- .../main/java/com/longbridge/SdkNative.java | 2 + .../longbridge/screener/ScreenerContext.java | 18 ++++++-- nodejs/src/screener/context.rs | 10 +++-- nodejs/src/screener/types.rs | 30 +++++++++++++ python/pysrc/longbridge/openapi.pyi | 30 +++++++++++-- python/src/screener/context.rs | 6 ++- python/src/screener/context_async.rs | 6 ++- python/src/screener/mod.rs | 1 + python/src/screener/types.rs | 44 +++++++++++++++++++ rust/src/blocking/screener.rs | 2 +- rust/src/screener/context.rs | 36 ++++++++------- rust/src/screener/types.rs | 25 +++++++++++ 12 files changed, 177 insertions(+), 33 deletions(-) diff --git a/java/javasrc/src/main/java/com/longbridge/SdkNative.java b/java/javasrc/src/main/java/com/longbridge/SdkNative.java index 777647bae..4ed90791a 100644 --- a/java/javasrc/src/main/java/com/longbridge/SdkNative.java +++ b/java/javasrc/src/main/java/com/longbridge/SdkNative.java @@ -335,9 +335,11 @@ public static native void marketContextRankList(long context, Object opts, public static native void freeScreenerContext(long context); public static native void screenerContextRecommendStrategies(long context, + String market, AsyncCallback callback); public static native void screenerContextUserStrategies(long context, + String market, AsyncCallback callback); public static native void screenerContextStrategy(long context, Object opts, diff --git a/java/javasrc/src/main/java/com/longbridge/screener/ScreenerContext.java b/java/javasrc/src/main/java/com/longbridge/screener/ScreenerContext.java index 7fad58470..c97d66f4a 100644 --- a/java/javasrc/src/main/java/com/longbridge/screener/ScreenerContext.java +++ b/java/javasrc/src/main/java/com/longbridge/screener/ScreenerContext.java @@ -20,14 +20,24 @@ public void close() throws Exception { SdkNative.freeScreenerContext(raw); } - /** Get platform-recommended screener strategies. */ + /** Get platform-preset screener strategies for the given market (default "US"). */ + public CompletableFuture getRecommendStrategies(String market) throws OpenApiException { + return AsyncCallback.executeTask((callback) -> SdkNative.screenerContextRecommendStrategies(raw, market, callback)); + } + + /** Get platform-preset screener strategies (defaults to US market). */ public CompletableFuture getRecommendStrategies() throws OpenApiException { - return AsyncCallback.executeTask((callback) -> SdkNative.screenerContextRecommendStrategies(raw, callback)); + return getRecommendStrategies("US"); + } + + /** Get the current user's saved screener strategies for the given market (default "US"). */ + public CompletableFuture getUserStrategies(String market) throws OpenApiException { + return AsyncCallback.executeTask((callback) -> SdkNative.screenerContextUserStrategies(raw, market, callback)); } - /** Get the current user's saved screener strategies. */ + /** Get the current user's saved screener strategies (defaults to US market). */ public CompletableFuture getUserStrategies() throws OpenApiException { - return AsyncCallback.executeTask((callback) -> SdkNative.screenerContextUserStrategies(raw, callback)); + return getUserStrategies("US"); } /** Get detail for one screener strategy by ID. */ diff --git a/nodejs/src/screener/context.rs b/nodejs/src/screener/context.rs index 5c14f3a1e..92ab8b7ef 100644 --- a/nodejs/src/screener/context.rs +++ b/nodejs/src/screener/context.rs @@ -67,7 +67,7 @@ impl ScreenerContext { /// strategy response. /// /// When `strategyId` is `null` / `undefined` (Mode B), `conditions` must be - /// `"KEY:MIN:MAX"` strings and `market` is used directly. + /// `ScreenerCondition` objects and `market` is used directly. /// /// `filter_` is stripped from every `items[].indicators[].key` in the /// response before it is returned. @@ -76,14 +76,16 @@ impl ScreenerContext { &self, market: String, strategy_id: Option, - #[napi(ts_arg_type = "string[]")] conditions: Vec, - #[napi(ts_arg_type = "string[]")] show: Vec, + conditions: Vec, + show: Vec, page: u32, size: u32, ) -> Result { + let lb_conditions: Vec = + conditions.into_iter().map(Into::into).collect(); Ok(self .ctx - .screener_search(market, strategy_id, conditions, show, page, size) + .screener_search(market, strategy_id, lb_conditions, show, page, size) .await .map_err(ErrorNewType)? .into()) diff --git a/nodejs/src/screener/types.rs b/nodejs/src/screener/types.rs index 3956b8887..f2a239c50 100644 --- a/nodejs/src/screener/types.rs +++ b/nodejs/src/screener/types.rs @@ -89,3 +89,33 @@ impl From for ScreenerIndicatorsResponse { } } } + +// ── ScreenerCondition ───────────────────────────────────────────── + +/// A filter condition for screener_search Mode B. +#[napi_derive::napi(object)] +#[derive(Debug, Clone, Default)] +pub struct ScreenerCondition { + /// Indicator key without filter_ prefix, e.g. "pettm", "roe", "macd_day" + pub key: String, + /// Lower bound (empty = no lower bound) + pub min: String, + /// Upper bound (empty = no upper bound) + pub max: String, + /// Technical indicator params as JSON string (empty object "{}" for + /// fundamental indicators) + pub tech_values: String, +} + +impl From for longbridge::screener::ScreenerCondition { + fn from(v: ScreenerCondition) -> Self { + let tv: serde_json::Value = + serde_json::from_str(&v.tech_values).unwrap_or(serde_json::json!({})); + Self { + key: v.key, + min: v.min, + max: v.max, + tech_values: tv, + } + } +} diff --git a/python/pysrc/longbridge/openapi.pyi b/python/pysrc/longbridge/openapi.pyi index 74dab75e7..4f5a85090 100644 --- a/python/pysrc/longbridge/openapi.pyi +++ b/python/pysrc/longbridge/openapi.pyi @@ -10530,6 +10530,28 @@ class RankListResponse: # ── ScreenerContext ─────────────────────────────────────────────── +class ScreenerCondition: + """A filter condition for :meth:`ScreenerContext.screener_search` Mode B.""" + + key: str + """Indicator key without ``filter_`` prefix, e.g. ``"pettm"``, ``"roe"``, ``"macd_day"``""" + min: str + """Lower bound (empty string = no lower bound)""" + max: str + """Upper bound (empty string = no upper bound)""" + tech_values: str + """Technical indicator params as JSON string. Use ``"{}"`` for fundamental indicators. + Example: ``'{"category": "goldenfork", "period": "day"}'``""" + + def __init__( + self, + key: str, + min: str = "", + max: str = "", + tech_values: str = "{}", + ) -> None: ... + + class ScreenerRecommendStrategiesResponse: """Recommended screener strategies response. ``data`` is a Python dict/list from JSON.""" @@ -10586,7 +10608,7 @@ class ScreenerContext: self, market: str, strategy_id: Optional[int] = None, - conditions: List[str] = [], + conditions: List["ScreenerCondition"] = [], show: List[str] = [], page: int = 0, size: int = 20, @@ -10598,7 +10620,7 @@ class ScreenerContext: ``market`` is taken from the strategy response. When *strategy_id* is ``None`` (Mode B), *conditions* must be provided as - ``"KEY:MIN:MAX"`` strings and *market* is used directly. + :class:`ScreenerCondition` objects and *market* is used directly. ``filter_`` is stripped from every ``items[].indicators[].key`` in the response before it is returned. @@ -10640,7 +10662,7 @@ class AsyncScreenerContext: self, market: str, strategy_id: Optional[int] = None, - conditions: List[str] = [], + conditions: List["ScreenerCondition"] = [], show: List[str] = [], page: int = 0, size: int = 20, @@ -10653,7 +10675,7 @@ class AsyncScreenerContext: ``market`` is taken from the strategy response. When *strategy_id* is ``None`` (Mode B), *conditions* must be provided as - ``"KEY:MIN:MAX"`` strings and *market* is used directly. + :class:`ScreenerCondition` objects and *market* is used directly. ``filter_`` is stripped from every ``items[].indicators[].key`` in the response before it is returned. diff --git a/python/src/screener/context.rs b/python/src/screener/context.rs index 279500995..864f3210b 100644 --- a/python/src/screener/context.rs +++ b/python/src/screener/context.rs @@ -52,14 +52,16 @@ impl ScreenerContext { &self, market: String, strategy_id: Option, - conditions: Vec, + conditions: Vec, show: Vec, page: u32, size: u32, ) -> PyResult { + let lb_conditions: Vec = + conditions.into_iter().map(Into::into).collect(); Ok(self .ctx - .screener_search(market, strategy_id, conditions, show, page, size) + .screener_search(market, strategy_id, lb_conditions, show, page, size) .map_err(ErrorNewType)? .into()) } diff --git a/python/src/screener/context_async.rs b/python/src/screener/context_async.rs index c3b3e9d9e..5c14848df 100644 --- a/python/src/screener/context_async.rs +++ b/python/src/screener/context_async.rs @@ -66,15 +66,17 @@ impl AsyncScreenerContext { py: Python<'_>, market: String, strategy_id: Option, - conditions: Vec, + conditions: Vec, show: Vec, page: u32, size: u32, ) -> PyResult> { let ctx = self.ctx.clone(); + let lb_conditions: Vec = + conditions.into_iter().map(Into::into).collect(); pyo3_async_runtimes::tokio::future_into_py(py, async move { Ok(ScreenerSearchResponse::from( - ctx.screener_search(market, strategy_id, conditions, show, page, size) + ctx.screener_search(market, strategy_id, lb_conditions, show, page, size) .await .map_err(ErrorNewType)?, )) diff --git a/python/src/screener/mod.rs b/python/src/screener/mod.rs index 37c3193e9..9d7ca43e5 100644 --- a/python/src/screener/mod.rs +++ b/python/src/screener/mod.rs @@ -11,6 +11,7 @@ pub(crate) fn register_types(parent: &Bound) -> PyResult<()> { parent.add_class::()?; parent.add_class::()?; parent.add_class::()?; + parent.add_class::()?; parent.add_class::()?; parent.add_class::()?; Ok(()) diff --git a/python/src/screener/types.rs b/python/src/screener/types.rs index b87ca8600..6e51e965b 100644 --- a/python/src/screener/types.rs +++ b/python/src/screener/types.rs @@ -105,3 +105,47 @@ impl From for ScreenerIndicatorsResponse { } } } + +// ── ScreenerCondition ───────────────────────────────────────────── + +/// A filter condition for screener_search Mode B. +#[pyclass(get_all, set_all)] +#[derive(Debug, Clone, Default)] +pub(crate) struct ScreenerCondition { + /// Indicator key without filter_ prefix, e.g. "pettm", "roe", "macd_day" + pub key: String, + /// Lower bound (empty = no lower bound) + pub min: String, + /// Upper bound (empty = no upper bound) + pub max: String, + /// Technical indicator params as JSON string (empty object "{}" for + /// fundamental indicators) + pub tech_values: String, +} + +#[pymethods] +impl ScreenerCondition { + #[new] + #[pyo3(signature = (key, min="", max="", tech_values="{}"))] + pub fn new(key: String, min: &str, max: &str, tech_values: &str) -> Self { + Self { + key, + min: min.to_string(), + max: max.to_string(), + tech_values: tech_values.to_string(), + } + } +} + +impl From for longbridge::screener::ScreenerCondition { + fn from(v: ScreenerCondition) -> Self { + let tv: serde_json::Value = + serde_json::from_str(&v.tech_values).unwrap_or(serde_json::json!({})); + Self { + key: v.key, + min: v.min, + max: v.max, + tech_values: tv, + } + } +} diff --git a/rust/src/blocking/screener.rs b/rust/src/blocking/screener.rs index 81beeb93b..b80ca3fd9 100644 --- a/rust/src/blocking/screener.rs +++ b/rust/src/blocking/screener.rs @@ -63,7 +63,7 @@ impl ScreenerContextSync { &self, market: impl Into + Send + 'static, strategy_id: Option, - conditions: Vec, + conditions: Vec, show: Vec, page: u32, size: u32, diff --git a/rust/src/screener/context.rs b/rust/src/screener/context.rs index 979542688..6506f7fa0 100644 --- a/rust/src/screener/context.rs +++ b/rust/src/screener/context.rs @@ -195,7 +195,7 @@ impl ScreenerContext { &self, market: impl Into, strategy_id: Option, - conditions: Vec, + conditions: Vec, show: Vec, page: u32, size: u32, @@ -241,23 +241,27 @@ impl ScreenerContext { } (mkt, filters) } else { - // Mode B: custom conditions ("KEY:MIN:MAX" strings) + // Mode B: typed condition objects let filters: Vec = conditions .iter() - .filter_map(|cond| { - let parts: Vec<&str> = cond.splitn(3, ':').collect(); - if parts.is_empty() || parts[0].is_empty() { - return None; - } - let key = parts[0].to_string(); - let min = parts.get(1).copied().unwrap_or("").to_string(); - let max = parts.get(2).copied().unwrap_or("").to_string(); - Some(serde_json::json!({ - "key": key, - "min": min, - "max": max, - "tech_values": {}, - })) + .filter(|c| !c.key.is_empty()) + .map(|c| { + let api_key = if c.key.starts_with("filter_") { + c.key.clone() + } else { + format!("filter_{}", c.key) + }; + let tv = if c.tech_values.is_object() { + c.tech_values.clone() + } else { + serde_json::json!({}) + }; + serde_json::json!({ + "key": api_key, + "min": c.min, + "max": c.max, + "tech_values": tv, + }) }) .collect(); (market, filters) diff --git a/rust/src/screener/types.rs b/rust/src/screener/types.rs index 0f71a2c0a..a60ac41da 100644 --- a/rust/src/screener/types.rs +++ b/rust/src/screener/types.rs @@ -39,6 +39,31 @@ pub struct ScreenerStrategyResponse { pub data: serde_json::Value, } +// ── screener_condition ─────────────────────────────────────────── + +/// A filter condition for [`crate::ScreenerContext::screener_search`] Mode B. +/// +/// `key` is the indicator key (without the `filter_` prefix, e.g. `"pettm"`). +/// `min` / `max` bound the range; leave empty for an open bound. +/// `tech_values` is used for technical indicators (e.g. MACD/RSI); pass an +/// empty map `{}` for fundamental indicators. +#[derive(Debug, Clone, Serialize, Deserialize, Default)] +pub struct ScreenerCondition { + /// Indicator key without `filter_` prefix, e.g. `"pettm"`, `"roe"`, + /// `"macd_day"` + pub key: String, + /// Lower bound (empty string = no lower bound) + #[serde(default)] + pub min: String, + /// Upper bound (empty string = no upper bound) + #[serde(default)] + pub max: String, + /// Technical indicator parameters (empty map for fundamental indicators). + /// Example: `{"category": "goldenfork", "period": "day"}` + #[serde(default)] + pub tech_values: serde_json::Value, +} + // ── screener_search ─────────────────────────────────────────────── /// Response for [`crate::ScreenerContext::screener_search`] From 948f2f2398a6d2d8ae4347aafa9e912528d1925b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A2=81=E7=AB=A0=E6=B4=AA?= Date: Sat, 23 May 2026 15:55:12 +0800 Subject: [PATCH 08/26] fix(python): use from_py_object for ScreenerCondition to fix deprecated warning --- python/src/screener/types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/src/screener/types.rs b/python/src/screener/types.rs index 6e51e965b..69d0eecce 100644 --- a/python/src/screener/types.rs +++ b/python/src/screener/types.rs @@ -109,7 +109,7 @@ impl From for ScreenerIndicatorsResponse { // ── ScreenerCondition ───────────────────────────────────────────── /// A filter condition for screener_search Mode B. -#[pyclass(get_all, set_all)] +#[pyclass(get_all, set_all, from_py_object)] #[derive(Debug, Clone, Default)] pub(crate) struct ScreenerCondition { /// Indicator key without filter_ prefix, e.g. "pettm", "roe", "macd_day" From 5f14b07b26cf1e029466d022eb2046afdf552fa2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A2=81=E7=AB=A0=E6=B4=AA?= Date: Sat, 23 May 2026 16:00:07 +0800 Subject: [PATCH 09/26] chore: remove [Unreleased] CHANGELOG entries --- CHANGELOG.md | 8 -------- 1 file changed, 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0f85ad429..e7b058502 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,14 +4,6 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased] - -### Changed - -- **Screener:** all endpoints migrated to `/v1/quote/ai/screener/*`; `screener_recommend_strategies` and `screener_user_strategies` now require a `market` parameter; `screener_strategy(id)` uses a path parameter instead of a query parameter -- **Screener:** `screener_strategy` and `screener_indicators` now strip the `filter_` prefix from response keys before returning; `screener_indicators` additionally builds `tech_values` from `tech_indicators` -- **Screener:** `screener_search` gains `conditions` and `show` parameters; Mode A fetches the strategy via AI endpoint and derives `market` from the response; Mode B accepts `"KEY:MIN:MAX"` condition strings; response `items[].indicators[].key` values have `filter_` stripped; `page` is now 0-indexed and defaults to 0 - ## [4.2.0] ### Added From 1dbba24306c5648facae6735eef6b4aa3d87c224 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A2=81=E7=AB=A0=E6=B4=AA?= Date: Sat, 23 May 2026 18:13:59 +0800 Subject: [PATCH 10/26] =?UTF-8?q?fix(fundamental):=20rename=20OperatingFin?= =?UTF-8?q?ancial.counter=5Fid=20=E2=86=92=20symbol=20in=20all=20SDKs?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 4.6 (1M context) --- .../fundamental/OperatingFinancial.java | 4 +-- java/src/types/classes.rs | 2 +- nodejs/index.d.ts | 35 ++++++++++++++++--- python/pysrc/longbridge/openapi.pyi | 2 ++ rust/src/fundamental/types.rs | 8 +++-- 5 files changed, 42 insertions(+), 9 deletions(-) diff --git a/java/javasrc/src/main/java/com/longbridge/fundamental/OperatingFinancial.java b/java/javasrc/src/main/java/com/longbridge/fundamental/OperatingFinancial.java index 3a95d115a..db4e55224 100644 --- a/java/javasrc/src/main/java/com/longbridge/fundamental/OperatingFinancial.java +++ b/java/javasrc/src/main/java/com/longbridge/fundamental/OperatingFinancial.java @@ -4,8 +4,8 @@ public class OperatingFinancial { /** Ticker code (may be empty). */ public String code; - /** Raw counter ID (may be empty). */ - public String counterId; + /** Symbol in CODE.MARKET format (may be empty). */ + public String symbol; /** Reporting currency. */ public String currency; /** Company name. */ diff --git a/java/src/types/classes.rs b/java/src/types/classes.rs index 2b1dbab87..29c7751c2 100644 --- a/java/src/types/classes.rs +++ b/java/src/types/classes.rs @@ -2208,7 +2208,7 @@ impl_java_class!( longbridge::fundamental::OperatingFinancial, [ code, - counter_id, + symbol, currency, name, region, diff --git a/nodejs/index.d.ts b/nodejs/index.d.ts index 8650cc6be..40056b695 100644 --- a/nodejs/index.d.ts +++ b/nodejs/index.d.ts @@ -2067,13 +2067,25 @@ export declare class ScreenerContext { /** Create a new `ScreenerContext` */ static new(config: Config): ScreenerContext /** Get recommended built-in screener strategies */ - screenerRecommendStrategies(): Promise + screenerRecommendStrategies(market: string): Promise /** Get the current user's saved screener strategies */ - screenerUserStrategies(): Promise + screenerUserStrategies(market: string): Promise /** Get detail for one screener strategy by ID */ screenerStrategy(id: number): Promise - /** Search / screen securities using a strategy */ - screenerSearch(market: string, strategyId: number | undefined | null, page: number, size: number): Promise + /** + * Search / screen securities using a strategy or custom conditions. + * + * When `strategyId` is given (Mode A), the strategy is fetched from the AI + * endpoint and its filters drive the search. The market is taken from the + * strategy response. + * + * When `strategyId` is `null` / `undefined` (Mode B), `conditions` must be + * `ScreenerCondition` objects and `market` is used directly. + * + * `filter_` is stripped from every `items[].indicators[].key` in the + * response before it is returned. + */ + screenerSearch(market: string, strategyId: number | undefined | null, conditions: Array, show: Array, page: number, size: number): Promise /** Get all available screener indicator definitions */ screenerIndicators(): Promise } @@ -5107,6 +5119,21 @@ export interface ReplaceOrderOptions { remark?: string } +/** A filter condition for screener_search Mode B. */ +export interface ScreenerCondition { + /** Indicator key without filter_ prefix, e.g. "pettm", "roe", "macd_day" */ + key: string + /** Lower bound (empty = no lower bound) */ + min: string + /** Upper bound (empty = no upper bound) */ + max: string + /** + * Technical indicator params as JSON string (empty object "{}" for + * fundamental indicators) + */ + techValues: string +} + /** Screener indicator definitions response. `data` is a JSON string. */ export interface ScreenerIndicatorsResponse { /** Raw indicator definitions data (JSON string) */ diff --git a/python/pysrc/longbridge/openapi.pyi b/python/pysrc/longbridge/openapi.pyi index 4f5a85090..fa4bb05fd 100644 --- a/python/pysrc/longbridge/openapi.pyi +++ b/python/pysrc/longbridge/openapi.pyi @@ -9570,6 +9570,8 @@ class OperatingFinancial: code: str """Ticker code""" + symbol: str + """Symbol in CODE.MARKET format (e.g. ``AAPL.US``)""" currency: str """Reporting currency""" name: str diff --git a/rust/src/fundamental/types.rs b/rust/src/fundamental/types.rs index b6332d4d2..bbae2ec51 100644 --- a/rust/src/fundamental/types.rs +++ b/rust/src/fundamental/types.rs @@ -873,8 +873,12 @@ pub struct OperatingItem { pub struct OperatingFinancial { /// Ticker code (may be empty) pub code: String, - /// Raw counter ID (may be empty) - pub counter_id: String, + /// Symbol in `CODE.MARKET` format (may be empty) + #[serde( + rename = "counter_id", + deserialize_with = "deserialize_counter_id_as_symbol" + )] + pub symbol: String, /// Reporting currency pub currency: String, /// Company name From f69e077c46446fa0691d8ce172d3c3c74e2f0852 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A2=81=E7=AB=A0=E6=B4=AA?= Date: Sat, 23 May 2026 19:38:54 +0800 Subject: [PATCH 11/26] chore: release 4.2.1 Co-Authored-By: Claude Sonnet 4.6 (1M context) --- CHANGELOG.md | 10 ++++++++++ Cargo.toml | 2 +- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e7b058502..90b9bfb04 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,16 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [4.2.1] + +### Changed + +- `ScreenerContext`: screener endpoints migrated to `/v1/quote/ai/screener/*`; `screener_recommend_strategies` / `screener_user_strategies` now accept a `market` parameter; `screener_search` accepts typed `ScreenerCondition` objects (Mode B) instead of raw strings + +### Fixed + +- `OperatingFinancial`: renamed `counter_id` → `symbol` (converts `ST/US/AAPL` → `AAPL.US`) + ## [4.2.0] ### Added diff --git a/Cargo.toml b/Cargo.toml index 613175113..fabc86433 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ resolver = "3" members = ["rust", "python", "nodejs", "java", "c"] [workspace.package] -version = "4.2.0" +version = "4.2.1" edition = "2024" [profile.release] From 169ec2702010cc41bb10278fd0f0ae62b4f62370 Mon Sep 17 00:00:00 2001 From: Hogan Date: Sat, 23 May 2026 19:58:42 +0800 Subject: [PATCH 12/26] feat(screener): migrate to /v1/quote/ai/screener/* endpoints (#530) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Migrates all screener endpoints from `/v1/quote/screener/*` to `/v1/quote/ai/screener/*` per [longbridge-terminal PR #217](https://github.com/longbridge/longbridge-terminal/pull/217). ## Changes | Old endpoint | New endpoint | |---|---| | `GET /v1/quote/screener/strategies/recommend` | `GET /v1/quote/ai/screener/strategies/recommend` | | `GET /v1/quote/screener/strategies/mine` | `GET /v1/quote/ai/screener/strategies/mine` | | `GET /v1/quote/screener/strategy?id=N` | `GET /v1/quote/ai/screener/strategy/{id}` | | `POST /v1/quote/screener/search` | `POST /v1/quote/ai/screener/search` | | `GET /v1/quote/screener/indicators` | `GET /v1/quote/ai/screener/indicators` | ### Breaking changes - `screener_recommend_strategies(market)` and `screener_user_strategies(market)` now require a `market` parameter (Rust/Python/Node.js/Java/C) - `screener_strategy(id)` uses path param instead of query param 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Sonnet 4.6 (1M context) --- CHANGELOG.md | 10 + Cargo.toml | 2 +- c/csrc/include/longbridge.h | 2 + c/src/screener_context/context.rs | 15 +- cpp/include/screener_context.hpp | 8 +- cpp/src/screener_context.cpp | 11 +- .../main/java/com/longbridge/SdkNative.java | 2 + .../fundamental/OperatingFinancial.java | 4 +- .../longbridge/screener/ScreenerContext.java | 18 +- java/src/screener_context.rs | 14 +- java/src/types/classes.rs | 2 +- nodejs/index.d.ts | 35 ++- nodejs/src/screener/context.rs | 28 +- nodejs/src/screener/types.rs | 30 ++ python/pysrc/longbridge/openapi.pyi | 69 +++- python/src/screener/context.rs | 19 +- python/src/screener/context_async.rs | 19 +- python/src/screener/mod.rs | 1 + python/src/screener/types.rs | 44 +++ rust/src/blocking/screener.rs | 19 +- rust/src/fundamental/types.rs | 8 +- rust/src/market/context.rs | 29 +- rust/src/screener/context.rs | 294 +++++++++++++++--- rust/src/screener/types.rs | 25 ++ 24 files changed, 601 insertions(+), 107 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e7b058502..90b9bfb04 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,16 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [4.2.1] + +### Changed + +- `ScreenerContext`: screener endpoints migrated to `/v1/quote/ai/screener/*`; `screener_recommend_strategies` / `screener_user_strategies` now accept a `market` parameter; `screener_search` accepts typed `ScreenerCondition` objects (Mode B) instead of raw strings + +### Fixed + +- `OperatingFinancial`: renamed `counter_id` → `symbol` (converts `ST/US/AAPL` → `AAPL.US`) + ## [4.2.0] ### Added diff --git a/Cargo.toml b/Cargo.toml index 613175113..fabc86433 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ resolver = "3" members = ["rust", "python", "nodejs", "java", "c"] [workspace.package] -version = "4.2.0" +version = "4.2.1" edition = "2024" [profile.release] diff --git a/c/csrc/include/longbridge.h b/c/csrc/include/longbridge.h index 5cfcd77ac..cb8db05c0 100644 --- a/c/csrc/include/longbridge.h +++ b/c/csrc/include/longbridge.h @@ -10193,6 +10193,7 @@ void lb_screener_context_release(const struct lb_screener_context_t *ctx); * Returns `CScreenerRecommendStrategiesResponse`. */ void lb_screener_context_recommend_strategies(const struct lb_screener_context_t *ctx, + const char *market, lb_async_callback_t callback, void *userdata); @@ -10201,6 +10202,7 @@ void lb_screener_context_recommend_strategies(const struct lb_screener_context_t * Returns `CScreenerUserStrategiesResponse`. */ void lb_screener_context_user_strategies(const struct lb_screener_context_t *ctx, + const char *market, lb_async_callback_t callback, void *userdata); diff --git a/c/src/screener_context/context.rs b/c/src/screener_context/context.rs index 4a027ebee..cb3c44579 100644 --- a/c/src/screener_context/context.rs +++ b/c/src/screener_context/context.rs @@ -38,14 +38,16 @@ pub unsafe extern "C" fn lb_screener_context_release(ctx: *const CScreenerContex #[unsafe(no_mangle)] pub unsafe extern "C" fn lb_screener_context_recommend_strategies( ctx: *const CScreenerContext, + market: *const c_char, callback: CAsyncCallback, userdata: *mut c_void, ) { let ctx_inner = (*ctx).ctx.clone(); + let market = cstr_to_rust(market); execute_async(callback, ctx, userdata, async move { let resp: CCow = CCow::new(CScreenerRecommendStrategiesResponseOwned::from( - ctx_inner.screener_recommend_strategies().await?, + ctx_inner.screener_recommend_strategies(market).await?, )); Ok(resp) }); @@ -56,14 +58,17 @@ pub unsafe extern "C" fn lb_screener_context_recommend_strategies( #[unsafe(no_mangle)] pub unsafe extern "C" fn lb_screener_context_user_strategies( ctx: *const CScreenerContext, + market: *const c_char, callback: CAsyncCallback, userdata: *mut c_void, ) { let ctx_inner = (*ctx).ctx.clone(); + let market = cstr_to_rust(market); execute_async(callback, ctx, userdata, async move { - let resp: CCow = CCow::new( - CScreenerUserStrategiesResponseOwned::from(ctx_inner.screener_user_strategies().await?), - ); + let resp: CCow = + CCow::new(CScreenerUserStrategiesResponseOwned::from( + ctx_inner.screener_user_strategies(market).await?, + )); Ok(resp) }); } @@ -110,7 +115,7 @@ pub unsafe extern "C" fn lb_screener_context_search( let resp: CCow = CCow::new(CScreenerSearchResponseOwned::from( ctx_inner - .screener_search(market, strategy_id, page, size) + .screener_search(market, strategy_id, vec![], vec![], page, size) .await?, )); Ok(resp) diff --git a/cpp/include/screener_context.hpp b/cpp/include/screener_context.hpp index 843bb0fc5..2c6adb121 100644 --- a/cpp/include/screener_context.hpp +++ b/cpp/include/screener_context.hpp @@ -24,11 +24,13 @@ class ScreenerContext static ScreenerContext create(const Config& config); - /// Get recommended built-in screener strategies (raw JSON string) - void screener_recommend_strategies(AsyncCallback callback) const; + /// Get preset screener strategies for a given market (raw JSON string) + void screener_recommend_strategies(const std::string& market, + AsyncCallback callback) const; /// Get the current user's saved screener strategies (raw JSON string) - void screener_user_strategies(AsyncCallback callback) const; + void screener_user_strategies(const std::string& market, + AsyncCallback callback) const; /// Get detail for one screener strategy by ID (raw JSON string) void screener_strategy(int64_t id, AsyncCallback callback) const; diff --git a/cpp/src/screener_context.cpp b/cpp/src/screener_context.cpp index 46054aacb..886438b2e 100644 --- a/cpp/src/screener_context.cpp +++ b/cpp/src/screener_context.cpp @@ -8,8 +8,7 @@ extern "C" { const lb_screener_context_t* lb_screener_context_new(const lb_config_t* config); void lb_screener_context_retain(const lb_screener_context_t* ctx); void lb_screener_context_release(const lb_screener_context_t* ctx); -void lb_screener_context_recommend_strategies(const lb_screener_context_t*, lb_async_callback_t, void*); -void lb_screener_context_user_strategies(const lb_screener_context_t*, lb_async_callback_t, void*); +// Declarations already present in longbridge.h (with market param) — no need to redeclare. void lb_screener_context_strategy(const lb_screener_context_t*, int64_t, lb_async_callback_t, void*); void lb_screener_context_search(const lb_screener_context_t*, const char*, int64_t, bool, uint32_t, uint32_t, lb_async_callback_t, void*); void lb_screener_context_indicators(const lb_screener_context_t*, lb_async_callback_t, void*); @@ -39,12 +38,12 @@ ScreenerContext ScreenerContext::create(const Config& config) { else{(*cb)(AsyncResult(sctx,std::move(status),nullptr));} \ }, new AsyncCallback(callback)) -void ScreenerContext::screener_recommend_strategies(AsyncCallback callback) const { - S_JSON(lb_screener_context_recommend_strategies, lb_screener_recommend_strategies_response_t, ctx_); +void ScreenerContext::screener_recommend_strategies(const std::string& market, AsyncCallback callback) const { + S_JSON(lb_screener_context_recommend_strategies, lb_screener_recommend_strategies_response_t, ctx_, market.c_str()); } -void ScreenerContext::screener_user_strategies(AsyncCallback callback) const { - S_JSON(lb_screener_context_user_strategies, lb_screener_user_strategies_response_t, ctx_); +void ScreenerContext::screener_user_strategies(const std::string& market, AsyncCallback callback) const { + S_JSON(lb_screener_context_user_strategies, lb_screener_user_strategies_response_t, ctx_, market.c_str()); } void ScreenerContext::screener_strategy(int64_t id, AsyncCallback callback) const { diff --git a/java/javasrc/src/main/java/com/longbridge/SdkNative.java b/java/javasrc/src/main/java/com/longbridge/SdkNative.java index 777647bae..4ed90791a 100644 --- a/java/javasrc/src/main/java/com/longbridge/SdkNative.java +++ b/java/javasrc/src/main/java/com/longbridge/SdkNative.java @@ -335,9 +335,11 @@ public static native void marketContextRankList(long context, Object opts, public static native void freeScreenerContext(long context); public static native void screenerContextRecommendStrategies(long context, + String market, AsyncCallback callback); public static native void screenerContextUserStrategies(long context, + String market, AsyncCallback callback); public static native void screenerContextStrategy(long context, Object opts, diff --git a/java/javasrc/src/main/java/com/longbridge/fundamental/OperatingFinancial.java b/java/javasrc/src/main/java/com/longbridge/fundamental/OperatingFinancial.java index 3a95d115a..db4e55224 100644 --- a/java/javasrc/src/main/java/com/longbridge/fundamental/OperatingFinancial.java +++ b/java/javasrc/src/main/java/com/longbridge/fundamental/OperatingFinancial.java @@ -4,8 +4,8 @@ public class OperatingFinancial { /** Ticker code (may be empty). */ public String code; - /** Raw counter ID (may be empty). */ - public String counterId; + /** Symbol in CODE.MARKET format (may be empty). */ + public String symbol; /** Reporting currency. */ public String currency; /** Company name. */ diff --git a/java/javasrc/src/main/java/com/longbridge/screener/ScreenerContext.java b/java/javasrc/src/main/java/com/longbridge/screener/ScreenerContext.java index 7fad58470..c97d66f4a 100644 --- a/java/javasrc/src/main/java/com/longbridge/screener/ScreenerContext.java +++ b/java/javasrc/src/main/java/com/longbridge/screener/ScreenerContext.java @@ -20,14 +20,24 @@ public void close() throws Exception { SdkNative.freeScreenerContext(raw); } - /** Get platform-recommended screener strategies. */ + /** Get platform-preset screener strategies for the given market (default "US"). */ + public CompletableFuture getRecommendStrategies(String market) throws OpenApiException { + return AsyncCallback.executeTask((callback) -> SdkNative.screenerContextRecommendStrategies(raw, market, callback)); + } + + /** Get platform-preset screener strategies (defaults to US market). */ public CompletableFuture getRecommendStrategies() throws OpenApiException { - return AsyncCallback.executeTask((callback) -> SdkNative.screenerContextRecommendStrategies(raw, callback)); + return getRecommendStrategies("US"); + } + + /** Get the current user's saved screener strategies for the given market (default "US"). */ + public CompletableFuture getUserStrategies(String market) throws OpenApiException { + return AsyncCallback.executeTask((callback) -> SdkNative.screenerContextUserStrategies(raw, market, callback)); } - /** Get the current user's saved screener strategies. */ + /** Get the current user's saved screener strategies (defaults to US market). */ public CompletableFuture getUserStrategies() throws OpenApiException { - return AsyncCallback.executeTask((callback) -> SdkNative.screenerContextUserStrategies(raw, callback)); + return getUserStrategies("US"); } /** Get detail for one screener strategy by ID. */ diff --git a/java/src/screener_context.rs b/java/src/screener_context.rs index c6b66330d..2482094d1 100644 --- a/java/src/screener_context.rs +++ b/java/src/screener_context.rs @@ -2,14 +2,14 @@ use std::sync::Arc; use jni::{ JNIEnv, - objects::{JClass, JObject}, + objects::{JClass, JObject, JString}, }; use longbridge::{Config, ScreenerContext}; use crate::{ async_util, error::jni_result, - types::{JavaInteger, get_field}, + types::{FromJValue, JavaInteger, get_field}, }; struct ContextObj { @@ -41,12 +41,14 @@ pub unsafe extern "system" fn Java_com_longbridge_SdkNative_screenerContextRecom mut env: JNIEnv, _class: JClass, context: i64, + market: JString, callback: JObject, ) { jni_result(&mut env, (), |env| { let context = &*(context as *const ContextObj); + let market: String = FromJValue::from_jvalue(env, market.into())?; async_util::execute(env, callback, async move { - let resp = context.ctx.screener_recommend_strategies().await?; + let resp = context.ctx.screener_recommend_strategies(market).await?; Ok(resp) })?; Ok(()) @@ -58,12 +60,14 @@ pub unsafe extern "system" fn Java_com_longbridge_SdkNative_screenerContextUserS mut env: JNIEnv, _class: JClass, context: i64, + market: JString, callback: JObject, ) { jni_result(&mut env, (), |env| { let context = &*(context as *const ContextObj); + let market: String = FromJValue::from_jvalue(env, market.into())?; async_util::execute(env, callback, async move { - let resp = context.ctx.screener_user_strategies().await?; + let resp = context.ctx.screener_user_strategies(market).await?; Ok(resp) })?; Ok(()) @@ -107,7 +111,7 @@ pub unsafe extern "system" fn Java_com_longbridge_SdkNative_screenerContextSearc async_util::execute(env, callback, async move { let resp = context .ctx - .screener_search(market, strategy_id, page, size) + .screener_search(market, strategy_id, vec![], vec![], page, size) .await?; Ok(resp) })?; diff --git a/java/src/types/classes.rs b/java/src/types/classes.rs index 2b1dbab87..29c7751c2 100644 --- a/java/src/types/classes.rs +++ b/java/src/types/classes.rs @@ -2208,7 +2208,7 @@ impl_java_class!( longbridge::fundamental::OperatingFinancial, [ code, - counter_id, + symbol, currency, name, region, diff --git a/nodejs/index.d.ts b/nodejs/index.d.ts index 8650cc6be..40056b695 100644 --- a/nodejs/index.d.ts +++ b/nodejs/index.d.ts @@ -2067,13 +2067,25 @@ export declare class ScreenerContext { /** Create a new `ScreenerContext` */ static new(config: Config): ScreenerContext /** Get recommended built-in screener strategies */ - screenerRecommendStrategies(): Promise + screenerRecommendStrategies(market: string): Promise /** Get the current user's saved screener strategies */ - screenerUserStrategies(): Promise + screenerUserStrategies(market: string): Promise /** Get detail for one screener strategy by ID */ screenerStrategy(id: number): Promise - /** Search / screen securities using a strategy */ - screenerSearch(market: string, strategyId: number | undefined | null, page: number, size: number): Promise + /** + * Search / screen securities using a strategy or custom conditions. + * + * When `strategyId` is given (Mode A), the strategy is fetched from the AI + * endpoint and its filters drive the search. The market is taken from the + * strategy response. + * + * When `strategyId` is `null` / `undefined` (Mode B), `conditions` must be + * `ScreenerCondition` objects and `market` is used directly. + * + * `filter_` is stripped from every `items[].indicators[].key` in the + * response before it is returned. + */ + screenerSearch(market: string, strategyId: number | undefined | null, conditions: Array, show: Array, page: number, size: number): Promise /** Get all available screener indicator definitions */ screenerIndicators(): Promise } @@ -5107,6 +5119,21 @@ export interface ReplaceOrderOptions { remark?: string } +/** A filter condition for screener_search Mode B. */ +export interface ScreenerCondition { + /** Indicator key without filter_ prefix, e.g. "pettm", "roe", "macd_day" */ + key: string + /** Lower bound (empty = no lower bound) */ + min: string + /** Upper bound (empty = no upper bound) */ + max: string + /** + * Technical indicator params as JSON string (empty object "{}" for + * fundamental indicators) + */ + techValues: string +} + /** Screener indicator definitions response. `data` is a JSON string. */ export interface ScreenerIndicatorsResponse { /** Raw indicator definitions data (JSON string) */ diff --git a/nodejs/src/screener/context.rs b/nodejs/src/screener/context.rs index b5b16fbbd..92ab8b7ef 100644 --- a/nodejs/src/screener/context.rs +++ b/nodejs/src/screener/context.rs @@ -25,10 +25,11 @@ impl ScreenerContext { #[napi] pub async fn screener_recommend_strategies( &self, + market: String, ) -> Result { Ok(self .ctx - .screener_recommend_strategies() + .screener_recommend_strategies(market) .await .map_err(ErrorNewType)? .into()) @@ -36,10 +37,13 @@ impl ScreenerContext { /// Get the current user's saved screener strategies #[napi] - pub async fn screener_user_strategies(&self) -> Result { + pub async fn screener_user_strategies( + &self, + market: String, + ) -> Result { Ok(self .ctx - .screener_user_strategies() + .screener_user_strategies(market) .await .map_err(ErrorNewType)? .into()) @@ -56,18 +60,32 @@ impl ScreenerContext { .into()) } - /// Search / screen securities using a strategy + /// Search / screen securities using a strategy or custom conditions. + /// + /// When `strategyId` is given (Mode A), the strategy is fetched from the AI + /// endpoint and its filters drive the search. The market is taken from the + /// strategy response. + /// + /// When `strategyId` is `null` / `undefined` (Mode B), `conditions` must be + /// `ScreenerCondition` objects and `market` is used directly. + /// + /// `filter_` is stripped from every `items[].indicators[].key` in the + /// response before it is returned. #[napi] pub async fn screener_search( &self, market: String, strategy_id: Option, + conditions: Vec, + show: Vec, page: u32, size: u32, ) -> Result { + let lb_conditions: Vec = + conditions.into_iter().map(Into::into).collect(); Ok(self .ctx - .screener_search(market, strategy_id, page, size) + .screener_search(market, strategy_id, lb_conditions, show, page, size) .await .map_err(ErrorNewType)? .into()) diff --git a/nodejs/src/screener/types.rs b/nodejs/src/screener/types.rs index 3956b8887..f2a239c50 100644 --- a/nodejs/src/screener/types.rs +++ b/nodejs/src/screener/types.rs @@ -89,3 +89,33 @@ impl From for ScreenerIndicatorsResponse { } } } + +// ── ScreenerCondition ───────────────────────────────────────────── + +/// A filter condition for screener_search Mode B. +#[napi_derive::napi(object)] +#[derive(Debug, Clone, Default)] +pub struct ScreenerCondition { + /// Indicator key without filter_ prefix, e.g. "pettm", "roe", "macd_day" + pub key: String, + /// Lower bound (empty = no lower bound) + pub min: String, + /// Upper bound (empty = no upper bound) + pub max: String, + /// Technical indicator params as JSON string (empty object "{}" for + /// fundamental indicators) + pub tech_values: String, +} + +impl From for longbridge::screener::ScreenerCondition { + fn from(v: ScreenerCondition) -> Self { + let tv: serde_json::Value = + serde_json::from_str(&v.tech_values).unwrap_or(serde_json::json!({})); + Self { + key: v.key, + min: v.min, + max: v.max, + tech_values: tv, + } + } +} diff --git a/python/pysrc/longbridge/openapi.pyi b/python/pysrc/longbridge/openapi.pyi index aa3b1cb2d..fa4bb05fd 100644 --- a/python/pysrc/longbridge/openapi.pyi +++ b/python/pysrc/longbridge/openapi.pyi @@ -9570,6 +9570,8 @@ class OperatingFinancial: code: str """Ticker code""" + symbol: str + """Symbol in CODE.MARKET format (e.g. ``AAPL.US``)""" currency: str """Reporting currency""" name: str @@ -10530,6 +10532,28 @@ class RankListResponse: # ── ScreenerContext ─────────────────────────────────────────────── +class ScreenerCondition: + """A filter condition for :meth:`ScreenerContext.screener_search` Mode B.""" + + key: str + """Indicator key without ``filter_`` prefix, e.g. ``"pettm"``, ``"roe"``, ``"macd_day"``""" + min: str + """Lower bound (empty string = no lower bound)""" + max: str + """Upper bound (empty string = no upper bound)""" + tech_values: str + """Technical indicator params as JSON string. Use ``"{}"`` for fundamental indicators. + Example: ``'{"category": "goldenfork", "period": "day"}'``""" + + def __init__( + self, + key: str, + min: str = "", + max: str = "", + tech_values: str = "{}", + ) -> None: ... + + class ScreenerRecommendStrategiesResponse: """Recommended screener strategies response. ``data`` is a Python dict/list from JSON.""" @@ -10570,11 +10594,11 @@ class ScreenerContext: def __init__(self, config: Config) -> None: ... - def screener_recommend_strategies(self) -> ScreenerRecommendStrategiesResponse: - """Get recommended built-in screener strategies.""" + def screener_recommend_strategies(self, market: str) -> ScreenerRecommendStrategiesResponse: + """Get preset built-in screener strategies.""" ... - def screener_user_strategies(self) -> ScreenerUserStrategiesResponse: + def screener_user_strategies(self, market: str) -> ScreenerUserStrategiesResponse: """Get the current user's saved screener strategies.""" ... @@ -10586,10 +10610,23 @@ class ScreenerContext: self, market: str, strategy_id: Optional[int] = None, - page: int = 1, + conditions: List["ScreenerCondition"] = [], + show: List[str] = [], + page: int = 0, size: int = 20, ) -> ScreenerSearchResponse: - """Search / screen securities using a strategy.""" + """Search / screen securities using a strategy or custom conditions. + + When *strategy_id* is given (Mode A), the strategy is fetched from the AI + endpoint and its filters are forwarded to the search request. The + ``market`` is taken from the strategy response. + + When *strategy_id* is ``None`` (Mode B), *conditions* must be provided as + :class:`ScreenerCondition` objects and *market* is used directly. + + ``filter_`` is stripped from every ``items[].indicators[].key`` in the + response before it is returned. + """ ... def screener_indicators(self) -> ScreenerIndicatorsResponse: @@ -10605,12 +10642,14 @@ class AsyncScreenerContext: def screener_recommend_strategies( self, + market: str, ) -> Awaitable[ScreenerRecommendStrategiesResponse]: - """Get recommended built-in screener strategies. Returns awaitable.""" + """Get preset built-in screener strategies. Returns awaitable.""" ... def screener_user_strategies( self, + market: str, ) -> Awaitable[ScreenerUserStrategiesResponse]: """Get the current user's saved screener strategies. Returns awaitable.""" ... @@ -10625,10 +10664,24 @@ class AsyncScreenerContext: self, market: str, strategy_id: Optional[int] = None, - page: int = 1, + conditions: List["ScreenerCondition"] = [], + show: List[str] = [], + page: int = 0, size: int = 20, ) -> Awaitable[ScreenerSearchResponse]: - """Search / screen securities using a strategy. Returns awaitable.""" + """Search / screen securities using a strategy or custom conditions. + Returns awaitable. + + When *strategy_id* is given (Mode A), the strategy is fetched from the AI + endpoint and its filters are forwarded to the search request. The + ``market`` is taken from the strategy response. + + When *strategy_id* is ``None`` (Mode B), *conditions* must be provided as + :class:`ScreenerCondition` objects and *market* is used directly. + + ``filter_`` is stripped from every ``items[].indicators[].key`` in the + response before it is returned. + """ ... def screener_indicators(self) -> Awaitable[ScreenerIndicatorsResponse]: diff --git a/python/src/screener/context.rs b/python/src/screener/context.rs index 4030702f7..864f3210b 100644 --- a/python/src/screener/context.rs +++ b/python/src/screener/context.rs @@ -21,19 +21,22 @@ impl ScreenerContext { } /// Get recommended built-in screener strategies. - fn screener_recommend_strategies(&self) -> PyResult { + fn screener_recommend_strategies( + &self, + market: String, + ) -> PyResult { Ok(self .ctx - .screener_recommend_strategies() + .screener_recommend_strategies(market) .map_err(ErrorNewType)? .into()) } /// Get the current user's saved screener strategies. - fn screener_user_strategies(&self) -> PyResult { + fn screener_user_strategies(&self, market: String) -> PyResult { Ok(self .ctx - .screener_user_strategies() + .screener_user_strategies(market) .map_err(ErrorNewType)? .into()) } @@ -44,17 +47,21 @@ impl ScreenerContext { } /// Search / screen securities using a strategy. - #[pyo3(signature = (market, strategy_id = None, page = 1, size = 20))] + #[pyo3(signature = (market, strategy_id = None, conditions = vec![], show = vec![], page = 0, size = 20))] fn screener_search( &self, market: String, strategy_id: Option, + conditions: Vec, + show: Vec, page: u32, size: u32, ) -> PyResult { + let lb_conditions: Vec = + conditions.into_iter().map(Into::into).collect(); Ok(self .ctx - .screener_search(market, strategy_id, page, size) + .screener_search(market, strategy_id, lb_conditions, show, page, size) .map_err(ErrorNewType)? .into()) } diff --git a/python/src/screener/context_async.rs b/python/src/screener/context_async.rs index ddd026999..5c14848df 100644 --- a/python/src/screener/context_async.rs +++ b/python/src/screener/context_async.rs @@ -22,11 +22,11 @@ impl AsyncScreenerContext { } /// Get recommended built-in screener strategies. Returns awaitable. - fn screener_recommend_strategies(&self, py: Python<'_>) -> PyResult> { + fn screener_recommend_strategies(&self, py: Python<'_>, market: String) -> PyResult> { let ctx = self.ctx.clone(); pyo3_async_runtimes::tokio::future_into_py(py, async move { Ok(ScreenerRecommendStrategiesResponse::from( - ctx.screener_recommend_strategies() + ctx.screener_recommend_strategies(market) .await .map_err(ErrorNewType)?, )) @@ -35,11 +35,13 @@ impl AsyncScreenerContext { } /// Get the current user's saved screener strategies. Returns awaitable. - fn screener_user_strategies(&self, py: Python<'_>) -> PyResult> { + fn screener_user_strategies(&self, py: Python<'_>, market: String) -> PyResult> { let ctx = self.ctx.clone(); pyo3_async_runtimes::tokio::future_into_py(py, async move { Ok(ScreenerUserStrategiesResponse::from( - ctx.screener_user_strategies().await.map_err(ErrorNewType)?, + ctx.screener_user_strategies(market) + .await + .map_err(ErrorNewType)?, )) }) .map(|b| b.unbind()) @@ -57,19 +59,24 @@ impl AsyncScreenerContext { } /// Search / screen securities using a strategy. Returns awaitable. - #[pyo3(signature = (market, strategy_id = None, page = 1, size = 20))] + #[allow(clippy::too_many_arguments)] + #[pyo3(signature = (market, strategy_id = None, conditions = vec![], show = vec![], page = 0, size = 20))] fn screener_search( &self, py: Python<'_>, market: String, strategy_id: Option, + conditions: Vec, + show: Vec, page: u32, size: u32, ) -> PyResult> { let ctx = self.ctx.clone(); + let lb_conditions: Vec = + conditions.into_iter().map(Into::into).collect(); pyo3_async_runtimes::tokio::future_into_py(py, async move { Ok(ScreenerSearchResponse::from( - ctx.screener_search(market, strategy_id, page, size) + ctx.screener_search(market, strategy_id, lb_conditions, show, page, size) .await .map_err(ErrorNewType)?, )) diff --git a/python/src/screener/mod.rs b/python/src/screener/mod.rs index 37c3193e9..9d7ca43e5 100644 --- a/python/src/screener/mod.rs +++ b/python/src/screener/mod.rs @@ -11,6 +11,7 @@ pub(crate) fn register_types(parent: &Bound) -> PyResult<()> { parent.add_class::()?; parent.add_class::()?; parent.add_class::()?; + parent.add_class::()?; parent.add_class::()?; parent.add_class::()?; Ok(()) diff --git a/python/src/screener/types.rs b/python/src/screener/types.rs index b87ca8600..69d0eecce 100644 --- a/python/src/screener/types.rs +++ b/python/src/screener/types.rs @@ -105,3 +105,47 @@ impl From for ScreenerIndicatorsResponse { } } } + +// ── ScreenerCondition ───────────────────────────────────────────── + +/// A filter condition for screener_search Mode B. +#[pyclass(get_all, set_all, from_py_object)] +#[derive(Debug, Clone, Default)] +pub(crate) struct ScreenerCondition { + /// Indicator key without filter_ prefix, e.g. "pettm", "roe", "macd_day" + pub key: String, + /// Lower bound (empty = no lower bound) + pub min: String, + /// Upper bound (empty = no upper bound) + pub max: String, + /// Technical indicator params as JSON string (empty object "{}" for + /// fundamental indicators) + pub tech_values: String, +} + +#[pymethods] +impl ScreenerCondition { + #[new] + #[pyo3(signature = (key, min="", max="", tech_values="{}"))] + pub fn new(key: String, min: &str, max: &str, tech_values: &str) -> Self { + Self { + key, + min: min.to_string(), + max: max.to_string(), + tech_values: tech_values.to_string(), + } + } +} + +impl From for longbridge::screener::ScreenerCondition { + fn from(v: ScreenerCondition) -> Self { + let tv: serde_json::Value = + serde_json::from_str(&v.tech_values).unwrap_or(serde_json::json!({})); + Self { + key: v.key, + min: v.min, + max: v.max, + tech_values: tv, + } + } +} diff --git a/rust/src/blocking/screener.rs b/rust/src/blocking/screener.rs index b5cbd3e1b..b80ca3fd9 100644 --- a/rust/src/blocking/screener.rs +++ b/rust/src/blocking/screener.rs @@ -35,15 +35,21 @@ impl ScreenerContextSync { } /// Get recommended built-in screener strategies - pub fn screener_recommend_strategies(&self) -> Result { + pub fn screener_recommend_strategies( + &self, + market: impl Into + Send + 'static, + ) -> Result { self.rt - .call(|ctx| async move { ctx.screener_recommend_strategies().await }) + .call(|ctx| async move { ctx.screener_recommend_strategies(market).await }) } /// Get the current user's saved screener strategies - pub fn screener_user_strategies(&self) -> Result { + pub fn screener_user_strategies( + &self, + market: impl Into + Send + 'static, + ) -> Result { self.rt - .call(|ctx| async move { ctx.screener_user_strategies().await }) + .call(|ctx| async move { ctx.screener_user_strategies(market).await }) } /// Get detail for one screener strategy by ID @@ -57,11 +63,14 @@ impl ScreenerContextSync { &self, market: impl Into + Send + 'static, strategy_id: Option, + conditions: Vec, + show: Vec, page: u32, size: u32, ) -> Result { self.rt.call(move |ctx| async move { - ctx.screener_search(market, strategy_id, page, size).await + ctx.screener_search(market, strategy_id, conditions, show, page, size) + .await }) } diff --git a/rust/src/fundamental/types.rs b/rust/src/fundamental/types.rs index b6332d4d2..bbae2ec51 100644 --- a/rust/src/fundamental/types.rs +++ b/rust/src/fundamental/types.rs @@ -873,8 +873,12 @@ pub struct OperatingItem { pub struct OperatingFinancial { /// Ticker code (may be empty) pub code: String, - /// Raw counter ID (may be empty) - pub counter_id: String, + /// Symbol in `CODE.MARKET` format (may be empty) + #[serde( + rename = "counter_id", + deserialize_with = "deserialize_counter_id_as_symbol" + )] + pub symbol: String, /// Reporting currency pub currency: String, /// Company name diff --git a/rust/src/market/context.rs b/rust/src/market/context.rs index 4edba7306..e0a27b470 100644 --- a/rust/src/market/context.rs +++ b/rust/src/market/context.rs @@ -391,9 +391,27 @@ impl MarketContext { pub async fn rank_categories(&self) -> Result { #[derive(Serialize)] struct Empty {} - let raw: serde_json::Value = self + let mut raw: serde_json::Value = self .get("/v1/quote/market/rank/categories", Empty {}) .await?; + // Strip the "ib_" prefix from all key fields so callers get clean keys + // that can be passed back to rank_list without the prefix. + if let Some(tags) = raw["first_tags"].as_array_mut() { + for tag in tags.iter_mut() { + if let Some(k) = tag["key"].as_str() { + let stripped = k.strip_prefix("ib_").unwrap_or(k).to_string(); + tag["key"] = serde_json::Value::String(stripped); + } + if let Some(subs) = tag["second_tags"].as_array_mut() { + for sub in subs.iter_mut() { + if let Some(sk) = sub["key"].as_str() { + let stripped = sk.strip_prefix("ib_").unwrap_or(sk).to_string(); + sub["key"] = serde_json::Value::String(stripped); + } + } + } + } + } Ok(RankCategoriesResponse { data: raw }) } @@ -413,11 +431,18 @@ impl MarketContext { delay_bmp: &'static str, need_article: &'static str, } + let key_str = key.into(); + // Add "ib_" prefix if the caller passed a clean key (without it). + let api_key = if key_str.starts_with("ib_") { + key_str + } else { + format!("ib_{key_str}") + }; let raw: serde_json::Value = self .get( "/v1/quote/market/rank/list", Query { - key: key.into(), + key: api_key, delay_bmp: "false", need_article: if need_article { "true" } else { "false" }, }, diff --git a/rust/src/screener/context.rs b/rust/src/screener/context.rs index d17746aaf..6506f7fa0 100644 --- a/rust/src/screener/context.rs +++ b/rust/src/screener/context.rs @@ -46,7 +46,7 @@ impl ScreenerContext { self.0.log_subscriber.clone() } - async fn get(&self, path: &'static str, query: Q) -> Result + async fn get(&self, path: &str, query: Q) -> Result where R: DeserializeOwned + Send + Sync + 'static, Q: Serialize + Send + Sync, @@ -63,7 +63,7 @@ impl ScreenerContext { .0) } - async fn post(&self, path: &'static str, body: B) -> Result + async fn post(&self, path: &str, body: B) -> Result where R: DeserializeOwned + Send + Sync + 'static, B: std::fmt::Debug + Serialize + Send + Sync + 'static, @@ -82,16 +82,24 @@ impl ScreenerContext { // ── screener_recommend_strategies ───────────────────────────── - /// Get recommended built-in screener strategies. + /// Get preset built-in screener strategies. /// - /// Path: `GET /v1/quote/screener/strategies/recommend` + /// Path: `GET /v1/quote/ai/screener/strategies/recommend` pub async fn screener_recommend_strategies( &self, + market: impl Into, ) -> Result { #[derive(Serialize)] - struct Empty {} + struct Query { + market: String, + } let raw: serde_json::Value = self - .get("/v1/quote/screener/strategies/recommend", Empty {}) + .get( + "/v1/quote/ai/screener/strategies/recommend", + Query { + market: market.into(), + }, + ) .await?; Ok(ScreenerRecommendStrategiesResponse { data: raw }) } @@ -100,12 +108,22 @@ impl ScreenerContext { /// Get the current user's saved screener strategies. /// - /// Path: `GET /v1/quote/screener/strategies/mine` - pub async fn screener_user_strategies(&self) -> Result { + /// Path: `GET /v1/quote/ai/screener/strategies/mine` + pub async fn screener_user_strategies( + &self, + market: impl Into, + ) -> Result { #[derive(Serialize)] - struct Empty {} + struct Query { + market: String, + } let raw: serde_json::Value = self - .get("/v1/quote/screener/strategies/mine", Empty {}) + .get( + "/v1/quote/ai/screener/strategies/mine", + Query { + market: market.into(), + }, + ) .await?; Ok(ScreenerUserStrategiesResponse { data: raw }) } @@ -114,65 +132,257 @@ impl ScreenerContext { /// Get detail for one screener strategy by ID. /// - /// Path: `GET /v1/quote/screener/strategy?id=` + /// Path: `GET /v1/quote/ai/screener/strategy/{id}` + /// + /// The `filter_` prefix is stripped from every `filters[].key` before + /// returning so callers see clean keys like `pettm` instead of + /// `filter_pettm`. pub async fn screener_strategy(&self, id: i64) -> Result { + let path = format!("/v1/quote/ai/screener/strategy/{id}"); #[derive(Serialize)] - struct Query { - id: i64, + struct Empty {} + let mut raw: serde_json::Value = self.get(&path, Empty {}).await?; + // Strip filter_ prefix from filter.filters[].key + if let Some(filters) = raw["filter"]["filters"].as_array_mut() { + for f in filters.iter_mut() { + if let Some(k) = f["key"].as_str() { + let stripped = k.strip_prefix("filter_").unwrap_or(k).to_string(); + f["key"] = serde_json::Value::String(stripped); + } + } } - let raw: serde_json::Value = self - .get("/v1/quote/screener/strategy", Query { id }) - .await?; Ok(ScreenerStrategyResponse { data: raw }) } // ── screener_search ─────────────────────────────────────────── - /// Search / screen securities using a strategy. + /// Default return columns always included in a screener search request. + const DEFAULT_RETURNS: &'static [&'static str] = &[ + "filter_prevclose", + "filter_prevchg", + "filter_marketcap", + "filter_salesgrowthyoy", + "filter_pettm", + "filter_pbmrq", + "filter_industry", + ]; + + /// Search / screen securities using a strategy or custom conditions. + /// + /// Path: `POST /v1/quote/ai/screener/search` + /// + /// ## Mode A — strategy ID given /// - /// Path: `POST /v1/quote/screener/search` + /// When `strategy_id` is `Some`, the strategy is fetched from + /// `GET /v1/quote/ai/screener/strategy/{id}` and its `filter.filters[]` + /// are forwarded to the search endpoint together with + /// [`DEFAULT_RETURNS`]. The `market` is taken from the strategy + /// response (falls back to `"US"` if absent or `"-"`). /// - /// When `strategy_id` is `Some`, it is included in the request body. - /// When `None`, only `market`, `page`, and `size` are sent (custom - /// filter support is out of scope for this SDK). + /// ## Mode B — custom conditions + /// + /// When `strategy_id` is `None` and `conditions` is non-empty each + /// element is either a `"KEY:MIN:MAX"` string **or** a JSON object with + /// `key`, `min`, `max`, and optional `tech_values` fields. The + /// supplied `market` is used directly. `DEFAULT_RETURNS` plus every + /// condition key are added to the `returns` list. + /// + /// The `filter_` prefix is stripped from every `items[].indicators[].key` + /// in the response before it is returned to the caller. + /// + /// `page` is 0-indexed. pub async fn screener_search( &self, market: impl Into, strategy_id: Option, + conditions: Vec, + show: Vec, page: u32, size: u32, ) -> Result { - #[derive(Debug, Serialize)] - struct Body { - market: String, - #[serde(skip_serializing_if = "Option::is_none")] - strategy_id: Option, - page: u32, - size: u32, + let market: String = market.into(); + + // ── build filters and effective market ────────────────────────────── + let (effective_market, filters) = if let Some(sid) = strategy_id { + // Mode A: fetch strategy from AI endpoint + let path = format!("/v1/quote/ai/screener/strategy/{sid}"); + #[derive(Serialize)] + struct Empty {} + let strategy: serde_json::Value = self.get(&path, Empty {}).await?; + + let mkt_val = strategy["market"].as_str().unwrap_or("US").to_uppercase(); + let mkt = if mkt_val.is_empty() || mkt_val == "-" { + "US".to_string() + } else { + mkt_val + }; + + let mut filters: Vec = Vec::new(); + if let Some(f) = strategy["filter"]["filters"].as_array() { + for ind in f { + let key = ind["key"].as_str().unwrap_or("").to_string(); + if key.is_empty() { + continue; + } + let min = ind["min"].as_str().unwrap_or("").to_string(); + let max = ind["max"].as_str().unwrap_or("").to_string(); + let tech_values = if ind["tech_values"].is_object() { + ind["tech_values"].clone() + } else { + serde_json::json!({}) + }; + filters.push(serde_json::json!({ + "key": key, + "min": min, + "max": max, + "tech_values": tech_values, + })); + } + } + (mkt, filters) + } else { + // Mode B: typed condition objects + let filters: Vec = conditions + .iter() + .filter(|c| !c.key.is_empty()) + .map(|c| { + let api_key = if c.key.starts_with("filter_") { + c.key.clone() + } else { + format!("filter_{}", c.key) + }; + let tv = if c.tech_values.is_object() { + c.tech_values.clone() + } else { + serde_json::json!({}) + }; + serde_json::json!({ + "key": api_key, + "min": c.min, + "max": c.max, + "tech_values": tv, + }) + }) + .collect(); + (market, filters) + }; + + // ── build returns list ─────────────────────────────────────────────── + let mut returns: Vec = Self::DEFAULT_RETURNS + .iter() + .map(|s| s.to_string()) + .collect(); + // add keys from filters (with filter_ prefix for the API) + for f in &filters { + if let Some(k) = f["key"].as_str() { + let api_key = if k.starts_with("filter_") { + k.to_string() + } else { + format!("filter_{k}") + }; + if !returns.contains(&api_key) { + returns.push(api_key); + } + } } - let raw: serde_json::Value = self - .post( - "/v1/quote/screener/search", - Body { - market: market.into(), - strategy_id, - page, - size, - }, - ) - .await?; - Ok(ScreenerSearchResponse { data: raw }) + // add extra columns requested by the caller + for s in &show { + let api_key = if s.starts_with("filter_") { + s.clone() + } else { + format!("filter_{s}") + }; + if !returns.contains(&api_key) { + returns.push(api_key); + } + } + + // ── POST request ──────────────────────────────────────────────────── + let body = serde_json::json!({ + "market": effective_market, + "filters": filters, + "returns": returns, + "page": page, + "size": size, + }); + + let raw: serde_json::Value = self.post("/v1/quote/ai/screener/search", body).await?; + Ok(ScreenerSearchResponse { + data: strip_filter_prefix_from_search_results(raw), + }) } // ── screener_indicators ─────────────────────────────────────── /// Get all available screener indicator definitions. /// - /// Path: `GET /v1/quote/screener/indicators` + /// Path: `GET /v1/quote/ai/screener/indicators` + /// + /// Post-processing applied before returning: + /// - `filter_` prefix is stripped from every `groups[].indicators[].key` + /// - `tech_values` is built from `tech_indicators`: `{tech_key: [{value, + /// label}]}` pub async fn screener_indicators(&self) -> Result { #[derive(Serialize)] struct Empty {} - let raw: serde_json::Value = self.get("/v1/quote/screener/indicators", Empty {}).await?; + let mut raw: serde_json::Value = self + .get("/v1/quote/ai/screener/indicators", Empty {}) + .await?; + if let Some(groups) = raw["groups"].as_array_mut() { + for group in groups.iter_mut() { + if let Some(indicators) = group["indicators"].as_array_mut() { + for ind in indicators.iter_mut() { + // Strip filter_ prefix from key + if let Some(k) = ind["key"].as_str() { + let stripped = k.strip_prefix("filter_").unwrap_or(k).to_string(); + ind["key"] = serde_json::Value::String(stripped); + } + // Build tech_values from tech_indicators + if let Some(tech_inds) = ind["tech_indicators"].as_array().cloned() { + let tv: serde_json::Map = tech_inds + .iter() + .filter_map(|ti| { + let key = ti["tech_key"].as_str()?.to_string(); + let opts: Vec = ti["tech_items"] + .as_array() + .unwrap_or(&vec![]) + .iter() + .map(|item| { + serde_json::json!({ + "value": item["item_value"].as_str().unwrap_or(""), + "label": item["item_name"].as_str().unwrap_or(""), + }) + }) + .collect(); + Some((key, serde_json::Value::Array(opts))) + }) + .collect(); + if !tv.is_empty() { + ind["tech_values"] = serde_json::Value::Object(tv); + } + } + } + } + } + } Ok(ScreenerIndicatorsResponse { data: raw }) } } + +/// Strip `filter_` prefix from every `items[].indicators[].key` in a raw +/// screener search result. +fn strip_filter_prefix_from_search_results(mut raw: serde_json::Value) -> serde_json::Value { + if let Some(items) = raw["items"].as_array_mut() { + for item in items.iter_mut() { + if let Some(indicators) = item["indicators"].as_array_mut() { + for ind in indicators.iter_mut() { + if let Some(k) = ind["key"].as_str() { + let stripped = k.strip_prefix("filter_").unwrap_or(k).to_string(); + ind["key"] = serde_json::Value::String(stripped); + } + } + } + } + } + raw +} diff --git a/rust/src/screener/types.rs b/rust/src/screener/types.rs index 0f71a2c0a..a60ac41da 100644 --- a/rust/src/screener/types.rs +++ b/rust/src/screener/types.rs @@ -39,6 +39,31 @@ pub struct ScreenerStrategyResponse { pub data: serde_json::Value, } +// ── screener_condition ─────────────────────────────────────────── + +/// A filter condition for [`crate::ScreenerContext::screener_search`] Mode B. +/// +/// `key` is the indicator key (without the `filter_` prefix, e.g. `"pettm"`). +/// `min` / `max` bound the range; leave empty for an open bound. +/// `tech_values` is used for technical indicators (e.g. MACD/RSI); pass an +/// empty map `{}` for fundamental indicators. +#[derive(Debug, Clone, Serialize, Deserialize, Default)] +pub struct ScreenerCondition { + /// Indicator key without `filter_` prefix, e.g. `"pettm"`, `"roe"`, + /// `"macd_day"` + pub key: String, + /// Lower bound (empty string = no lower bound) + #[serde(default)] + pub min: String, + /// Upper bound (empty string = no upper bound) + #[serde(default)] + pub max: String, + /// Technical indicator parameters (empty map for fundamental indicators). + /// Example: `{"category": "goldenfork", "period": "day"}` + #[serde(default)] + pub tech_values: serde_json::Value, +} + // ── screener_search ─────────────────────────────────────────────── /// Response for [`crate::ScreenerContext::screener_search`] From 56c52a56009579919101b29ececda2585b46e734 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=A2=81=E7=AB=A0=E6=B4=AA?= Date: Sat, 23 May 2026 21:23:18 +0800 Subject: [PATCH 13/26] fix(ci): add contents:write permission to publish-nodejs-sdk job Co-Authored-By: Claude Sonnet 4.6 (1M context) --- .github/workflows/release.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 1e90de553..937ca3e3c 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -684,6 +684,8 @@ jobs: publish-nodejs-sdk: runs-on: ubuntu-24.04 + permissions: + contents: write needs: - build steps: From c5275cfa57ad8ffdf7e2dd5fce6ba00cd8ae3c10 Mon Sep 17 00:00:00 2001 From: Hogan Date: Sat, 23 May 2026 23:08:31 +0800 Subject: [PATCH 14/26] fix(ci): pass GITHUB_TOKEN to napi prepublish (#531) ## Summary - `napi prepublish -t npm` needs `GITHUB_TOKEN` explicitly passed via `env:` to create the GitHub Release. Without it the request is unauthenticated (401). ## Fix Added `GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}` to the `Publish` step in `publish-nodejs-sdk` job. Co-authored-by: Claude Sonnet 4.6 (1M context) --- .github/workflows/release.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 937ca3e3c..d7dc64c16 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -719,6 +719,7 @@ jobs: working-directory: ./nodejs env: NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} publish-java-sdk: runs-on: ubuntu-24.04 From ae02853eebb739586da82f48ed54e7a3c0748052 Mon Sep 17 00:00:00 2001 From: Hogan Date: Tue, 2 Jun 2026 17:21:41 +0800 Subject: [PATCH 15/26] fix(calendar): expose next_date cursor in finance_calendar response (#532) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary - The `/v1/quote/finance_calendar` endpoint paginates via a `next_date` cursor, but all SDK bindings were silently dropping it, making multi-page range queries return incomplete data (e.g. CRM.US, PDD.US, MRVL.US missing for a 2026-05-23→05-30 range) - `next_date` is now returned as-is in `CalendarEventsResponse` across all language SDKs so callers can follow the cursor themselves ## Changes | File | Change | |------|--------| | `rust/src/calendar/types.rs` | Add `next_date` to `CalendarEventsResponse` | | `rust/src/calendar/context.rs` | Revert to single request (no internal pagination) | | `c/src/calendar_context/types.rs` | Add `next_date` to C binding owned/FFI types | | `c/csrc/include/longbridge.h` | Add `next_date` to `lb_calendar_events_response_t` | | `cpp/include/calendar_context.hpp` | Add `next_date` to C++ `CalendarEventsResponse` struct | | `cpp/src/calendar_context.cpp` | Populate `next_date` from C response in callback | | `nodejs/index.d.ts` | Add `nextDate: string` to `CalendarEventsResponse` | | `python/pysrc/longbridge/openapi.pyi` | Add `next_date: str` to `CalendarEventsResponse` | | `java/.../CalendarEventsResponse.java` | Add `public String nextDate` | ## Related - Go SDK fix: longbridge/openapi-go#fix/finance-calendar-pagination - Issue: https://github.com/longbridge/developers/issues/1045#issuecomment-4591933632 --------- Co-authored-by: Claude Sonnet 4.6 (1M context) --- c/csrc/include/longbridge.h | 4 ++++ c/src/calendar_context/types.rs | 6 ++++++ cpp/include/calendar_context.hpp | 3 ++- cpp/src/calendar_context.cpp | 1 + .../com/longbridge/calendar/CalendarEventsResponse.java | 2 ++ java/src/types/classes.rs | 3 ++- nodejs/index.d.ts | 2 ++ python/pysrc/longbridge/openapi.pyi | 2 ++ rust/src/calendar/context.rs | 3 +++ rust/src/calendar/types.rs | 4 ++++ 10 files changed, 28 insertions(+), 2 deletions(-) diff --git a/c/csrc/include/longbridge.h b/c/csrc/include/longbridge.h index cb8db05c0..81fefdb02 100644 --- a/c/csrc/include/longbridge.h +++ b/c/csrc/include/longbridge.h @@ -7110,6 +7110,10 @@ typedef struct lb_calendar_events_response_t { * Number of elements in the `list` array. */ uintptr_t num_list; + /** + * Pagination cursor; pass as start to fetch the next page, empty when there are no more pages. + */ + const char *next_date; } lb_calendar_events_response_t; /** diff --git a/c/src/calendar_context/types.rs b/c/src/calendar_context/types.rs index 6d1c559e7..014839660 100644 --- a/c/src/calendar_context/types.rs +++ b/c/src/calendar_context/types.rs @@ -198,16 +198,21 @@ pub struct CCalendarEventsResponse { pub list: *const CCalendarDateGroup, /// Number of elements in the `list` array. pub num_list: usize, + /// Pagination cursor; pass as start to fetch the next page, empty when + /// there are no more pages. + pub next_date: *const c_char, } pub(crate) struct CCalendarEventsResponseOwned { date: CString, list: CVec, + next_date: CString, } impl From for CCalendarEventsResponseOwned { fn from(v: CalendarEventsResponse) -> Self { Self { date: v.date.into(), list: v.list.into(), + next_date: v.next_date.into(), } } } @@ -218,6 +223,7 @@ impl ToFFI for CCalendarEventsResponseOwned { date: self.date.to_ffi_type(), list: self.list.to_ffi_type(), num_list: self.list.len(), + next_date: self.next_date.to_ffi_type(), } } } diff --git a/cpp/include/calendar_context.hpp b/cpp/include/calendar_context.hpp index f4c4ea65a..b42e28e53 100644 --- a/cpp/include/calendar_context.hpp +++ b/cpp/include/calendar_context.hpp @@ -26,7 +26,8 @@ struct CalendarEventInfo { std::string symbol; std::string market; std::string c /// Calendar events grouped by date. struct CalendarDateGroup { std::string date; int32_t count; std::vector infos; }; /// Response for finance_calendar — events grouped by date within the requested range. -struct CalendarEventsResponse { std::string date; std::vector list; }; +/// Response for finance_calendar — events grouped by date within the requested range. +struct CalendarEventsResponse { std::string date; std::vector list; std::string next_date; }; /// Financial calendar context — earnings, dividends, splits, IPOs, macro data. class CalendarContext { diff --git a/cpp/src/calendar_context.cpp b/cpp/src/calendar_context.cpp index ed9163f44..a4e48a29e 100644 --- a/cpp/src/calendar_context.cpp +++ b/cpp/src/calendar_context.cpp @@ -29,6 +29,7 @@ void CalendarContext::finance_calendar(CalendarCategory category, const std::str auto* r = (const lb_calendar_events_response_t*)res->data; CalendarEventsResponse resp; resp.date = r->date; + resp.next_date = r->next_date ? r->next_date : ""; for (size_t i = 0; i < r->num_list; ++i) { CalendarDateGroup grp; grp.date = r->list[i].date; grp.count = r->list[i].count; for (size_t j = 0; j < r->list[i].num_infos; ++j) { diff --git a/java/javasrc/src/main/java/com/longbridge/calendar/CalendarEventsResponse.java b/java/javasrc/src/main/java/com/longbridge/calendar/CalendarEventsResponse.java index 830a06e0d..b290b5065 100644 --- a/java/javasrc/src/main/java/com/longbridge/calendar/CalendarEventsResponse.java +++ b/java/javasrc/src/main/java/com/longbridge/calendar/CalendarEventsResponse.java @@ -6,4 +6,6 @@ public class CalendarEventsResponse { public String date; /** Per-day event groups. */ public CalendarDateGroup[] list; + /** Pagination cursor; pass as start to fetch the next page, empty when there are no more pages. */ + public String nextDate; } diff --git a/java/src/types/classes.rs b/java/src/types/classes.rs index 29c7751c2..141d5f839 100644 --- a/java/src/types/classes.rs +++ b/java/src/types/classes.rs @@ -1261,7 +1261,8 @@ impl_java_class!( [ date, #[java(objarray)] - list + list, + next_date ] ); diff --git a/nodejs/index.d.ts b/nodejs/index.d.ts index 40056b695..5de5f15f7 100644 --- a/nodejs/index.d.ts +++ b/nodejs/index.d.ts @@ -3397,6 +3397,8 @@ export interface CalendarEventsResponse { date: string /** Per-day event groups */ list: Array + /** Pagination cursor; pass as start to fetch the next page, empty when there are no more pages */ + nextDate: string } export declare const enum CashFlowDirection { diff --git a/python/pysrc/longbridge/openapi.pyi b/python/pysrc/longbridge/openapi.pyi index fa4bb05fd..5641e2bf9 100644 --- a/python/pysrc/longbridge/openapi.pyi +++ b/python/pysrc/longbridge/openapi.pyi @@ -10759,6 +10759,8 @@ class CalendarEventsResponse: """Start date of the query window""" list: list[CalendarDateGroup] """Per-day event groups""" + next_date: str + """Pagination cursor; pass as start to fetch the next page, empty when there are no more pages""" class CalendarCategory: diff --git a/rust/src/calendar/context.rs b/rust/src/calendar/context.rs index 6ed5bea05..5cbf6d90f 100644 --- a/rust/src/calendar/context.rs +++ b/rust/src/calendar/context.rs @@ -48,6 +48,9 @@ impl CalendarContext { /// Get financial calendar events. /// + /// The endpoint is paginated via `next_date`. When the returned + /// `next_date` is non-empty, pass it as `start` to fetch the next page. + /// /// Path: `GET /v1/quote/finance_calendar` pub async fn finance_calendar( &self, diff --git a/rust/src/calendar/types.rs b/rust/src/calendar/types.rs index 889f3e47e..b68a6488e 100644 --- a/rust/src/calendar/types.rs +++ b/rust/src/calendar/types.rs @@ -12,6 +12,10 @@ pub struct CalendarEventsResponse { pub date: String, /// Per-day event groups pub list: Vec, + /// Pagination cursor; pass as `start` to fetch the next page, empty when + /// there are no more pages + #[serde(default)] + pub next_date: String, } /// Events for one calendar date From e6c84eccc6d9f7766aad8bcd7b45ab2e13c964ad Mon Sep 17 00:00:00 2001 From: Hogan Date: Tue, 2 Jun 2026 18:48:11 +0800 Subject: [PATCH 16/26] chore: release 4.2.2 (#533) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Bump version to `4.2.2` and add CHANGELOG entry. ## Changes in 4.2.2 ### Fixed - **All languages:** `CalendarEventsResponse` now exposes `next_date` cursor — callers can pass it as `start` (with the same `end`) to fetch the next page of `/v1/quote/finance_calendar` results - **All languages:** `CalendarEventInfo.symbol` now returns standard symbol format (e.g. `CRM.US`) instead of raw `counter_id` format (e.g. `ST/US/CRM`) ## Related - PR #532 --- CHANGELOG.md | 7 +++++++ Cargo.toml | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 90b9bfb04..661e9fc3e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,13 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [4.2.2] + +### Fixed + +- **All languages:** `CalendarEventsResponse` now exposes `next_date` cursor — callers can pass it as `start` (with the same `end`) to fetch the next page of `/v1/quote/finance_calendar` results +- **All languages:** `CalendarEventInfo.symbol` now returns standard symbol format (e.g. `CRM.US`) instead of raw `counter_id` format (e.g. `ST/US/CRM`) + ## [4.2.1] ### Changed diff --git a/Cargo.toml b/Cargo.toml index fabc86433..932f6f842 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ resolver = "3" members = ["rust", "python", "nodejs", "java", "c"] [workspace.package] -version = "4.2.1" +version = "4.2.2" edition = "2024" [profile.release] From 48a70aac855fda71cb71c3739fa31a4b42fa170e Mon Sep 17 00:00:00 2001 From: Jason Lee Date: Thu, 4 Jun 2026 11:11:00 +0800 Subject: [PATCH 17/26] feat(quote): add etf_asset_allocation API (#535) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary - Add `etf_asset_allocation(symbol)` to `QuoteContext` in all SDKs (Rust, Python, Node.js, C, C++), querying `GET /v1/quote/etf-asset-allocation` for ETF asset allocation grouped by element type (`Holdings` / `Regional` / `AssetClass` / `Industry`) - New types: `AssetAllocationResponse` → `AssetAllocationGroup` → `AssetAllocationItem` → `HoldingDetail`, plus `ElementType` enum (`Unknown=0` / `Holdings=1` / `Regional=2` / `AssetClass=3` / `Industry=4`) - Public parameter is `symbol` (e.g. `QQQ.US`), converted internally via `symbol_to_counter_id` (with US ETF detection); `counter_id` in responses is converted back to standard symbol format - `name_locales_map` exposed as locale → name map (`HashMap` in Rust, `dict` in Python, object in Node.js, `std::map` in C++; C uses a `lb_locale_name_t` pair array sorted by locale) ## Per-SDK changes | SDK | Changes | |---|---| | Rust | `quote/types.rs`, `quote/context.rs`, `quote/mod.rs`, `blocking/quote.rs` | | Python | types + sync/async context + module registration + `openapi.pyi` stubs | | Node.js | types + context; `index.d.ts`/`index.js` regenerated via `npm run build:debug` | | C | `CElementType` enum, FFI types, `lb_quote_context_etf_asset_allocation`, `cbindgen.toml` exports; `longbridge.h` regenerated | | C++ | `types.hpp`, `convert.hpp`, `quote_context.hpp/.cpp` | ## Verification - `cargo clippy --all --all-features`: clean - `cargo +nightly fmt --all`: applied - All crates compile; C++ checked with `-fsyntax-only` 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.8 (1M context) --- CHANGELOG.md | 6 + c/cbindgen.toml | 9 ++ c/csrc/include/longbridge.h | 152 +++++++++++++++++- c/src/quote_context/context.rs | 20 +++ c/src/quote_context/enum_types.rs | 23 +++ c/src/quote_context/types.rs | 231 +++++++++++++++++++++++++++- cpp/include/quote_context.hpp | 5 + cpp/include/types.hpp | 68 ++++++++ cpp/src/convert.hpp | 48 ++++++ cpp/src/quote_context.cpp | 25 +++ nodejs/index.d.ts | 69 ++++++++- nodejs/index.js | 1 + nodejs/src/quote/context.rs | 32 ++-- nodejs/src/quote/types.rs | 121 +++++++++++++++ python/pysrc/longbridge/openapi.pyi | 97 ++++++++++++ python/src/quote/context.rs | 13 ++ python/src/quote/context_async.rs | 15 ++ python/src/quote/mod.rs | 5 + python/src/quote/types.rs | 121 +++++++++++++++ rust/src/blocking/quote.rs | 14 +- rust/src/quote/context.rs | 37 ++++- rust/src/quote/mod.rs | 5 + rust/src/quote/types.rs | 107 +++++++++++++ 23 files changed, 1199 insertions(+), 25 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 661e9fc3e..796462fac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + +### Added + +- **All languages:** `QuoteContext` gains `etf_asset_allocation(symbol)` — queries `GET /v1/quote/etf-asset-allocation` for ETF asset allocation grouped by element type (`Holdings` / `Regional` / `AssetClass` / `Industry`); returns `AssetAllocationResponse` with report date, position ratios, localized names, and per-holding detail + ## [4.2.2] ### Fixed diff --git a/c/cbindgen.toml b/c/cbindgen.toml index ed12c8f59..229a40d58 100644 --- a/c/cbindgen.toml +++ b/c/cbindgen.toml @@ -304,6 +304,12 @@ cpp_compat = true "COptionVolumeStats" = "lb_option_volume_stats_t" "COptionVolumeDailyStat" = "lb_option_volume_daily_stat_t" "COptionVolumeDaily" = "lb_option_volume_daily_t" +"CElementType" = "lb_element_type_t" +"CLocaleName" = "lb_locale_name_t" +"CHoldingDetail" = "lb_holding_detail_t" +"CAssetAllocationItem" = "lb_asset_allocation_item_t" +"CAssetAllocationGroup" = "lb_asset_allocation_group_t" +"CAssetAllocationResponse" = "lb_asset_allocation_response_t" # FundamentalContext new types "CShareholderTopResponse" = "lb_shareholder_top_response_t" "CShareholderDetailResponse" = "lb_shareholder_detail_response_t" @@ -441,6 +447,9 @@ include = [ "CShortTradesItem", "CShortTradesResponse", "COptionVolumeStats", "COptionVolumeDailyStat", "COptionVolumeDaily", + "CElementType", + "CLocaleName", "CHoldingDetail", + "CAssetAllocationItem", "CAssetAllocationGroup", "CAssetAllocationResponse", # FundamentalContext new types "CShareholderTopResponse", "CShareholderDetailResponse", "CValuationHistoryPoint", "CValuationComparisonItem", "CValuationComparisonResponse", diff --git a/c/csrc/include/longbridge.h b/c/csrc/include/longbridge.h index 81fefdb02..b298458e7 100644 --- a/c/csrc/include/longbridge.h +++ b/c/csrc/include/longbridge.h @@ -1594,6 +1594,32 @@ typedef enum lb_asset_type_t { AssetTypeCrypto, } lb_asset_type_t; +/** + * ETF asset allocation element type + */ +typedef enum lb_element_type_t { + /** + * Unknown + */ + ElementTypeUnknown, + /** + * Holdings + */ + ElementTypeHoldings, + /** + * Regional + */ + ElementTypeRegional, + /** + * Asset class + */ + ElementTypeAssetClass, + /** + * Industry + */ + ElementTypeIndustry, +} lb_element_type_t; + typedef struct lb_alert_context_t lb_alert_context_t; /** @@ -7111,7 +7137,8 @@ typedef struct lb_calendar_events_response_t { */ uintptr_t num_list; /** - * Pagination cursor; pass as start to fetch the next page, empty when there are no more pages. + * Pagination cursor; pass as start to fetch the next page, empty when + * there are no more pages. */ const char *next_date; } lb_calendar_events_response_t; @@ -8318,6 +8345,120 @@ typedef struct lb_option_volume_daily_t { uintptr_t num_stats; } lb_option_volume_daily_t; +/** + * Localized name entry (locale → name) + */ +typedef struct lb_locale_name_t { + /** + * Locale (e.g. `zh-CN`) + */ + const char *locale; + /** + * Localized name + */ + const char *name; +} lb_locale_name_t; + +/** + * Holding detail of an ETF asset allocation element (holdings only) + */ +typedef struct lb_holding_detail_t { + /** + * Industry ID + */ + const char *industry_id; + /** + * Industry name + */ + const char *industry_name; + /** + * Index counter ID (e.g. `BK/US/CP99000`) + */ + const char *index; + /** + * Index name + */ + const char *index_name; + /** + * Holding type (e.g. `E` for stock) + */ + const char *holding_type; + /** + * Holding type name + */ + const char *holding_type_name; +} lb_holding_detail_t; + +/** + * One element of an ETF asset allocation group + */ +typedef struct lb_asset_allocation_item_t { + /** + * Element name + */ + const char *name; + /** + * Security code (holdings only, e.g. `NVDA`) + */ + const char *code; + /** + * Position ratio (e.g. `0.0861114`) + */ + const char *position_ratio; + /** + * Security symbol (holdings only, e.g. `NVDA.US`) + */ + const char *symbol; + /** + * Pointer to array of localized name entries + */ + const struct lb_locale_name_t *name_locales; + /** + * Number of elements in the localized name array + */ + uintptr_t num_name_locales; + /** + * Holding detail (holdings only, maybe null) + */ + const struct lb_holding_detail_t *holding_detail; +} lb_asset_allocation_item_t; + +/** + * One ETF asset allocation group (grouped by element type) + */ +typedef struct lb_asset_allocation_group_t { + /** + * Report date (e.g. `20260601`) + */ + const char *report_date; + /** + * Element type of this group + */ + enum lb_element_type_t asset_type; + /** + * Pointer to array of elements + */ + const struct lb_asset_allocation_item_t *lists; + /** + * Number of elements in the array + */ + uintptr_t num_lists; +} lb_asset_allocation_group_t; + +/** + * ETF asset allocation response + */ +typedef struct lb_asset_allocation_response_t { + /** + * Pointer to array of asset allocation groups + */ + const struct lb_asset_allocation_group_t *info; + /** + * Number of elements in the array + */ + uintptr_t num_info; +} lb_asset_allocation_response_t; + /** * Top-shareholder list response. `data` is a NUL-terminated JSON string. */ @@ -10186,6 +10327,15 @@ void lb_quote_context_option_volume_daily(const struct lb_quote_context_t *ctx, lb_async_callback_t callback, void *userdata); +/** + * Get ETF asset allocation (holdings / regional / asset class / industry). + * Returns `CAssetAllocationResponse`. + */ +void lb_quote_context_etf_asset_allocation(const struct lb_quote_context_t *ctx, + const char *symbol, + lb_async_callback_t callback, + void *userdata); + const struct lb_screener_context_t *lb_screener_context_new(const struct lb_config_t *config); void lb_screener_context_retain(const struct lb_screener_context_t *ctx); diff --git a/c/src/quote_context/context.rs b/c/src/quote_context/context.rs index ce9feef9b..24cc31d10 100644 --- a/c/src/quote_context/context.rs +++ b/c/src/quote_context/context.rs @@ -1290,3 +1290,23 @@ pub unsafe extern "C" fn lb_quote_context_option_volume_daily( Ok(resp) }); } + +/// Get ETF asset allocation (holdings / regional / asset class / industry). +/// Returns `CAssetAllocationResponse`. +#[unsafe(no_mangle)] +pub unsafe extern "C" fn lb_quote_context_etf_asset_allocation( + ctx: *const CQuoteContext, + symbol: *const c_char, + callback: CAsyncCallback, + userdata: *mut c_void, +) { + use crate::{quote_context::types::CAssetAllocationResponseOwned, types::CCow}; + let ctx_inner = (*ctx).ctx.clone(); + let symbol = cstr_to_rust(symbol); + execute_async(callback, ctx, userdata, async move { + let resp: CCow = CCow::new( + CAssetAllocationResponseOwned::from(ctx_inner.etf_asset_allocation(symbol).await?), + ); + Ok(resp) + }); +} diff --git a/c/src/quote_context/enum_types.rs b/c/src/quote_context/enum_types.rs index 9bf17ebaa..e53a2900b 100644 --- a/c/src/quote_context/enum_types.rs +++ b/c/src/quote_context/enum_types.rs @@ -632,3 +632,26 @@ pub enum CGranularity { #[c(remote = "Monthly")] GranularityMonthly, } + +/// ETF asset allocation element type +#[derive(Debug, Copy, Clone, Eq, PartialEq, CEnum)] +#[c(remote = "longbridge::quote::ElementType")] +#[allow(clippy::enum_variant_names)] +#[repr(C)] +pub enum CElementType { + /// Unknown + #[c(remote = "Unknown")] + ElementTypeUnknown, + /// Holdings + #[c(remote = "Holdings")] + ElementTypeHoldings, + /// Regional + #[c(remote = "Regional")] + ElementTypeRegional, + /// Asset class + #[c(remote = "AssetClass")] + ElementTypeAssetClass, + /// Industry + #[c(remote = "Industry")] + ElementTypeIndustry, +} diff --git a/c/src/quote_context/types.rs b/c/src/quote_context/types.rs index 72cdaf5c8..312aeee15 100644 --- a/c/src/quote_context/types.rs +++ b/c/src/quote_context/types.rs @@ -1,11 +1,12 @@ use std::os::raw::c_char; use longbridge::quote::{ - Brokers, Candlestick, CapitalDistribution, CapitalDistributionResponse, CapitalFlowLine, Depth, - FilingItem, HistoryMarketTemperatureResponse, IntradayLine, IssuerInfo, MarketTemperature, - MarketTradingDays, MarketTradingSession, OptionDirection, OptionQuote, OptionType, - OptionVolumeDaily, OptionVolumeDailyStat, OptionVolumeStats, ParticipantInfo, Period, - PrePostQuote, PushBrokers, PushCandlestick, PushDepth, PushQuote, PushTrades, + AssetAllocationGroup, AssetAllocationItem, AssetAllocationResponse, Brokers, Candlestick, + CapitalDistribution, CapitalDistributionResponse, CapitalFlowLine, Depth, ElementType, + FilingItem, HistoryMarketTemperatureResponse, HoldingDetail, IntradayLine, IssuerInfo, + MarketTemperature, MarketTradingDays, MarketTradingSession, OptionDirection, OptionQuote, + OptionType, OptionVolumeDaily, OptionVolumeDailyStat, OptionVolumeStats, ParticipantInfo, + Period, PrePostQuote, PushBrokers, PushCandlestick, PushDepth, PushQuote, PushTrades, QuotePackageDetail, RealtimeQuote, Security, SecurityBoard, SecurityBrokers, SecurityCalcIndex, SecurityDepth, SecurityQuote, SecurityStaticInfo, ShortPositionsItem, ShortPositionsResponse, ShortTradesItem, ShortTradesResponse, StrikePriceInfo, Subscription, Trade, TradeDirection, @@ -15,7 +16,7 @@ use longbridge::quote::{ use crate::{ quote_context::enum_types::{ - CGranularity, COptionDirection, COptionType, CPeriod, CSecuritiesUpdateMode, + CElementType, CGranularity, COptionDirection, COptionType, CPeriod, CSecuritiesUpdateMode, CSecurityBoard, CTradeDirection, CTradeSession, CTradeStatus, CWarrantStatus, CWarrantType, }, types::{CDate, CDecimal, CMarket, COption, CString, CTime, CVec, ToFFI}, @@ -3442,3 +3443,221 @@ impl ToFFI for COptionVolumeDailyOwned { } } } + +// ── EtfAssetAllocation ──────────────────────────────────────────── + +/// Localized name entry (locale → name) +#[repr(C)] +pub struct CLocaleName { + /// Locale (e.g. `zh-CN`) + pub locale: *const c_char, + /// Localized name + pub name: *const c_char, +} + +pub(crate) struct CLocaleNameOwned { + locale: CString, + name: CString, +} + +impl From<(String, String)> for CLocaleNameOwned { + fn from((locale, name): (String, String)) -> Self { + Self { + locale: locale.into(), + name: name.into(), + } + } +} + +impl ToFFI for CLocaleNameOwned { + type FFIType = CLocaleName; + fn to_ffi_type(&self) -> Self::FFIType { + CLocaleName { + locale: self.locale.to_ffi_type(), + name: self.name.to_ffi_type(), + } + } +} + +/// Holding detail of an ETF asset allocation element (holdings only) +#[repr(C)] +pub struct CHoldingDetail { + /// Industry ID + pub industry_id: *const c_char, + /// Industry name + pub industry_name: *const c_char, + /// Index counter ID (e.g. `BK/US/CP99000`) + pub index: *const c_char, + /// Index name + pub index_name: *const c_char, + /// Holding type (e.g. `E` for stock) + pub holding_type: *const c_char, + /// Holding type name + pub holding_type_name: *const c_char, +} + +pub(crate) struct CHoldingDetailOwned { + industry_id: CString, + industry_name: CString, + index: CString, + index_name: CString, + holding_type: CString, + holding_type_name: CString, +} + +impl From for CHoldingDetailOwned { + fn from(v: HoldingDetail) -> Self { + Self { + industry_id: v.industry_id.into(), + industry_name: v.industry_name.into(), + index: v.index.into(), + index_name: v.index_name.into(), + holding_type: v.holding_type.into(), + holding_type_name: v.holding_type_name.into(), + } + } +} + +impl ToFFI for CHoldingDetailOwned { + type FFIType = CHoldingDetail; + fn to_ffi_type(&self) -> Self::FFIType { + CHoldingDetail { + industry_id: self.industry_id.to_ffi_type(), + industry_name: self.industry_name.to_ffi_type(), + index: self.index.to_ffi_type(), + index_name: self.index_name.to_ffi_type(), + holding_type: self.holding_type.to_ffi_type(), + holding_type_name: self.holding_type_name.to_ffi_type(), + } + } +} + +/// One element of an ETF asset allocation group +#[repr(C)] +pub struct CAssetAllocationItem { + /// Element name + pub name: *const c_char, + /// Security code (holdings only, e.g. `NVDA`) + pub code: *const c_char, + /// Position ratio (e.g. `0.0861114`) + pub position_ratio: *const c_char, + /// Security symbol (holdings only, e.g. `NVDA.US`) + pub symbol: *const c_char, + /// Pointer to array of localized name entries + pub name_locales: *const CLocaleName, + /// Number of elements in the localized name array + pub num_name_locales: usize, + /// Holding detail (holdings only, maybe null) + pub holding_detail: *const CHoldingDetail, +} + +pub(crate) struct CAssetAllocationItemOwned { + name: CString, + code: CString, + position_ratio: CString, + symbol: CString, + name_locales: CVec, + holding_detail: COption, +} + +impl From for CAssetAllocationItemOwned { + fn from(v: AssetAllocationItem) -> Self { + let mut name_locales = v.name_locales.into_iter().collect::>(); + name_locales.sort(); + Self { + name: v.name.into(), + code: v.code.into(), + position_ratio: v.position_ratio.into(), + symbol: v.symbol.into(), + name_locales: name_locales.into(), + holding_detail: v.holding_detail.into(), + } + } +} + +impl ToFFI for CAssetAllocationItemOwned { + type FFIType = CAssetAllocationItem; + fn to_ffi_type(&self) -> Self::FFIType { + CAssetAllocationItem { + name: self.name.to_ffi_type(), + code: self.code.to_ffi_type(), + position_ratio: self.position_ratio.to_ffi_type(), + symbol: self.symbol.to_ffi_type(), + name_locales: self.name_locales.to_ffi_type(), + num_name_locales: self.name_locales.len(), + holding_detail: self.holding_detail.to_ffi_type(), + } + } +} + +/// One ETF asset allocation group (grouped by element type) +#[repr(C)] +pub struct CAssetAllocationGroup { + /// Report date (e.g. `20260601`) + pub report_date: *const c_char, + /// Element type of this group + pub asset_type: CElementType, + /// Pointer to array of elements + pub lists: *const CAssetAllocationItem, + /// Number of elements in the array + pub num_lists: usize, +} + +pub(crate) struct CAssetAllocationGroupOwned { + report_date: CString, + asset_type: ElementType, + lists: CVec, +} + +impl From for CAssetAllocationGroupOwned { + fn from(v: AssetAllocationGroup) -> Self { + Self { + report_date: v.report_date.into(), + asset_type: v.asset_type, + lists: v.lists.into(), + } + } +} + +impl ToFFI for CAssetAllocationGroupOwned { + type FFIType = CAssetAllocationGroup; + fn to_ffi_type(&self) -> Self::FFIType { + CAssetAllocationGroup { + report_date: self.report_date.to_ffi_type(), + asset_type: self.asset_type.into(), + lists: self.lists.to_ffi_type(), + num_lists: self.lists.len(), + } + } +} + +/// ETF asset allocation response +#[repr(C)] +pub struct CAssetAllocationResponse { + /// Pointer to array of asset allocation groups + pub info: *const CAssetAllocationGroup, + /// Number of elements in the array + pub num_info: usize, +} + +pub(crate) struct CAssetAllocationResponseOwned { + info: CVec, +} + +impl From for CAssetAllocationResponseOwned { + fn from(v: AssetAllocationResponse) -> Self { + Self { + info: v.info.into(), + } + } +} + +impl ToFFI for CAssetAllocationResponseOwned { + type FFIType = CAssetAllocationResponse; + fn to_ffi_type(&self) -> Self::FFIType { + CAssetAllocationResponse { + info: self.info.to_ffi_type(), + num_info: self.info.len(), + } + } +} diff --git a/cpp/include/quote_context.hpp b/cpp/include/quote_context.hpp index 01644f332..5f5a98fe7 100644 --- a/cpp/include/quote_context.hpp +++ b/cpp/include/quote_context.hpp @@ -333,6 +333,11 @@ class QuoteContext int64_t timestamp, uint32_t count, AsyncCallback callback) const; + + /// Get ETF asset allocation (holdings / regional / asset class / industry) + void etf_asset_allocation( + const std::string& symbol, + AsyncCallback callback) const; }; } // namespace quote diff --git a/cpp/include/types.hpp b/cpp/include/types.hpp index 0ba445c9a..94684d5ae 100644 --- a/cpp/include/types.hpp +++ b/cpp/include/types.hpp @@ -1,6 +1,7 @@ #pragma once #include "decimal.hpp" +#include #include #include @@ -1346,6 +1347,73 @@ struct OptionVolumeDaily std::vector stats; }; +/// ETF asset allocation element type +enum class ElementType +{ + /// Unknown + Unknown, + /// Holdings + Holdings, + /// Regional + Regional, + /// Asset class + AssetClass, + /// Industry + Industry, +}; + +/// Holding detail of an ETF asset allocation element (holdings only) +struct HoldingDetail +{ + /// Industry ID + std::string industry_id; + /// Industry name + std::string industry_name; + /// Index counter ID (e.g. `BK/US/CP99000`) + std::string index; + /// Index name + std::string index_name; + /// Holding type (e.g. `E` for stock) + std::string holding_type; + /// Holding type name + std::string holding_type_name; +}; + +/// One element of an ETF asset allocation group +struct AssetAllocationItem +{ + /// Element name + std::string name; + /// Security code (holdings only, e.g. `NVDA`) + std::string code; + /// Position ratio (e.g. `0.0861114`) + std::string position_ratio; + /// Security symbol (holdings only, e.g. `NVDA.US`) + std::string symbol; + /// Localized names (locale → name) + std::map name_locales; + /// Holding detail (holdings only) + std::optional holding_detail; +}; + +/// One ETF asset allocation group (grouped by element type) +struct AssetAllocationGroup +{ + /// Report date (e.g. `20260601`) + std::string report_date; + /// Element type of this group + ElementType asset_type; + /// Elements + std::vector lists; +}; + +/// ETF asset allocation response +struct AssetAllocationResponse +{ + /// Asset allocation groups + std::vector info; +}; + } // namespace quote namespace trade { diff --git a/cpp/src/convert.hpp b/cpp/src/convert.hpp index 287bea0cb..78a5f1beb 100644 --- a/cpp/src/convert.hpp +++ b/cpp/src/convert.hpp @@ -2335,6 +2335,54 @@ inline quote::OptionVolumeDaily convert(const lb_option_volume_daily_t* r) { for (size_t i = 0; i < r->num_stats; ++i) stats.push_back(convert(&r->stats[i])); return { std::move(stats) }; } +inline quote::ElementType convert(lb_element_type_t ty) { + switch (ty) { + case ElementTypeUnknown: + return quote::ElementType::Unknown; + case ElementTypeHoldings: + return quote::ElementType::Holdings; + case ElementTypeRegional: + return quote::ElementType::Regional; + case ElementTypeAssetClass: + return quote::ElementType::AssetClass; + case ElementTypeIndustry: + return quote::ElementType::Industry; + default: + throw std::invalid_argument("unreachable"); + } +} +inline quote::HoldingDetail convert(const lb_holding_detail_t* d) { + return { d->industry_id ? d->industry_id : "", + d->industry_name ? d->industry_name : "", + d->index ? d->index : "", + d->index_name ? d->index_name : "", + d->holding_type ? d->holding_type : "", + d->holding_type_name ? d->holding_type_name : "" }; +} +inline quote::AssetAllocationItem convert(const lb_asset_allocation_item_t* item) { + std::map name_locales; + for (size_t i = 0; i < item->num_name_locales; ++i) { + const auto& entry = item->name_locales[i]; + name_locales.emplace(entry.locale ? entry.locale : "", entry.name ? entry.name : ""); + } + return { item->name ? item->name : "", + item->code ? item->code : "", + item->position_ratio ? item->position_ratio : "", + item->symbol ? item->symbol : "", + std::move(name_locales), + item->holding_detail ? std::make_optional(convert(item->holding_detail)) + : std::nullopt }; +} +inline quote::AssetAllocationGroup convert(const lb_asset_allocation_group_t* g) { + std::vector lists; + for (size_t i = 0; i < g->num_lists; ++i) lists.push_back(convert(&g->lists[i])); + return { g->report_date ? g->report_date : "", convert(g->asset_type), std::move(lists) }; +} +inline quote::AssetAllocationResponse convert(const lb_asset_allocation_response_t* r) { + std::vector info; + for (size_t i = 0; i < r->num_info; ++i) info.push_back(convert(&r->info[i])); + return { std::move(info) }; +} // ── MarketContext conversions ───────────────────────────────────── diff --git a/cpp/src/quote_context.cpp b/cpp/src/quote_context.cpp index ab5e4f2b5..2f0d05417 100644 --- a/cpp/src/quote_context.cpp +++ b/cpp/src/quote_context.cpp @@ -1759,5 +1759,30 @@ QuoteContext::option_volume_daily(const std::string& symbol, new AsyncCallback(callback)); } +void +QuoteContext::etf_asset_allocation( + const std::string& symbol, + AsyncCallback callback) const +{ + lb_quote_context_etf_asset_allocation( + ctx_, + symbol.c_str(), + [](auto res) { + auto callback_ptr = + callback::get_async_callback(res->userdata); + QuoteContext ctx((const lb_quote_context_t*)res->ctx); + Status status(res->error); + if (status) { + auto value = convert::convert((const lb_asset_allocation_response_t*)res->data); + (*callback_ptr)( + AsyncResult(ctx, std::move(status), &value)); + } else { + (*callback_ptr)( + AsyncResult(ctx, std::move(status), nullptr)); + } + }, + new AsyncCallback(callback)); +} + } // namespace quote } // namespace longbridge \ No newline at end of file diff --git a/nodejs/index.d.ts b/nodejs/index.d.ts index 5de5f15f7..55217b341 100644 --- a/nodejs/index.d.ts +++ b/nodejs/index.d.ts @@ -2021,6 +2021,11 @@ export declare class QuoteContext { optionVolume(symbol: string): Promise /** Get daily historical option volume */ optionVolumeDaily(symbol: string, timestamp: number, count: number): Promise + /** + * Get ETF asset allocation (holdings / regional / asset class / + * industry) + */ + etfAssetAllocation(symbol: string): Promise } export declare class QuotePackageDetail { @@ -3097,6 +3102,38 @@ export interface AnomalyResponse { changes: Array } +/** One ETF asset allocation group (grouped by element type) */ +export interface AssetAllocationGroup { + /** Report date (e.g. `20260601`) */ + reportDate: string + /** Element type of this group */ + assetType: ElementType + /** Elements */ + lists: Array +} + +/** One element of an ETF asset allocation group */ +export interface AssetAllocationItem { + /** Element name */ + name: string + /** Security code (holdings only, e.g. `NVDA`) */ + code: string + /** Position ratio (e.g. `0.0861114`) */ + positionRatio: string + /** Security symbol (holdings only, e.g. `NVDA.US`) */ + symbol: string + /** Localized names (locale → name) */ + nameLocales: Record + /** Holding detail (holdings only) */ + holdingDetail?: HoldingDetail +} + +/** ETF asset allocation response */ +export interface AssetAllocationResponse { + /** Asset allocation groups */ + info: Array +} + export declare const enum AssetType { /** Unknown */ Unknown = 0, @@ -3397,8 +3434,6 @@ export interface CalendarEventsResponse { date: string /** Per-day event groups */ list: Array - /** Pagination cursor; pass as start to fetch the next page, empty when there are no more pages */ - nextDate: string } export declare const enum CashFlowDirection { @@ -3844,6 +3879,20 @@ export interface DividendList { list: Array } +/** ETF asset allocation element type */ +export declare const enum ElementType { + /** Unknown */ + Unknown = 0, + /** Holdings */ + Holdings = 1, + /** Regional */ + Regional = 2, + /** Asset class */ + AssetClass = 3, + /** Industry */ + Industry = 4 +} + /** Options for get cash flow request */ export interface EstimateMaxPurchaseQuantityOptions { symbol: string @@ -4174,6 +4223,22 @@ export declare const enum Granularity { Monthly = 3 } +/** Holding detail of an ETF asset allocation element (holdings only) */ +export interface HoldingDetail { + /** Industry ID */ + industryId: string + /** Industry name */ + industryName: string + /** Index counter ID (e.g. `BK/US/CP99000`) */ + index: string + /** Index name */ + indexName: string + /** Holding type (e.g. `E` for stock) */ + holdingType: string + /** Holding type name */ + holdingTypeName: string +} + /** Index constituents response */ export interface IndexConstituents { /** Number of constituent stocks that fell today */ diff --git a/nodejs/index.js b/nodejs/index.js index e13776cb4..a8cb5ec7a 100644 --- a/nodejs/index.js +++ b/nodejs/index.js @@ -680,6 +680,7 @@ module.exports.DCAFrequency = nativeBinding.DCAFrequency module.exports.DCAStatus = nativeBinding.DCAStatus module.exports.DeductionStatus = nativeBinding.DeductionStatus module.exports.DerivativeType = nativeBinding.DerivativeType +module.exports.ElementType = nativeBinding.ElementType module.exports.FilterWarrantExpiryDate = nativeBinding.FilterWarrantExpiryDate module.exports.FilterWarrantInOutBoundsType = nativeBinding.FilterWarrantInOutBoundsType module.exports.FinancialReportKind = nativeBinding.FinancialReportKind diff --git a/nodejs/src/quote/context.rs b/nodejs/src/quote/context.rs index 4ee04a1e2..7ede12509 100644 --- a/nodejs/src/quote/context.rs +++ b/nodejs/src/quote/context.rs @@ -13,16 +13,16 @@ use crate::{ }, requests::{CreateWatchlistGroup, DeleteWatchlistGroup, UpdateWatchlistGroup}, types::{ - AdjustType, CalcIndex, Candlestick, CapitalDistributionResponse, CapitalFlowLine, - FilingItem, FilterWarrantExpiryDate, FilterWarrantInOutBoundsType, - HistoryMarketTemperatureResponse, IntradayLine, IssuerInfo, MarketTemperature, - MarketTradingDays, MarketTradingSession, OptionQuote, OptionVolumeDaily, - OptionVolumeStats, ParticipantInfo, Period, PinnedMode, QuotePackageDetail, - RealtimeQuote, Security, SecurityBrokers, SecurityCalcIndex, SecurityDepth, - SecurityListCategory, SecurityQuote, SecurityStaticInfo, ShortPositionsResponse, - ShortTradesResponse, SortOrderType, StrikePriceInfo, SubType, SubTypes, Subscription, - Trade, TradeSessions, WarrantInfo, WarrantQuote, WarrantSortBy, WarrantStatus, - WarrantType, WatchlistGroup, + AdjustType, AssetAllocationResponse, CalcIndex, Candlestick, + CapitalDistributionResponse, CapitalFlowLine, FilingItem, FilterWarrantExpiryDate, + FilterWarrantInOutBoundsType, HistoryMarketTemperatureResponse, IntradayLine, + IssuerInfo, MarketTemperature, MarketTradingDays, MarketTradingSession, OptionQuote, + OptionVolumeDaily, OptionVolumeStats, ParticipantInfo, Period, PinnedMode, + QuotePackageDetail, RealtimeQuote, Security, SecurityBrokers, SecurityCalcIndex, + SecurityDepth, SecurityListCategory, SecurityQuote, SecurityStaticInfo, + ShortPositionsResponse, ShortTradesResponse, SortOrderType, StrikePriceInfo, SubType, + SubTypes, Subscription, Trade, TradeSessions, WarrantInfo, WarrantQuote, WarrantSortBy, + WarrantStatus, WarrantType, WatchlistGroup, }, }, time::{NaiveDate, NaiveDatetime}, @@ -1290,4 +1290,16 @@ impl QuoteContext { .map_err(ErrorNewType)? .into()) } + + /// Get ETF asset allocation (holdings / regional / asset class / + /// industry) + #[napi] + pub async fn etf_asset_allocation(&self, symbol: String) -> Result { + Ok(self + .ctx + .etf_asset_allocation(symbol) + .await + .map_err(ErrorNewType)? + .into()) + } } diff --git a/nodejs/src/quote/types.rs b/nodejs/src/quote/types.rs index acd0cfdd4..86379fa62 100644 --- a/nodejs/src/quote/types.rs +++ b/nodejs/src/quote/types.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use chrono::{DateTime, Utc}; use longbridge::quote::SubFlags; use longbridge_nodejs_macros::{JsEnum, JsObject}; @@ -1663,3 +1665,122 @@ impl From for OptionVolumeDailyStat { } } } + +// ── etf_asset_allocation ────────────────────────────────────────── + +/// ETF asset allocation element type +#[napi_derive::napi] +#[derive(JsEnum, Debug, Hash, Eq, PartialEq, Copy, Clone)] +#[js(remote = "longbridge::quote::ElementType")] +pub enum ElementType { + /// Unknown + Unknown, + /// Holdings + Holdings, + /// Regional + Regional, + /// Asset class + AssetClass, + /// Industry + Industry, +} + +/// Holding detail of an ETF asset allocation element (holdings only) +#[napi_derive::napi(object)] +#[derive(Debug, Clone)] +pub struct HoldingDetail { + /// Industry ID + pub industry_id: String, + /// Industry name + pub industry_name: String, + /// Index counter ID (e.g. `BK/US/CP99000`) + pub index: String, + /// Index name + pub index_name: String, + /// Holding type (e.g. `E` for stock) + pub holding_type: String, + /// Holding type name + pub holding_type_name: String, +} + +impl From for HoldingDetail { + fn from(v: longbridge::quote::HoldingDetail) -> Self { + Self { + industry_id: v.industry_id, + industry_name: v.industry_name, + index: v.index, + index_name: v.index_name, + holding_type: v.holding_type, + holding_type_name: v.holding_type_name, + } + } +} + +/// One element of an ETF asset allocation group +#[napi_derive::napi(object)] +#[derive(Debug, Clone)] +pub struct AssetAllocationItem { + /// Element name + pub name: String, + /// Security code (holdings only, e.g. `NVDA`) + pub code: String, + /// Position ratio (e.g. `0.0861114`) + pub position_ratio: String, + /// Security symbol (holdings only, e.g. `NVDA.US`) + pub symbol: String, + /// Localized names (locale → name) + pub name_locales: HashMap, + /// Holding detail (holdings only) + pub holding_detail: Option, +} + +impl From for AssetAllocationItem { + fn from(v: longbridge::quote::AssetAllocationItem) -> Self { + Self { + name: v.name, + code: v.code, + position_ratio: v.position_ratio, + symbol: v.symbol, + name_locales: v.name_locales, + holding_detail: v.holding_detail.map(Into::into), + } + } +} + +/// One ETF asset allocation group (grouped by element type) +#[napi_derive::napi(object)] +#[derive(Debug, Clone)] +pub struct AssetAllocationGroup { + /// Report date (e.g. `20260601`) + pub report_date: String, + /// Element type of this group + pub asset_type: ElementType, + /// Elements + pub lists: Vec, +} + +impl From for AssetAllocationGroup { + fn from(v: longbridge::quote::AssetAllocationGroup) -> Self { + Self { + report_date: v.report_date, + asset_type: v.asset_type.into(), + lists: v.lists.into_iter().map(Into::into).collect(), + } + } +} + +/// ETF asset allocation response +#[napi_derive::napi(object)] +#[derive(Debug, Clone)] +pub struct AssetAllocationResponse { + /// Asset allocation groups + pub info: Vec, +} + +impl From for AssetAllocationResponse { + fn from(v: longbridge::quote::AssetAllocationResponse) -> Self { + Self { + info: v.info.into_iter().map(Into::into).collect(), + } + } +} diff --git a/python/pysrc/longbridge/openapi.pyi b/python/pysrc/longbridge/openapi.pyi index 5641e2bf9..3590f5d30 100644 --- a/python/pysrc/longbridge/openapi.pyi +++ b/python/pysrc/longbridge/openapi.pyi @@ -4020,6 +4020,17 @@ class QuoteContext: :class:`ShortTradesResponse` with raw JSON data """ + def etf_asset_allocation(self, symbol: str) -> AssetAllocationResponse: + """ + Get ETF asset allocation (holdings / regional / asset class / industry). + + Args: + symbol: ETF security code (e.g. ``"QQQ.US"``) + + Returns: + :class:`AssetAllocationResponse` with allocation groups + """ + class AsyncQuoteContext: """ Async quote context for use with asyncio. Create via `AsyncQuoteContext.create(config)` and await inside asyncio. @@ -5372,6 +5383,21 @@ class AsyncQuoteContext: """ ... + def etf_asset_allocation( + self, symbol: str + ) -> Awaitable[AssetAllocationResponse]: + """ + Get ETF asset allocation (holdings / regional / asset class / industry). + Returns awaitable. + + Args: + symbol: ETF security code (e.g. ``"QQQ.US"``) + + Returns: + Awaitable resolving to :class:`AssetAllocationResponse` + """ + ... + class OrderSide: """ Order side @@ -11937,3 +11963,74 @@ class OptionVolumeDaily: stats: list[OptionVolumeDailyStat] """Daily option volume statistics""" + + +class ElementType: + """ETF asset allocation element type.""" + + class Unknown(ElementType): + """Unknown""" + + class Holdings(ElementType): + """Holdings""" + + class Regional(ElementType): + """Regional""" + + class AssetClass(ElementType): + """Asset class""" + + class Industry(ElementType): + """Industry""" + + +class HoldingDetail: + """Holding detail of an ETF asset allocation element (holdings only).""" + + industry_id: str + """Industry ID""" + industry_name: str + """Industry name""" + index: str + """Index counter ID (e.g. ``BK/US/CP99000``)""" + index_name: str + """Index name""" + holding_type: str + """Holding type (e.g. ``E`` for stock)""" + holding_type_name: str + """Holding type name""" + + +class AssetAllocationItem: + """One element of an ETF asset allocation group.""" + + name: str + """Element name""" + code: str + """Security code (holdings only, e.g. ``NVDA``)""" + position_ratio: str + """Position ratio (e.g. ``0.0861114``)""" + symbol: str + """Security symbol (holdings only, e.g. ``NVDA.US``)""" + name_locales: dict[str, str] + """Localized names (locale → name)""" + holding_detail: Optional[HoldingDetail] + """Holding detail (holdings only)""" + + +class AssetAllocationGroup: + """One ETF asset allocation group (grouped by element type).""" + + report_date: str + """Report date (e.g. ``20260601``)""" + asset_type: Type[ElementType] + """Element type of this group""" + lists: list[AssetAllocationItem] + """Elements""" + + +class AssetAllocationResponse: + """ETF asset allocation response.""" + + info: list[AssetAllocationGroup] + """Asset allocation groups""" diff --git a/python/src/quote/context.rs b/python/src/quote/context.rs index a2d6f9e1e..2357ebe78 100644 --- a/python/src/quote/context.rs +++ b/python/src/quote/context.rs @@ -687,4 +687,17 @@ impl QuoteContext { .map_err(ErrorNewType)? .into()) } + + /// Get ETF asset allocation (holdings / regional / asset class / + /// industry) + fn etf_asset_allocation( + &self, + symbol: String, + ) -> PyResult { + Ok(self + .ctx + .etf_asset_allocation(symbol) + .map_err(ErrorNewType)? + .into()) + } } diff --git a/python/src/quote/context_async.rs b/python/src/quote/context_async.rs index cd5ca44c9..f3637e282 100644 --- a/python/src/quote/context_async.rs +++ b/python/src/quote/context_async.rs @@ -895,4 +895,19 @@ impl AsyncQuoteContext { }) .map(|b| b.unbind()) } + + /// Get ETF asset allocation (holdings / regional / asset class / + /// industry). Returns awaitable. + fn etf_asset_allocation(&self, py: Python<'_>, symbol: String) -> PyResult> { + let ctx = self.ctx.clone(); + pyo3_async_runtimes::tokio::future_into_py(py, async move { + let r: crate::quote::types::AssetAllocationResponse = ctx + .etf_asset_allocation(symbol) + .await + .map_err(ErrorNewType)? + .into(); + Ok(r) + }) + .map(|b| b.unbind()) + } } diff --git a/python/src/quote/mod.rs b/python/src/quote/mod.rs index 749f0deb0..d69458841 100644 --- a/python/src/quote/mod.rs +++ b/python/src/quote/mod.rs @@ -71,6 +71,11 @@ pub(crate) fn register_types(parent: &Bound) -> PyResult<()> { parent.add_class::()?; parent.add_class::()?; parent.add_class::()?; + parent.add_class::()?; + parent.add_class::()?; + parent.add_class::()?; + parent.add_class::()?; + parent.add_class::()?; parent.add_class::()?; parent.add_class::()?; diff --git a/python/src/quote/types.rs b/python/src/quote/types.rs index d9849dac0..aeb7a5339 100644 --- a/python/src/quote/types.rs +++ b/python/src/quote/types.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use longbridge::quote::SubFlags; use longbridge_python_macros::{PyEnum, PyObject}; use pyo3::prelude::*; @@ -1621,3 +1623,122 @@ impl From for OptionVolumeDailyStat { } } } + +// ── etf_asset_allocation ────────────────────────────────────────── + +/// ETF asset allocation element type +#[pyclass(eq, eq_int, skip_from_py_object)] +#[derive(PyEnum, Debug, Copy, Clone, Hash, Eq, PartialEq)] +#[py(remote = "longbridge::quote::ElementType")] +pub(crate) enum ElementType { + /// Unknown + Unknown, + /// Holdings + Holdings, + /// Regional + Regional, + /// Asset class + AssetClass, + /// Industry + Industry, +} + +/// Holding detail of an ETF asset allocation element (holdings only) +#[pyclass(get_all, skip_from_py_object)] +#[derive(Debug, Clone)] +pub(crate) struct HoldingDetail { + /// Industry ID + pub industry_id: String, + /// Industry name + pub industry_name: String, + /// Index counter ID (e.g. `BK/US/CP99000`) + pub index: String, + /// Index name + pub index_name: String, + /// Holding type (e.g. `E` for stock) + pub holding_type: String, + /// Holding type name + pub holding_type_name: String, +} + +impl From for HoldingDetail { + fn from(v: longbridge::quote::HoldingDetail) -> Self { + Self { + industry_id: v.industry_id, + industry_name: v.industry_name, + index: v.index, + index_name: v.index_name, + holding_type: v.holding_type, + holding_type_name: v.holding_type_name, + } + } +} + +/// One element of an ETF asset allocation group +#[pyclass(get_all, skip_from_py_object)] +#[derive(Debug, Clone)] +pub(crate) struct AssetAllocationItem { + /// Element name + pub name: String, + /// Security code (holdings only, e.g. `NVDA`) + pub code: String, + /// Position ratio (e.g. `0.0861114`) + pub position_ratio: String, + /// Security symbol (holdings only, e.g. `NVDA.US`) + pub symbol: String, + /// Localized names (locale → name) + pub name_locales: HashMap, + /// Holding detail (holdings only) + pub holding_detail: Option, +} + +impl From for AssetAllocationItem { + fn from(v: longbridge::quote::AssetAllocationItem) -> Self { + Self { + name: v.name, + code: v.code, + position_ratio: v.position_ratio, + symbol: v.symbol, + name_locales: v.name_locales, + holding_detail: v.holding_detail.map(Into::into), + } + } +} + +/// One ETF asset allocation group (grouped by element type) +#[pyclass(get_all, skip_from_py_object)] +#[derive(Debug, Clone)] +pub(crate) struct AssetAllocationGroup { + /// Report date (e.g. `20260601`) + pub report_date: String, + /// Element type of this group + pub asset_type: ElementType, + /// Elements + pub lists: Vec, +} + +impl From for AssetAllocationGroup { + fn from(v: longbridge::quote::AssetAllocationGroup) -> Self { + Self { + report_date: v.report_date, + asset_type: v.asset_type.into(), + lists: v.lists.into_iter().map(Into::into).collect(), + } + } +} + +/// ETF asset allocation response +#[pyclass(get_all, skip_from_py_object)] +#[derive(Debug, Clone)] +pub(crate) struct AssetAllocationResponse { + /// Asset allocation groups + pub info: Vec, +} + +impl From for AssetAllocationResponse { + fn from(v: longbridge::quote::AssetAllocationResponse) -> Self { + Self { + info: v.info.into_iter().map(Into::into).collect(), + } + } +} diff --git a/rust/src/blocking/quote.rs b/rust/src/blocking/quote.rs index fbba09273..ba47fe6ab 100644 --- a/rust/src/blocking/quote.rs +++ b/rust/src/blocking/quote.rs @@ -6,8 +6,8 @@ use crate::{ Config, Market, QuoteContext, Result, blocking::runtime::BlockingRuntime, quote::{ - AdjustType, CalcIndex, Candlestick, CapitalDistributionResponse, CapitalFlowLine, - FilingItem, FilterWarrantExpiryDate, FilterWarrantInOutBoundsType, + AdjustType, AssetAllocationResponse, CalcIndex, Candlestick, CapitalDistributionResponse, + CapitalFlowLine, FilingItem, FilterWarrantExpiryDate, FilterWarrantInOutBoundsType, HistoryMarketTemperatureResponse, IntradayLine, IssuerInfo, MarketTemperature, MarketTradingDays, MarketTradingSession, OptionQuote, OptionVolumeDaily, OptionVolumeStats, ParticipantInfo, Period, PinnedMode, PushEvent, QuotePackageDetail, RealtimeQuote, @@ -1213,4 +1213,14 @@ impl QuoteContextSync { self.rt .call(move |ctx| async move { ctx.short_trades(symbol, count).await }) } + + /// Get ETF asset allocation (holdings / regional / asset class / + /// industry) + pub fn etf_asset_allocation( + &self, + symbol: impl Into + Send + 'static, + ) -> Result { + self.rt + .call(move |ctx| async move { ctx.etf_asset_allocation(symbol).await }) + } } diff --git a/rust/src/quote/context.rs b/rust/src/quote/context.rs index 168525c95..916a41a7e 100644 --- a/rust/src/quote/context.rs +++ b/rust/src/quote/context.rs @@ -14,10 +14,10 @@ use tracing::{Subscriber, dispatcher, instrument::WithSubscriber}; use crate::{ Config, Error, Language, Market, Result, quote::{ - AdjustType, CalcIndex, Candlestick, CapitalDistributionResponse, CapitalFlowLine, - FilingItem, HistoryMarketTemperatureResponse, IntradayLine, IssuerInfo, MarketTemperature, - MarketTradingDays, MarketTradingSession, OptionQuote, OptionVolumeDaily, OptionVolumeStats, - ParticipantInfo, Period, PushEvent, QuotePackageDetail, RealtimeQuote, + AdjustType, AssetAllocationResponse, CalcIndex, Candlestick, CapitalDistributionResponse, + CapitalFlowLine, FilingItem, HistoryMarketTemperatureResponse, IntradayLine, IssuerInfo, + MarketTemperature, MarketTradingDays, MarketTradingSession, OptionQuote, OptionVolumeDaily, + OptionVolumeStats, ParticipantInfo, Period, PushEvent, QuotePackageDetail, RealtimeQuote, RequestCreateWatchlistGroup, RequestUpdateWatchlistGroup, Security, SecurityBrokers, SecurityCalcIndex, SecurityDepth, SecurityListCategory, SecurityQuote, SecurityStaticInfo, ShortPositionsItem, ShortPositionsResponse, ShortTradesItem, ShortTradesResponse, @@ -2198,6 +2198,35 @@ impl QuoteContext { Ok(()) } + + // ── etf_asset_allocation ────────────────────────────────────── + + /// Get ETF asset allocation (holdings / regional / asset class / + /// industry). + /// + /// Path: `GET /v1/quote/etf-asset-allocation` + pub async fn etf_asset_allocation( + &self, + symbol: impl Into, + ) -> Result { + use crate::utils::counter::symbol_to_counter_id; + #[derive(serde::Serialize)] + struct Query { + counter_id: String, + } + let resp = self + .0 + .http_cli + .request(Method::GET, "/v1/quote/etf-asset-allocation") + .query_params(Query { + counter_id: symbol_to_counter_id(&symbol.into()), + }) + .response::>() + .send() + .with_subscriber(self.0.log_subscriber.clone()) + .await?; + Ok(resp.0) + } } fn normalize_symbol(symbol: &str) -> &str { diff --git a/rust/src/quote/mod.rs b/rust/src/quote/mod.rs index 78dcba0cb..6f91193fc 100644 --- a/rust/src/quote/mod.rs +++ b/rust/src/quote/mod.rs @@ -17,6 +17,9 @@ pub use push_types::{ }; pub use sub_flags::SubFlags; pub use types::{ + AssetAllocationGroup, + AssetAllocationItem, + AssetAllocationResponse, Brokers, CalcIndex, Candlestick, @@ -25,11 +28,13 @@ pub use types::{ CapitalFlowLine, Depth, DerivativeType, + ElementType, FilingItem, FilterWarrantExpiryDate, FilterWarrantInOutBoundsType, Granularity, HistoryMarketTemperatureResponse, + HoldingDetail, IntradayLine, IssuerInfo, MarketTemperature, diff --git a/rust/src/quote/types.rs b/rust/src/quote/types.rs index 08df9b007..3407b1a62 100644 --- a/rust/src/quote/types.rs +++ b/rust/src/quote/types.rs @@ -1,3 +1,5 @@ +use std::collections::HashMap; + use longbridge_candlesticks::CandlestickComponents; use longbridge_proto::quote::{self, Period, TradeStatus}; use num_enum::{FromPrimitive, IntoPrimitive, TryFromPrimitive}; @@ -2164,6 +2166,111 @@ pub enum PinnedMode { Remove, } +// ── etf_asset_allocation ────────────────────────────────────────── + +/// ETF asset allocation element type +#[derive(Debug, FromPrimitive, IntoPrimitive, Copy, Clone, Hash, Eq, PartialEq)] +#[repr(i32)] +pub enum ElementType { + /// Unknown + #[num_enum(default)] + Unknown = 0, + /// Holdings + Holdings = 1, + /// Regional + Regional = 2, + /// Asset class + AssetClass = 3, + /// Industry + Industry = 4, +} + +impl Serialize for ElementType { + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + serializer.serialize_i32((*self).into()) + } +} + +impl<'de> Deserialize<'de> for ElementType { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + Ok(ElementType::from(i32::deserialize(deserializer)?)) + } +} + +/// Holding detail of an ETF asset allocation element (holdings only) +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct HoldingDetail { + /// Industry ID + #[serde(default)] + pub industry_id: String, + /// Industry name + #[serde(default)] + pub industry_name: String, + /// Index counter ID (e.g. `BK/US/CP99000`) + #[serde(default)] + pub index: String, + /// Index name + #[serde(default)] + pub index_name: String, + /// Holding type (e.g. `E` for stock) + #[serde(default)] + pub holding_type: String, + /// Holding type name + #[serde(default)] + pub holding_type_name: String, +} + +/// One element of an ETF asset allocation group +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct AssetAllocationItem { + /// Element name + pub name: String, + /// Security code (holdings only, e.g. `NVDA`) + #[serde(default)] + pub code: String, + /// Position ratio (e.g. `0.0861114`) + pub position_ratio: String, + /// Security symbol (holdings only, e.g. `NVDA.US`) + #[serde( + rename = "counter_id", + deserialize_with = "crate::utils::counter::deserialize_counter_id_as_symbol", + default + )] + pub symbol: String, + /// Localized names (locale → name, e.g. `zh-CN` → `英伟达`) + #[serde(rename = "name_locales_map", default)] + pub name_locales: HashMap, + /// Holding detail (holdings only) + #[serde(default)] + pub holding_detail: Option, +} + +/// One ETF asset allocation group (grouped by element type) +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct AssetAllocationGroup { + /// Report date (e.g. `20260601`) + pub report_date: String, + /// Element type of this group + pub asset_type: ElementType, + /// Elements + #[serde(default)] + pub lists: Vec, +} + +/// Response for [`crate::QuoteContext::etf_asset_allocation`] +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct AssetAllocationResponse { + /// Asset allocation groups + #[serde(default)] + pub info: Vec, +} + #[cfg(test)] mod tests { use serde::Deserialize; From 4f055f23d5bd75dfa7d20699289411591dea9ce8 Mon Sep 17 00:00:00 2001 From: Jason Lee Date: Thu, 4 Jun 2026 11:47:42 +0800 Subject: [PATCH 18/26] refactor(fundamental): move etf_asset_allocation from QuoteContext to FundamentalContext (#536) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Follow-up to #535 (merged with the API on `QuoteContext`): relocate `etf_asset_allocation` and its types (`AssetAllocationResponse` / `AssetAllocationGroup` / `AssetAllocationItem`, `HoldingDetail`, `ElementType`) to the fundamental module across all languages. - **Rust:** types/method moved to `fundamental`; blocking wrapper moved to `FundamentalContextSync` - **Python:** classes registered under fundamental module; method on `FundamentalContext` / `AsyncFundamentalContext`; `openapi.pyi` updated - **Node.js:** `etfAssetAllocation` now on `FundamentalContext`; `index.d.ts`/`index.js` regenerated - **C:** `lb_quote_context_etf_asset_allocation` → `lb_fundamental_context_etf_asset_allocation`; FFI types moved to `fundamental_context`; `longbridge.h` regenerated - **C++:** method moved to `fundamental::FundamentalContext`; types moved to `namespace fundamental` - CHANGELOG `[Unreleased]` entry updated accordingly ## Breaking change note `QuoteContext::etf_asset_allocation` was only on main briefly (unreleased), so moving it pre-release avoids shipping it in the wrong context. ## Verification - `cargo clippy --all --all-features`: clean - `cargo +nightly fmt --all`: applied - All crates compile; C++ checked with `-fsyntax-only` - Verified end-to-end against staging via the CLI integration (`QQQ.US` returns all four allocation groups) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.8 (1M context) --- CHANGELOG.md | 2 +- c/cbindgen.toml | 4 +- c/csrc/include/longbridge.h | 18 +- c/src/fundamental_context/context.rs | 19 ++ c/src/fundamental_context/enum_types.rs | 23 +++ c/src/fundamental_context/types.rs | 220 +++++++++++++++++++++- c/src/quote_context/context.rs | 20 -- c/src/quote_context/enum_types.rs | 23 --- c/src/quote_context/types.rs | 231 +----------------------- cpp/include/fundamental_context.hpp | 5 + cpp/include/quote_context.hpp | 5 - cpp/include/types.hpp | 134 +++++++------- cpp/src/convert.hpp | 24 +-- cpp/src/fundamental_context.cpp | 14 ++ cpp/src/quote_context.cpp | 25 --- nodejs/index.d.ts | 10 +- nodejs/src/fundamental/context.rs | 12 ++ nodejs/src/fundamental/types.rs | 119 ++++++++++++ nodejs/src/quote/context.rs | 32 +--- nodejs/src/quote/types.rs | 121 ------------- python/pysrc/longbridge/openapi.pyi | 180 +++++++++--------- python/src/fundamental/context.rs | 10 + python/src/fundamental/context_async.rs | 14 ++ python/src/fundamental/mod.rs | 5 + python/src/fundamental/types.rs | 119 ++++++++++++ python/src/quote/context.rs | 13 -- python/src/quote/context_async.rs | 15 -- python/src/quote/mod.rs | 5 - python/src/quote/types.rs | 121 ------------- rust/src/blocking/fundamental.rs | 10 + rust/src/blocking/quote.rs | 14 +- rust/src/fundamental/context.rs | 23 +++ rust/src/fundamental/types.rs | 108 +++++++++++ rust/src/quote/context.rs | 37 +--- rust/src/quote/mod.rs | 5 - rust/src/quote/types.rs | 107 ----------- 36 files changed, 901 insertions(+), 946 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 796462fac..415603edb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- **All languages:** `QuoteContext` gains `etf_asset_allocation(symbol)` — queries `GET /v1/quote/etf-asset-allocation` for ETF asset allocation grouped by element type (`Holdings` / `Regional` / `AssetClass` / `Industry`); returns `AssetAllocationResponse` with report date, position ratios, localized names, and per-holding detail +- **All languages:** `FundamentalContext` gains `etf_asset_allocation(symbol)` — queries `GET /v1/quote/etf-asset-allocation` for ETF asset allocation grouped by element type (`Holdings` / `Regional` / `AssetClass` / `Industry`); returns `AssetAllocationResponse` with report date, position ratios, localized names, and per-holding detail ## [4.2.2] diff --git a/c/cbindgen.toml b/c/cbindgen.toml index 229a40d58..607547c80 100644 --- a/c/cbindgen.toml +++ b/c/cbindgen.toml @@ -304,13 +304,13 @@ cpp_compat = true "COptionVolumeStats" = "lb_option_volume_stats_t" "COptionVolumeDailyStat" = "lb_option_volume_daily_stat_t" "COptionVolumeDaily" = "lb_option_volume_daily_t" +# FundamentalContext new types "CElementType" = "lb_element_type_t" "CLocaleName" = "lb_locale_name_t" "CHoldingDetail" = "lb_holding_detail_t" "CAssetAllocationItem" = "lb_asset_allocation_item_t" "CAssetAllocationGroup" = "lb_asset_allocation_group_t" "CAssetAllocationResponse" = "lb_asset_allocation_response_t" -# FundamentalContext new types "CShareholderTopResponse" = "lb_shareholder_top_response_t" "CShareholderDetailResponse" = "lb_shareholder_detail_response_t" "CValuationHistoryPoint" = "lb_valuation_history_point_t" @@ -447,10 +447,10 @@ include = [ "CShortTradesItem", "CShortTradesResponse", "COptionVolumeStats", "COptionVolumeDailyStat", "COptionVolumeDaily", + # FundamentalContext new types "CElementType", "CLocaleName", "CHoldingDetail", "CAssetAllocationItem", "CAssetAllocationGroup", "CAssetAllocationResponse", - # FundamentalContext new types "CShareholderTopResponse", "CShareholderDetailResponse", "CValuationHistoryPoint", "CValuationComparisonItem", "CValuationComparisonResponse", # MarketContext new types diff --git a/c/csrc/include/longbridge.h b/c/csrc/include/longbridge.h index b298458e7..35ff1563c 100644 --- a/c/csrc/include/longbridge.h +++ b/c/csrc/include/longbridge.h @@ -9543,6 +9543,15 @@ void lb_fundamental_context_valuation_comparison(const struct lb_fundamental_con lb_async_callback_t callback, void *userdata); +/** + * Get ETF asset allocation (holdings / regional / asset class / industry). + * Returns `CAssetAllocationResponse`. + */ +void lb_fundamental_context_etf_asset_allocation(const struct lb_fundamental_context_t *ctx, + const char *symbol, + lb_async_callback_t callback, + void *userdata); + /** * Create a HTTP client using API Key authentication * @@ -10327,15 +10336,6 @@ void lb_quote_context_option_volume_daily(const struct lb_quote_context_t *ctx, lb_async_callback_t callback, void *userdata); -/** - * Get ETF asset allocation (holdings / regional / asset class / industry). - * Returns `CAssetAllocationResponse`. - */ -void lb_quote_context_etf_asset_allocation(const struct lb_quote_context_t *ctx, - const char *symbol, - lb_async_callback_t callback, - void *userdata); - const struct lb_screener_context_t *lb_screener_context_new(const struct lb_config_t *config); void lb_screener_context_retain(const struct lb_screener_context_t *ctx); diff --git a/c/src/fundamental_context/context.rs b/c/src/fundamental_context/context.rs index 9d05866ce..a7d8fb357 100644 --- a/c/src/fundamental_context/context.rs +++ b/c/src/fundamental_context/context.rs @@ -661,3 +661,22 @@ pub unsafe extern "C" fn lb_fundamental_context_valuation_comparison( Ok(resp) }); } + +/// Get ETF asset allocation (holdings / regional / asset class / industry). +/// Returns `CAssetAllocationResponse`. +#[unsafe(no_mangle)] +pub unsafe extern "C" fn lb_fundamental_context_etf_asset_allocation( + ctx: *const CFundamentalContext, + symbol: *const c_char, + callback: CAsyncCallback, + userdata: *mut c_void, +) { + let ctx_inner = (*ctx).ctx.clone(); + let symbol = cstr_to_rust(symbol); + execute_async(callback, ctx, userdata, async move { + let resp: CCow = CCow::new( + CAssetAllocationResponseOwned::from(ctx_inner.etf_asset_allocation(symbol).await?), + ); + Ok(resp) + }); +} diff --git a/c/src/fundamental_context/enum_types.rs b/c/src/fundamental_context/enum_types.rs index f93fd38c4..ba4f79965 100644 --- a/c/src/fundamental_context/enum_types.rs +++ b/c/src/fundamental_context/enum_types.rs @@ -80,3 +80,26 @@ pub enum CFinancialReportPeriod { #[c(remote = "ThreeQ")] FinancialReportPeriodThreeQ, } + +/// ETF asset allocation element type +#[derive(Debug, Copy, Clone, Eq, PartialEq, CEnum)] +#[c(remote = "longbridge::fundamental::types::ElementType")] +#[allow(clippy::enum_variant_names)] +#[repr(C)] +pub enum CElementType { + /// Unknown + #[c(remote = "Unknown")] + ElementTypeUnknown, + /// Holdings + #[c(remote = "Holdings")] + ElementTypeHoldings, + /// Regional + #[c(remote = "Regional")] + ElementTypeRegional, + /// Asset class + #[c(remote = "AssetClass")] + ElementTypeAssetClass, + /// Industry + #[c(remote = "Industry")] + ElementTypeIndustry, +} diff --git a/c/src/fundamental_context/types.rs b/c/src/fundamental_context/types.rs index ef9198d0b..189a33c68 100644 --- a/c/src/fundamental_context/types.rs +++ b/c/src/fundamental_context/types.rs @@ -3,7 +3,7 @@ use std::os::raw::c_char; use longbridge::fundamental::types::*; use crate::{ - fundamental_context::enum_types::CInstitutionRecommend, + fundamental_context::enum_types::{CElementType, CInstitutionRecommend}, types::{COption, CString, CVec, ToFFI}, }; @@ -3842,3 +3842,221 @@ impl ToFFI for CFinancialReportSnapshotOwned { } } } + +// ── EtfAssetAllocation ──────────────────────────────────────────── + +/// Localized name entry (locale → name) +#[repr(C)] +pub struct CLocaleName { + /// Locale (e.g. `zh-CN`) + pub locale: *const c_char, + /// Localized name + pub name: *const c_char, +} + +pub(crate) struct CLocaleNameOwned { + locale: CString, + name: CString, +} + +impl From<(String, String)> for CLocaleNameOwned { + fn from((locale, name): (String, String)) -> Self { + Self { + locale: locale.into(), + name: name.into(), + } + } +} + +impl ToFFI for CLocaleNameOwned { + type FFIType = CLocaleName; + fn to_ffi_type(&self) -> Self::FFIType { + CLocaleName { + locale: self.locale.to_ffi_type(), + name: self.name.to_ffi_type(), + } + } +} + +/// Holding detail of an ETF asset allocation element (holdings only) +#[repr(C)] +pub struct CHoldingDetail { + /// Industry ID + pub industry_id: *const c_char, + /// Industry name + pub industry_name: *const c_char, + /// Index counter ID (e.g. `BK/US/CP99000`) + pub index: *const c_char, + /// Index name + pub index_name: *const c_char, + /// Holding type (e.g. `E` for stock) + pub holding_type: *const c_char, + /// Holding type name + pub holding_type_name: *const c_char, +} + +pub(crate) struct CHoldingDetailOwned { + industry_id: CString, + industry_name: CString, + index: CString, + index_name: CString, + holding_type: CString, + holding_type_name: CString, +} + +impl From for CHoldingDetailOwned { + fn from(v: HoldingDetail) -> Self { + Self { + industry_id: v.industry_id.into(), + industry_name: v.industry_name.into(), + index: v.index.into(), + index_name: v.index_name.into(), + holding_type: v.holding_type.into(), + holding_type_name: v.holding_type_name.into(), + } + } +} + +impl ToFFI for CHoldingDetailOwned { + type FFIType = CHoldingDetail; + fn to_ffi_type(&self) -> Self::FFIType { + CHoldingDetail { + industry_id: self.industry_id.to_ffi_type(), + industry_name: self.industry_name.to_ffi_type(), + index: self.index.to_ffi_type(), + index_name: self.index_name.to_ffi_type(), + holding_type: self.holding_type.to_ffi_type(), + holding_type_name: self.holding_type_name.to_ffi_type(), + } + } +} + +/// One element of an ETF asset allocation group +#[repr(C)] +pub struct CAssetAllocationItem { + /// Element name + pub name: *const c_char, + /// Security code (holdings only, e.g. `NVDA`) + pub code: *const c_char, + /// Position ratio (e.g. `0.0861114`) + pub position_ratio: *const c_char, + /// Security symbol (holdings only, e.g. `NVDA.US`) + pub symbol: *const c_char, + /// Pointer to array of localized name entries + pub name_locales: *const CLocaleName, + /// Number of elements in the localized name array + pub num_name_locales: usize, + /// Holding detail (holdings only, maybe null) + pub holding_detail: *const CHoldingDetail, +} + +pub(crate) struct CAssetAllocationItemOwned { + name: CString, + code: CString, + position_ratio: CString, + symbol: CString, + name_locales: CVec, + holding_detail: COption, +} + +impl From for CAssetAllocationItemOwned { + fn from(v: AssetAllocationItem) -> Self { + let mut name_locales = v.name_locales.into_iter().collect::>(); + name_locales.sort(); + Self { + name: v.name.into(), + code: v.code.into(), + position_ratio: v.position_ratio.into(), + symbol: v.symbol.into(), + name_locales: name_locales.into(), + holding_detail: v.holding_detail.into(), + } + } +} + +impl ToFFI for CAssetAllocationItemOwned { + type FFIType = CAssetAllocationItem; + fn to_ffi_type(&self) -> Self::FFIType { + CAssetAllocationItem { + name: self.name.to_ffi_type(), + code: self.code.to_ffi_type(), + position_ratio: self.position_ratio.to_ffi_type(), + symbol: self.symbol.to_ffi_type(), + name_locales: self.name_locales.to_ffi_type(), + num_name_locales: self.name_locales.len(), + holding_detail: self.holding_detail.to_ffi_type(), + } + } +} + +/// One ETF asset allocation group (grouped by element type) +#[repr(C)] +pub struct CAssetAllocationGroup { + /// Report date (e.g. `20260601`) + pub report_date: *const c_char, + /// Element type of this group + pub asset_type: CElementType, + /// Pointer to array of elements + pub lists: *const CAssetAllocationItem, + /// Number of elements in the array + pub num_lists: usize, +} + +pub(crate) struct CAssetAllocationGroupOwned { + report_date: CString, + asset_type: ElementType, + lists: CVec, +} + +impl From for CAssetAllocationGroupOwned { + fn from(v: AssetAllocationGroup) -> Self { + Self { + report_date: v.report_date.into(), + asset_type: v.asset_type, + lists: v.lists.into(), + } + } +} + +impl ToFFI for CAssetAllocationGroupOwned { + type FFIType = CAssetAllocationGroup; + fn to_ffi_type(&self) -> Self::FFIType { + CAssetAllocationGroup { + report_date: self.report_date.to_ffi_type(), + asset_type: self.asset_type.into(), + lists: self.lists.to_ffi_type(), + num_lists: self.lists.len(), + } + } +} + +/// ETF asset allocation response +#[repr(C)] +pub struct CAssetAllocationResponse { + /// Pointer to array of asset allocation groups + pub info: *const CAssetAllocationGroup, + /// Number of elements in the array + pub num_info: usize, +} + +pub(crate) struct CAssetAllocationResponseOwned { + info: CVec, +} + +impl From for CAssetAllocationResponseOwned { + fn from(v: AssetAllocationResponse) -> Self { + Self { + info: v.info.into(), + } + } +} + +impl ToFFI for CAssetAllocationResponseOwned { + type FFIType = CAssetAllocationResponse; + fn to_ffi_type(&self) -> Self::FFIType { + CAssetAllocationResponse { + info: self.info.to_ffi_type(), + num_info: self.info.len(), + } + } +} diff --git a/c/src/quote_context/context.rs b/c/src/quote_context/context.rs index 24cc31d10..ce9feef9b 100644 --- a/c/src/quote_context/context.rs +++ b/c/src/quote_context/context.rs @@ -1290,23 +1290,3 @@ pub unsafe extern "C" fn lb_quote_context_option_volume_daily( Ok(resp) }); } - -/// Get ETF asset allocation (holdings / regional / asset class / industry). -/// Returns `CAssetAllocationResponse`. -#[unsafe(no_mangle)] -pub unsafe extern "C" fn lb_quote_context_etf_asset_allocation( - ctx: *const CQuoteContext, - symbol: *const c_char, - callback: CAsyncCallback, - userdata: *mut c_void, -) { - use crate::{quote_context::types::CAssetAllocationResponseOwned, types::CCow}; - let ctx_inner = (*ctx).ctx.clone(); - let symbol = cstr_to_rust(symbol); - execute_async(callback, ctx, userdata, async move { - let resp: CCow = CCow::new( - CAssetAllocationResponseOwned::from(ctx_inner.etf_asset_allocation(symbol).await?), - ); - Ok(resp) - }); -} diff --git a/c/src/quote_context/enum_types.rs b/c/src/quote_context/enum_types.rs index e53a2900b..9bf17ebaa 100644 --- a/c/src/quote_context/enum_types.rs +++ b/c/src/quote_context/enum_types.rs @@ -632,26 +632,3 @@ pub enum CGranularity { #[c(remote = "Monthly")] GranularityMonthly, } - -/// ETF asset allocation element type -#[derive(Debug, Copy, Clone, Eq, PartialEq, CEnum)] -#[c(remote = "longbridge::quote::ElementType")] -#[allow(clippy::enum_variant_names)] -#[repr(C)] -pub enum CElementType { - /// Unknown - #[c(remote = "Unknown")] - ElementTypeUnknown, - /// Holdings - #[c(remote = "Holdings")] - ElementTypeHoldings, - /// Regional - #[c(remote = "Regional")] - ElementTypeRegional, - /// Asset class - #[c(remote = "AssetClass")] - ElementTypeAssetClass, - /// Industry - #[c(remote = "Industry")] - ElementTypeIndustry, -} diff --git a/c/src/quote_context/types.rs b/c/src/quote_context/types.rs index 312aeee15..72cdaf5c8 100644 --- a/c/src/quote_context/types.rs +++ b/c/src/quote_context/types.rs @@ -1,12 +1,11 @@ use std::os::raw::c_char; use longbridge::quote::{ - AssetAllocationGroup, AssetAllocationItem, AssetAllocationResponse, Brokers, Candlestick, - CapitalDistribution, CapitalDistributionResponse, CapitalFlowLine, Depth, ElementType, - FilingItem, HistoryMarketTemperatureResponse, HoldingDetail, IntradayLine, IssuerInfo, - MarketTemperature, MarketTradingDays, MarketTradingSession, OptionDirection, OptionQuote, - OptionType, OptionVolumeDaily, OptionVolumeDailyStat, OptionVolumeStats, ParticipantInfo, - Period, PrePostQuote, PushBrokers, PushCandlestick, PushDepth, PushQuote, PushTrades, + Brokers, Candlestick, CapitalDistribution, CapitalDistributionResponse, CapitalFlowLine, Depth, + FilingItem, HistoryMarketTemperatureResponse, IntradayLine, IssuerInfo, MarketTemperature, + MarketTradingDays, MarketTradingSession, OptionDirection, OptionQuote, OptionType, + OptionVolumeDaily, OptionVolumeDailyStat, OptionVolumeStats, ParticipantInfo, Period, + PrePostQuote, PushBrokers, PushCandlestick, PushDepth, PushQuote, PushTrades, QuotePackageDetail, RealtimeQuote, Security, SecurityBoard, SecurityBrokers, SecurityCalcIndex, SecurityDepth, SecurityQuote, SecurityStaticInfo, ShortPositionsItem, ShortPositionsResponse, ShortTradesItem, ShortTradesResponse, StrikePriceInfo, Subscription, Trade, TradeDirection, @@ -16,7 +15,7 @@ use longbridge::quote::{ use crate::{ quote_context::enum_types::{ - CElementType, CGranularity, COptionDirection, COptionType, CPeriod, CSecuritiesUpdateMode, + CGranularity, COptionDirection, COptionType, CPeriod, CSecuritiesUpdateMode, CSecurityBoard, CTradeDirection, CTradeSession, CTradeStatus, CWarrantStatus, CWarrantType, }, types::{CDate, CDecimal, CMarket, COption, CString, CTime, CVec, ToFFI}, @@ -3443,221 +3442,3 @@ impl ToFFI for COptionVolumeDailyOwned { } } } - -// ── EtfAssetAllocation ──────────────────────────────────────────── - -/// Localized name entry (locale → name) -#[repr(C)] -pub struct CLocaleName { - /// Locale (e.g. `zh-CN`) - pub locale: *const c_char, - /// Localized name - pub name: *const c_char, -} - -pub(crate) struct CLocaleNameOwned { - locale: CString, - name: CString, -} - -impl From<(String, String)> for CLocaleNameOwned { - fn from((locale, name): (String, String)) -> Self { - Self { - locale: locale.into(), - name: name.into(), - } - } -} - -impl ToFFI for CLocaleNameOwned { - type FFIType = CLocaleName; - fn to_ffi_type(&self) -> Self::FFIType { - CLocaleName { - locale: self.locale.to_ffi_type(), - name: self.name.to_ffi_type(), - } - } -} - -/// Holding detail of an ETF asset allocation element (holdings only) -#[repr(C)] -pub struct CHoldingDetail { - /// Industry ID - pub industry_id: *const c_char, - /// Industry name - pub industry_name: *const c_char, - /// Index counter ID (e.g. `BK/US/CP99000`) - pub index: *const c_char, - /// Index name - pub index_name: *const c_char, - /// Holding type (e.g. `E` for stock) - pub holding_type: *const c_char, - /// Holding type name - pub holding_type_name: *const c_char, -} - -pub(crate) struct CHoldingDetailOwned { - industry_id: CString, - industry_name: CString, - index: CString, - index_name: CString, - holding_type: CString, - holding_type_name: CString, -} - -impl From for CHoldingDetailOwned { - fn from(v: HoldingDetail) -> Self { - Self { - industry_id: v.industry_id.into(), - industry_name: v.industry_name.into(), - index: v.index.into(), - index_name: v.index_name.into(), - holding_type: v.holding_type.into(), - holding_type_name: v.holding_type_name.into(), - } - } -} - -impl ToFFI for CHoldingDetailOwned { - type FFIType = CHoldingDetail; - fn to_ffi_type(&self) -> Self::FFIType { - CHoldingDetail { - industry_id: self.industry_id.to_ffi_type(), - industry_name: self.industry_name.to_ffi_type(), - index: self.index.to_ffi_type(), - index_name: self.index_name.to_ffi_type(), - holding_type: self.holding_type.to_ffi_type(), - holding_type_name: self.holding_type_name.to_ffi_type(), - } - } -} - -/// One element of an ETF asset allocation group -#[repr(C)] -pub struct CAssetAllocationItem { - /// Element name - pub name: *const c_char, - /// Security code (holdings only, e.g. `NVDA`) - pub code: *const c_char, - /// Position ratio (e.g. `0.0861114`) - pub position_ratio: *const c_char, - /// Security symbol (holdings only, e.g. `NVDA.US`) - pub symbol: *const c_char, - /// Pointer to array of localized name entries - pub name_locales: *const CLocaleName, - /// Number of elements in the localized name array - pub num_name_locales: usize, - /// Holding detail (holdings only, maybe null) - pub holding_detail: *const CHoldingDetail, -} - -pub(crate) struct CAssetAllocationItemOwned { - name: CString, - code: CString, - position_ratio: CString, - symbol: CString, - name_locales: CVec, - holding_detail: COption, -} - -impl From for CAssetAllocationItemOwned { - fn from(v: AssetAllocationItem) -> Self { - let mut name_locales = v.name_locales.into_iter().collect::>(); - name_locales.sort(); - Self { - name: v.name.into(), - code: v.code.into(), - position_ratio: v.position_ratio.into(), - symbol: v.symbol.into(), - name_locales: name_locales.into(), - holding_detail: v.holding_detail.into(), - } - } -} - -impl ToFFI for CAssetAllocationItemOwned { - type FFIType = CAssetAllocationItem; - fn to_ffi_type(&self) -> Self::FFIType { - CAssetAllocationItem { - name: self.name.to_ffi_type(), - code: self.code.to_ffi_type(), - position_ratio: self.position_ratio.to_ffi_type(), - symbol: self.symbol.to_ffi_type(), - name_locales: self.name_locales.to_ffi_type(), - num_name_locales: self.name_locales.len(), - holding_detail: self.holding_detail.to_ffi_type(), - } - } -} - -/// One ETF asset allocation group (grouped by element type) -#[repr(C)] -pub struct CAssetAllocationGroup { - /// Report date (e.g. `20260601`) - pub report_date: *const c_char, - /// Element type of this group - pub asset_type: CElementType, - /// Pointer to array of elements - pub lists: *const CAssetAllocationItem, - /// Number of elements in the array - pub num_lists: usize, -} - -pub(crate) struct CAssetAllocationGroupOwned { - report_date: CString, - asset_type: ElementType, - lists: CVec, -} - -impl From for CAssetAllocationGroupOwned { - fn from(v: AssetAllocationGroup) -> Self { - Self { - report_date: v.report_date.into(), - asset_type: v.asset_type, - lists: v.lists.into(), - } - } -} - -impl ToFFI for CAssetAllocationGroupOwned { - type FFIType = CAssetAllocationGroup; - fn to_ffi_type(&self) -> Self::FFIType { - CAssetAllocationGroup { - report_date: self.report_date.to_ffi_type(), - asset_type: self.asset_type.into(), - lists: self.lists.to_ffi_type(), - num_lists: self.lists.len(), - } - } -} - -/// ETF asset allocation response -#[repr(C)] -pub struct CAssetAllocationResponse { - /// Pointer to array of asset allocation groups - pub info: *const CAssetAllocationGroup, - /// Number of elements in the array - pub num_info: usize, -} - -pub(crate) struct CAssetAllocationResponseOwned { - info: CVec, -} - -impl From for CAssetAllocationResponseOwned { - fn from(v: AssetAllocationResponse) -> Self { - Self { - info: v.info.into(), - } - } -} - -impl ToFFI for CAssetAllocationResponseOwned { - type FFIType = CAssetAllocationResponse; - fn to_ffi_type(&self) -> Self::FFIType { - CAssetAllocationResponse { - info: self.info.to_ffi_type(), - num_info: self.info.len(), - } - } -} diff --git a/cpp/include/fundamental_context.hpp b/cpp/include/fundamental_context.hpp index 451da4256..799231d58 100644 --- a/cpp/include/fundamental_context.hpp +++ b/cpp/include/fundamental_context.hpp @@ -175,6 +175,11 @@ class FundamentalContext const std::string& currency, const std::vector* comparison_symbols, AsyncCallback callback) const; + + /// Get ETF asset allocation (holdings / regional / asset class / industry) + void etf_asset_allocation( + const std::string& symbol, + AsyncCallback callback) const; }; } // namespace fundamental diff --git a/cpp/include/quote_context.hpp b/cpp/include/quote_context.hpp index 5f5a98fe7..01644f332 100644 --- a/cpp/include/quote_context.hpp +++ b/cpp/include/quote_context.hpp @@ -333,11 +333,6 @@ class QuoteContext int64_t timestamp, uint32_t count, AsyncCallback callback) const; - - /// Get ETF asset allocation (holdings / regional / asset class / industry) - void etf_asset_allocation( - const std::string& symbol, - AsyncCallback callback) const; }; } // namespace quote diff --git a/cpp/include/types.hpp b/cpp/include/types.hpp index 94684d5ae..7c66849b0 100644 --- a/cpp/include/types.hpp +++ b/cpp/include/types.hpp @@ -1347,73 +1347,6 @@ struct OptionVolumeDaily std::vector stats; }; -/// ETF asset allocation element type -enum class ElementType -{ - /// Unknown - Unknown, - /// Holdings - Holdings, - /// Regional - Regional, - /// Asset class - AssetClass, - /// Industry - Industry, -}; - -/// Holding detail of an ETF asset allocation element (holdings only) -struct HoldingDetail -{ - /// Industry ID - std::string industry_id; - /// Industry name - std::string industry_name; - /// Index counter ID (e.g. `BK/US/CP99000`) - std::string index; - /// Index name - std::string index_name; - /// Holding type (e.g. `E` for stock) - std::string holding_type; - /// Holding type name - std::string holding_type_name; -}; - -/// One element of an ETF asset allocation group -struct AssetAllocationItem -{ - /// Element name - std::string name; - /// Security code (holdings only, e.g. `NVDA`) - std::string code; - /// Position ratio (e.g. `0.0861114`) - std::string position_ratio; - /// Security symbol (holdings only, e.g. `NVDA.US`) - std::string symbol; - /// Localized names (locale → name) - std::map name_locales; - /// Holding detail (holdings only) - std::optional holding_detail; -}; - -/// One ETF asset allocation group (grouped by element type) -struct AssetAllocationGroup -{ - /// Report date (e.g. `20260601`) - std::string report_date; - /// Element type of this group - ElementType asset_type; - /// Elements - std::vector lists; -}; - -/// ETF asset allocation response -struct AssetAllocationResponse -{ - /// Asset allocation groups - std::vector info; -}; - } // namespace quote namespace trade { @@ -3341,6 +3274,73 @@ struct ValuationComparisonResponse std::vector list; }; +/// ETF asset allocation element type +enum class ElementType +{ + /// Unknown + Unknown, + /// Holdings + Holdings, + /// Regional + Regional, + /// Asset class + AssetClass, + /// Industry + Industry, +}; + +/// Holding detail of an ETF asset allocation element (holdings only) +struct HoldingDetail +{ + /// Industry ID + std::string industry_id; + /// Industry name + std::string industry_name; + /// Index counter ID (e.g. `BK/US/CP99000`) + std::string index; + /// Index name + std::string index_name; + /// Holding type (e.g. `E` for stock) + std::string holding_type; + /// Holding type name + std::string holding_type_name; +}; + +/// One element of an ETF asset allocation group +struct AssetAllocationItem +{ + /// Element name + std::string name; + /// Security code (holdings only, e.g. `NVDA`) + std::string code; + /// Position ratio (e.g. `0.0861114`) + std::string position_ratio; + /// Security symbol (holdings only, e.g. `NVDA.US`) + std::string symbol; + /// Localized names (locale → name) + std::map name_locales; + /// Holding detail (holdings only) + std::optional holding_detail; +}; + +/// One ETF asset allocation group (grouped by element type) +struct AssetAllocationGroup +{ + /// Report date (e.g. `20260601`) + std::string report_date; + /// Element type of this group + ElementType asset_type; + /// Elements + std::vector lists; +}; + +/// ETF asset allocation response +struct AssetAllocationResponse +{ + /// Asset allocation groups + std::vector info; +}; + } // namespace fundamental namespace alert { diff --git a/cpp/src/convert.hpp b/cpp/src/convert.hpp index 78a5f1beb..8789e1a77 100644 --- a/cpp/src/convert.hpp +++ b/cpp/src/convert.hpp @@ -2335,23 +2335,23 @@ inline quote::OptionVolumeDaily convert(const lb_option_volume_daily_t* r) { for (size_t i = 0; i < r->num_stats; ++i) stats.push_back(convert(&r->stats[i])); return { std::move(stats) }; } -inline quote::ElementType convert(lb_element_type_t ty) { +inline fundamental::ElementType convert(lb_element_type_t ty) { switch (ty) { case ElementTypeUnknown: - return quote::ElementType::Unknown; + return fundamental::ElementType::Unknown; case ElementTypeHoldings: - return quote::ElementType::Holdings; + return fundamental::ElementType::Holdings; case ElementTypeRegional: - return quote::ElementType::Regional; + return fundamental::ElementType::Regional; case ElementTypeAssetClass: - return quote::ElementType::AssetClass; + return fundamental::ElementType::AssetClass; case ElementTypeIndustry: - return quote::ElementType::Industry; + return fundamental::ElementType::Industry; default: throw std::invalid_argument("unreachable"); } } -inline quote::HoldingDetail convert(const lb_holding_detail_t* d) { +inline fundamental::HoldingDetail convert(const lb_holding_detail_t* d) { return { d->industry_id ? d->industry_id : "", d->industry_name ? d->industry_name : "", d->index ? d->index : "", @@ -2359,7 +2359,7 @@ inline quote::HoldingDetail convert(const lb_holding_detail_t* d) { d->holding_type ? d->holding_type : "", d->holding_type_name ? d->holding_type_name : "" }; } -inline quote::AssetAllocationItem convert(const lb_asset_allocation_item_t* item) { +inline fundamental::AssetAllocationItem convert(const lb_asset_allocation_item_t* item) { std::map name_locales; for (size_t i = 0; i < item->num_name_locales; ++i) { const auto& entry = item->name_locales[i]; @@ -2373,13 +2373,13 @@ inline quote::AssetAllocationItem convert(const lb_asset_allocation_item_t* item item->holding_detail ? std::make_optional(convert(item->holding_detail)) : std::nullopt }; } -inline quote::AssetAllocationGroup convert(const lb_asset_allocation_group_t* g) { - std::vector lists; +inline fundamental::AssetAllocationGroup convert(const lb_asset_allocation_group_t* g) { + std::vector lists; for (size_t i = 0; i < g->num_lists; ++i) lists.push_back(convert(&g->lists[i])); return { g->report_date ? g->report_date : "", convert(g->asset_type), std::move(lists) }; } -inline quote::AssetAllocationResponse convert(const lb_asset_allocation_response_t* r) { - std::vector info; +inline fundamental::AssetAllocationResponse convert(const lb_asset_allocation_response_t* r) { + std::vector info; for (size_t i = 0; i < r->num_info; ++i) info.push_back(convert(&r->info[i])); return { std::move(info) }; } diff --git a/cpp/src/fundamental_context.cpp b/cpp/src/fundamental_context.cpp index c14148cd0..f108dda11 100644 --- a/cpp/src/fundamental_context.cpp +++ b/cpp/src/fundamental_context.cpp @@ -169,5 +169,19 @@ void FundamentalContext::valuation_comparison(const std::string& s, const std::s #undef F_JSON_STRUCT +void FundamentalContext::etf_asset_allocation(const std::string& symbol, AsyncCallback callback) const { + lb_fundamental_context_etf_asset_allocation(ctx_, symbol.c_str(), + [](auto res) { + auto cb = callback::get_async_callback(res->userdata); + FundamentalContext fctx((const lb_fundamental_context_t*)res->ctx); Status status(res->error); + if (status) { + auto r = convert::convert((const lb_asset_allocation_response_t*)res->data); + (*cb)(AsyncResult(fctx, std::move(status), &r)); + } else { + (*cb)(AsyncResult(fctx, std::move(status), nullptr)); + } + }, new AsyncCallback(callback)); +} + } // namespace fundamental } // namespace longbridge diff --git a/cpp/src/quote_context.cpp b/cpp/src/quote_context.cpp index 2f0d05417..ab5e4f2b5 100644 --- a/cpp/src/quote_context.cpp +++ b/cpp/src/quote_context.cpp @@ -1759,30 +1759,5 @@ QuoteContext::option_volume_daily(const std::string& symbol, new AsyncCallback(callback)); } -void -QuoteContext::etf_asset_allocation( - const std::string& symbol, - AsyncCallback callback) const -{ - lb_quote_context_etf_asset_allocation( - ctx_, - symbol.c_str(), - [](auto res) { - auto callback_ptr = - callback::get_async_callback(res->userdata); - QuoteContext ctx((const lb_quote_context_t*)res->ctx); - Status status(res->error); - if (status) { - auto value = convert::convert((const lb_asset_allocation_response_t*)res->data); - (*callback_ptr)( - AsyncResult(ctx, std::move(status), &value)); - } else { - (*callback_ptr)( - AsyncResult(ctx, std::move(status), nullptr)); - } - }, - new AsyncCallback(callback)); -} - } // namespace quote } // namespace longbridge \ No newline at end of file diff --git a/nodejs/index.d.ts b/nodejs/index.d.ts index 55217b341..c7f7b1eb4 100644 --- a/nodejs/index.d.ts +++ b/nodejs/index.d.ts @@ -613,6 +613,11 @@ export declare class FundamentalContext { shareholderDetail(symbol: string, objectId: number): Promise /** Get valuation comparison between a security and optional peers */ valuationComparison(symbol: string, currency: string, comparisonSymbols?: Array | undefined | null): Promise + /** + * Get ETF asset allocation (holdings / regional / asset class / + * industry) + */ + etfAssetAllocation(symbol: string): Promise } /** Fund position */ @@ -2021,11 +2026,6 @@ export declare class QuoteContext { optionVolume(symbol: string): Promise /** Get daily historical option volume */ optionVolumeDaily(symbol: string, timestamp: number, count: number): Promise - /** - * Get ETF asset allocation (holdings / regional / asset class / - * industry) - */ - etfAssetAllocation(symbol: string): Promise } export declare class QuotePackageDetail { diff --git a/nodejs/src/fundamental/context.rs b/nodejs/src/fundamental/context.rs index 0878dad09..ca1cc3528 100644 --- a/nodejs/src/fundamental/context.rs +++ b/nodejs/src/fundamental/context.rs @@ -275,4 +275,16 @@ impl FundamentalContext { .map_err(ErrorNewType)? .into()) } + + /// Get ETF asset allocation (holdings / regional / asset class / + /// industry) + #[napi] + pub async fn etf_asset_allocation(&self, symbol: String) -> Result { + Ok(self + .ctx + .etf_asset_allocation(symbol) + .await + .map_err(ErrorNewType)? + .into()) + } } diff --git a/nodejs/src/fundamental/types.rs b/nodejs/src/fundamental/types.rs index eaf68e746..37664aba5 100644 --- a/nodejs/src/fundamental/types.rs +++ b/nodejs/src/fundamental/types.rs @@ -1783,3 +1783,122 @@ impl From for ValuationComparisonResponse { } } } + +// ── etf_asset_allocation ────────────────────────────────────────── + +/// ETF asset allocation element type +#[napi_derive::napi] +#[derive(longbridge_nodejs_macros::JsEnum, Debug, Hash, Eq, PartialEq, Copy, Clone)] +#[js(remote = "longbridge::fundamental::types::ElementType")] +pub enum ElementType { + /// Unknown + Unknown, + /// Holdings + Holdings, + /// Regional + Regional, + /// Asset class + AssetClass, + /// Industry + Industry, +} + +/// Holding detail of an ETF asset allocation element (holdings only) +#[napi_derive::napi(object)] +#[derive(Debug, Clone)] +pub struct HoldingDetail { + /// Industry ID + pub industry_id: String, + /// Industry name + pub industry_name: String, + /// Index counter ID (e.g. `BK/US/CP99000`) + pub index: String, + /// Index name + pub index_name: String, + /// Holding type (e.g. `E` for stock) + pub holding_type: String, + /// Holding type name + pub holding_type_name: String, +} + +impl From for HoldingDetail { + fn from(v: lb::HoldingDetail) -> Self { + Self { + industry_id: v.industry_id, + industry_name: v.industry_name, + index: v.index, + index_name: v.index_name, + holding_type: v.holding_type, + holding_type_name: v.holding_type_name, + } + } +} + +/// One element of an ETF asset allocation group +#[napi_derive::napi(object)] +#[derive(Debug, Clone)] +pub struct AssetAllocationItem { + /// Element name + pub name: String, + /// Security code (holdings only, e.g. `NVDA`) + pub code: String, + /// Position ratio (e.g. `0.0861114`) + pub position_ratio: String, + /// Security symbol (holdings only, e.g. `NVDA.US`) + pub symbol: String, + /// Localized names (locale → name) + pub name_locales: std::collections::HashMap, + /// Holding detail (holdings only) + pub holding_detail: Option, +} + +impl From for AssetAllocationItem { + fn from(v: lb::AssetAllocationItem) -> Self { + Self { + name: v.name, + code: v.code, + position_ratio: v.position_ratio, + symbol: v.symbol, + name_locales: v.name_locales, + holding_detail: v.holding_detail.map(Into::into), + } + } +} + +/// One ETF asset allocation group (grouped by element type) +#[napi_derive::napi(object)] +#[derive(Debug, Clone)] +pub struct AssetAllocationGroup { + /// Report date (e.g. `20260601`) + pub report_date: String, + /// Element type of this group + pub asset_type: ElementType, + /// Elements + pub lists: Vec, +} + +impl From for AssetAllocationGroup { + fn from(v: lb::AssetAllocationGroup) -> Self { + Self { + report_date: v.report_date, + asset_type: v.asset_type.into(), + lists: v.lists.into_iter().map(Into::into).collect(), + } + } +} + +/// ETF asset allocation response +#[napi_derive::napi(object)] +#[derive(Debug, Clone)] +pub struct AssetAllocationResponse { + /// Asset allocation groups + pub info: Vec, +} + +impl From for AssetAllocationResponse { + fn from(v: lb::AssetAllocationResponse) -> Self { + Self { + info: v.info.into_iter().map(Into::into).collect(), + } + } +} diff --git a/nodejs/src/quote/context.rs b/nodejs/src/quote/context.rs index 7ede12509..4ee04a1e2 100644 --- a/nodejs/src/quote/context.rs +++ b/nodejs/src/quote/context.rs @@ -13,16 +13,16 @@ use crate::{ }, requests::{CreateWatchlistGroup, DeleteWatchlistGroup, UpdateWatchlistGroup}, types::{ - AdjustType, AssetAllocationResponse, CalcIndex, Candlestick, - CapitalDistributionResponse, CapitalFlowLine, FilingItem, FilterWarrantExpiryDate, - FilterWarrantInOutBoundsType, HistoryMarketTemperatureResponse, IntradayLine, - IssuerInfo, MarketTemperature, MarketTradingDays, MarketTradingSession, OptionQuote, - OptionVolumeDaily, OptionVolumeStats, ParticipantInfo, Period, PinnedMode, - QuotePackageDetail, RealtimeQuote, Security, SecurityBrokers, SecurityCalcIndex, - SecurityDepth, SecurityListCategory, SecurityQuote, SecurityStaticInfo, - ShortPositionsResponse, ShortTradesResponse, SortOrderType, StrikePriceInfo, SubType, - SubTypes, Subscription, Trade, TradeSessions, WarrantInfo, WarrantQuote, WarrantSortBy, - WarrantStatus, WarrantType, WatchlistGroup, + AdjustType, CalcIndex, Candlestick, CapitalDistributionResponse, CapitalFlowLine, + FilingItem, FilterWarrantExpiryDate, FilterWarrantInOutBoundsType, + HistoryMarketTemperatureResponse, IntradayLine, IssuerInfo, MarketTemperature, + MarketTradingDays, MarketTradingSession, OptionQuote, OptionVolumeDaily, + OptionVolumeStats, ParticipantInfo, Period, PinnedMode, QuotePackageDetail, + RealtimeQuote, Security, SecurityBrokers, SecurityCalcIndex, SecurityDepth, + SecurityListCategory, SecurityQuote, SecurityStaticInfo, ShortPositionsResponse, + ShortTradesResponse, SortOrderType, StrikePriceInfo, SubType, SubTypes, Subscription, + Trade, TradeSessions, WarrantInfo, WarrantQuote, WarrantSortBy, WarrantStatus, + WarrantType, WatchlistGroup, }, }, time::{NaiveDate, NaiveDatetime}, @@ -1290,16 +1290,4 @@ impl QuoteContext { .map_err(ErrorNewType)? .into()) } - - /// Get ETF asset allocation (holdings / regional / asset class / - /// industry) - #[napi] - pub async fn etf_asset_allocation(&self, symbol: String) -> Result { - Ok(self - .ctx - .etf_asset_allocation(symbol) - .await - .map_err(ErrorNewType)? - .into()) - } } diff --git a/nodejs/src/quote/types.rs b/nodejs/src/quote/types.rs index 86379fa62..acd0cfdd4 100644 --- a/nodejs/src/quote/types.rs +++ b/nodejs/src/quote/types.rs @@ -1,5 +1,3 @@ -use std::collections::HashMap; - use chrono::{DateTime, Utc}; use longbridge::quote::SubFlags; use longbridge_nodejs_macros::{JsEnum, JsObject}; @@ -1665,122 +1663,3 @@ impl From for OptionVolumeDailyStat { } } } - -// ── etf_asset_allocation ────────────────────────────────────────── - -/// ETF asset allocation element type -#[napi_derive::napi] -#[derive(JsEnum, Debug, Hash, Eq, PartialEq, Copy, Clone)] -#[js(remote = "longbridge::quote::ElementType")] -pub enum ElementType { - /// Unknown - Unknown, - /// Holdings - Holdings, - /// Regional - Regional, - /// Asset class - AssetClass, - /// Industry - Industry, -} - -/// Holding detail of an ETF asset allocation element (holdings only) -#[napi_derive::napi(object)] -#[derive(Debug, Clone)] -pub struct HoldingDetail { - /// Industry ID - pub industry_id: String, - /// Industry name - pub industry_name: String, - /// Index counter ID (e.g. `BK/US/CP99000`) - pub index: String, - /// Index name - pub index_name: String, - /// Holding type (e.g. `E` for stock) - pub holding_type: String, - /// Holding type name - pub holding_type_name: String, -} - -impl From for HoldingDetail { - fn from(v: longbridge::quote::HoldingDetail) -> Self { - Self { - industry_id: v.industry_id, - industry_name: v.industry_name, - index: v.index, - index_name: v.index_name, - holding_type: v.holding_type, - holding_type_name: v.holding_type_name, - } - } -} - -/// One element of an ETF asset allocation group -#[napi_derive::napi(object)] -#[derive(Debug, Clone)] -pub struct AssetAllocationItem { - /// Element name - pub name: String, - /// Security code (holdings only, e.g. `NVDA`) - pub code: String, - /// Position ratio (e.g. `0.0861114`) - pub position_ratio: String, - /// Security symbol (holdings only, e.g. `NVDA.US`) - pub symbol: String, - /// Localized names (locale → name) - pub name_locales: HashMap, - /// Holding detail (holdings only) - pub holding_detail: Option, -} - -impl From for AssetAllocationItem { - fn from(v: longbridge::quote::AssetAllocationItem) -> Self { - Self { - name: v.name, - code: v.code, - position_ratio: v.position_ratio, - symbol: v.symbol, - name_locales: v.name_locales, - holding_detail: v.holding_detail.map(Into::into), - } - } -} - -/// One ETF asset allocation group (grouped by element type) -#[napi_derive::napi(object)] -#[derive(Debug, Clone)] -pub struct AssetAllocationGroup { - /// Report date (e.g. `20260601`) - pub report_date: String, - /// Element type of this group - pub asset_type: ElementType, - /// Elements - pub lists: Vec, -} - -impl From for AssetAllocationGroup { - fn from(v: longbridge::quote::AssetAllocationGroup) -> Self { - Self { - report_date: v.report_date, - asset_type: v.asset_type.into(), - lists: v.lists.into_iter().map(Into::into).collect(), - } - } -} - -/// ETF asset allocation response -#[napi_derive::napi(object)] -#[derive(Debug, Clone)] -pub struct AssetAllocationResponse { - /// Asset allocation groups - pub info: Vec, -} - -impl From for AssetAllocationResponse { - fn from(v: longbridge::quote::AssetAllocationResponse) -> Self { - Self { - info: v.info.into_iter().map(Into::into).collect(), - } - } -} diff --git a/python/pysrc/longbridge/openapi.pyi b/python/pysrc/longbridge/openapi.pyi index 3590f5d30..90bc788e3 100644 --- a/python/pysrc/longbridge/openapi.pyi +++ b/python/pysrc/longbridge/openapi.pyi @@ -4020,17 +4020,6 @@ class QuoteContext: :class:`ShortTradesResponse` with raw JSON data """ - def etf_asset_allocation(self, symbol: str) -> AssetAllocationResponse: - """ - Get ETF asset allocation (holdings / regional / asset class / industry). - - Args: - symbol: ETF security code (e.g. ``"QQQ.US"``) - - Returns: - :class:`AssetAllocationResponse` with allocation groups - """ - class AsyncQuoteContext: """ Async quote context for use with asyncio. Create via `AsyncQuoteContext.create(config)` and await inside asyncio. @@ -5383,21 +5372,6 @@ class AsyncQuoteContext: """ ... - def etf_asset_allocation( - self, symbol: str - ) -> Awaitable[AssetAllocationResponse]: - """ - Get ETF asset allocation (holdings / regional / asset class / industry). - Returns awaitable. - - Args: - symbol: ETF security code (e.g. ``"QQQ.US"``) - - Returns: - Awaitable resolving to :class:`AssetAllocationResponse` - """ - ... - class OrderSide: """ Order side @@ -9936,6 +9910,18 @@ class FundamentalContext: """ ... + def etf_asset_allocation(self, symbol: str) -> "AssetAllocationResponse": + """ + Get ETF asset allocation (holdings / regional / asset class / industry). + + Args: + symbol: ETF security code (e.g. ``"QQQ.US"``) + + Returns: + :class:`AssetAllocationResponse` with allocation groups + """ + ... + # ── FundamentalContext new response types ───────────────────────── @@ -10008,6 +9994,77 @@ class ValuationComparisonResponse: """Valuation comparison items""" +class ElementType: + """ETF asset allocation element type.""" + + class Unknown(ElementType): + """Unknown""" + + class Holdings(ElementType): + """Holdings""" + + class Regional(ElementType): + """Regional""" + + class AssetClass(ElementType): + """Asset class""" + + class Industry(ElementType): + """Industry""" + + +class HoldingDetail: + """Holding detail of an ETF asset allocation element (holdings only).""" + + industry_id: str + """Industry ID""" + industry_name: str + """Industry name""" + index: str + """Index counter ID (e.g. ``BK/US/CP99000``)""" + index_name: str + """Index name""" + holding_type: str + """Holding type (e.g. ``E`` for stock)""" + holding_type_name: str + """Holding type name""" + + +class AssetAllocationItem: + """One element of an ETF asset allocation group.""" + + name: str + """Element name""" + code: str + """Security code (holdings only, e.g. ``NVDA``)""" + position_ratio: str + """Position ratio (e.g. ``0.0861114``)""" + symbol: str + """Security symbol (holdings only, e.g. ``NVDA.US``)""" + name_locales: dict[str, str] + """Localized names (locale → name)""" + holding_detail: Optional[HoldingDetail] + """Holding detail (holdings only)""" + + +class AssetAllocationGroup: + """One ETF asset allocation group (grouped by element type).""" + + report_date: str + """Report date (e.g. ``20260601``)""" + asset_type: Type[ElementType] + """Element type of this group""" + lists: list[AssetAllocationItem] + """Elements""" + + +class AssetAllocationResponse: + """ETF asset allocation response.""" + + info: list[AssetAllocationGroup] + """Asset allocation groups""" + + # ── MarketContext ───────────────────────────────────────────────── class MarketTimeItem: @@ -11963,74 +12020,3 @@ class OptionVolumeDaily: stats: list[OptionVolumeDailyStat] """Daily option volume statistics""" - - -class ElementType: - """ETF asset allocation element type.""" - - class Unknown(ElementType): - """Unknown""" - - class Holdings(ElementType): - """Holdings""" - - class Regional(ElementType): - """Regional""" - - class AssetClass(ElementType): - """Asset class""" - - class Industry(ElementType): - """Industry""" - - -class HoldingDetail: - """Holding detail of an ETF asset allocation element (holdings only).""" - - industry_id: str - """Industry ID""" - industry_name: str - """Industry name""" - index: str - """Index counter ID (e.g. ``BK/US/CP99000``)""" - index_name: str - """Index name""" - holding_type: str - """Holding type (e.g. ``E`` for stock)""" - holding_type_name: str - """Holding type name""" - - -class AssetAllocationItem: - """One element of an ETF asset allocation group.""" - - name: str - """Element name""" - code: str - """Security code (holdings only, e.g. ``NVDA``)""" - position_ratio: str - """Position ratio (e.g. ``0.0861114``)""" - symbol: str - """Security symbol (holdings only, e.g. ``NVDA.US``)""" - name_locales: dict[str, str] - """Localized names (locale → name)""" - holding_detail: Optional[HoldingDetail] - """Holding detail (holdings only)""" - - -class AssetAllocationGroup: - """One ETF asset allocation group (grouped by element type).""" - - report_date: str - """Report date (e.g. ``20260601``)""" - asset_type: Type[ElementType] - """Element type of this group""" - lists: list[AssetAllocationItem] - """Elements""" - - -class AssetAllocationResponse: - """ETF asset allocation response.""" - - info: list[AssetAllocationGroup] - """Asset allocation groups""" diff --git a/python/src/fundamental/context.rs b/python/src/fundamental/context.rs index 87f2e26fd..e65d93fd2 100644 --- a/python/src/fundamental/context.rs +++ b/python/src/fundamental/context.rs @@ -198,4 +198,14 @@ impl FundamentalContext { .map_err(ErrorNewType)? .into()) } + + /// Get ETF asset allocation (holdings / regional / asset class / + /// industry). + fn etf_asset_allocation(&self, symbol: String) -> PyResult { + Ok(self + .ctx + .etf_asset_allocation(symbol) + .map_err(ErrorNewType)? + .into()) + } } diff --git a/python/src/fundamental/context_async.rs b/python/src/fundamental/context_async.rs index 8c162b9a5..eed4d6142 100644 --- a/python/src/fundamental/context_async.rs +++ b/python/src/fundamental/context_async.rs @@ -303,4 +303,18 @@ impl AsyncFundamentalContext { }) .map(|b| b.unbind()) } + + /// Get ETF asset allocation (holdings / regional / asset class / + /// industry). Returns awaitable. + fn etf_asset_allocation(&self, py: Python<'_>, symbol: String) -> PyResult> { + let ctx = self.ctx.clone(); + pyo3_async_runtimes::tokio::future_into_py(py, async move { + Ok(AssetAllocationResponse::from( + ctx.etf_asset_allocation(symbol) + .await + .map_err(ErrorNewType)?, + )) + }) + .map(|b| b.unbind()) + } } diff --git a/python/src/fundamental/mod.rs b/python/src/fundamental/mod.rs index 62dfd8da4..a788e712e 100644 --- a/python/src/fundamental/mod.rs +++ b/python/src/fundamental/mod.rs @@ -69,6 +69,11 @@ pub(crate) fn register_types(parent: &Bound) -> PyResult<()> { parent.add_class::()?; parent.add_class::()?; parent.add_class::()?; + parent.add_class::()?; + parent.add_class::()?; + parent.add_class::()?; + parent.add_class::()?; + parent.add_class::()?; parent.add_class::()?; parent.add_class::()?; Ok(()) diff --git a/python/src/fundamental/types.rs b/python/src/fundamental/types.rs index 8219dc6f4..3a8f6ed59 100644 --- a/python/src/fundamental/types.rs +++ b/python/src/fundamental/types.rs @@ -1846,3 +1846,122 @@ impl From for ValuationComparisonResponse { } } } + +// ── etf_asset_allocation ────────────────────────────────────────── + +/// ETF asset allocation element type +#[pyclass(eq, eq_int, skip_from_py_object)] +#[derive(PyEnum, Debug, Copy, Clone, Hash, Eq, PartialEq)] +#[py(remote = "longbridge::fundamental::types::ElementType")] +pub(crate) enum ElementType { + /// Unknown + Unknown, + /// Holdings + Holdings, + /// Regional + Regional, + /// Asset class + AssetClass, + /// Industry + Industry, +} + +/// Holding detail of an ETF asset allocation element (holdings only) +#[pyclass(get_all, skip_from_py_object)] +#[derive(Debug, Clone)] +pub(crate) struct HoldingDetail { + /// Industry ID + pub industry_id: String, + /// Industry name + pub industry_name: String, + /// Index counter ID (e.g. `BK/US/CP99000`) + pub index: String, + /// Index name + pub index_name: String, + /// Holding type (e.g. `E` for stock) + pub holding_type: String, + /// Holding type name + pub holding_type_name: String, +} + +impl From for HoldingDetail { + fn from(v: lb::HoldingDetail) -> Self { + Self { + industry_id: v.industry_id, + industry_name: v.industry_name, + index: v.index, + index_name: v.index_name, + holding_type: v.holding_type, + holding_type_name: v.holding_type_name, + } + } +} + +/// One element of an ETF asset allocation group +#[pyclass(get_all, skip_from_py_object)] +#[derive(Debug, Clone)] +pub(crate) struct AssetAllocationItem { + /// Element name + pub name: String, + /// Security code (holdings only, e.g. `NVDA`) + pub code: String, + /// Position ratio (e.g. `0.0861114`) + pub position_ratio: String, + /// Security symbol (holdings only, e.g. `NVDA.US`) + pub symbol: String, + /// Localized names (locale → name) + pub name_locales: std::collections::HashMap, + /// Holding detail (holdings only) + pub holding_detail: Option, +} + +impl From for AssetAllocationItem { + fn from(v: lb::AssetAllocationItem) -> Self { + Self { + name: v.name, + code: v.code, + position_ratio: v.position_ratio, + symbol: v.symbol, + name_locales: v.name_locales, + holding_detail: v.holding_detail.map(Into::into), + } + } +} + +/// One ETF asset allocation group (grouped by element type) +#[pyclass(get_all, skip_from_py_object)] +#[derive(Debug, Clone)] +pub(crate) struct AssetAllocationGroup { + /// Report date (e.g. `20260601`) + pub report_date: String, + /// Element type of this group + pub asset_type: ElementType, + /// Elements + pub lists: Vec, +} + +impl From for AssetAllocationGroup { + fn from(v: lb::AssetAllocationGroup) -> Self { + Self { + report_date: v.report_date, + asset_type: v.asset_type.into(), + lists: v.lists.into_iter().map(Into::into).collect(), + } + } +} + +/// ETF asset allocation response +#[pyclass(get_all, skip_from_py_object)] +#[derive(Debug, Clone)] +pub(crate) struct AssetAllocationResponse { + /// Asset allocation groups + pub info: Vec, +} + +impl From for AssetAllocationResponse { + fn from(v: lb::AssetAllocationResponse) -> Self { + Self { + info: v.info.into_iter().map(Into::into).collect(), + } + } +} diff --git a/python/src/quote/context.rs b/python/src/quote/context.rs index 2357ebe78..a2d6f9e1e 100644 --- a/python/src/quote/context.rs +++ b/python/src/quote/context.rs @@ -687,17 +687,4 @@ impl QuoteContext { .map_err(ErrorNewType)? .into()) } - - /// Get ETF asset allocation (holdings / regional / asset class / - /// industry) - fn etf_asset_allocation( - &self, - symbol: String, - ) -> PyResult { - Ok(self - .ctx - .etf_asset_allocation(symbol) - .map_err(ErrorNewType)? - .into()) - } } diff --git a/python/src/quote/context_async.rs b/python/src/quote/context_async.rs index f3637e282..cd5ca44c9 100644 --- a/python/src/quote/context_async.rs +++ b/python/src/quote/context_async.rs @@ -895,19 +895,4 @@ impl AsyncQuoteContext { }) .map(|b| b.unbind()) } - - /// Get ETF asset allocation (holdings / regional / asset class / - /// industry). Returns awaitable. - fn etf_asset_allocation(&self, py: Python<'_>, symbol: String) -> PyResult> { - let ctx = self.ctx.clone(); - pyo3_async_runtimes::tokio::future_into_py(py, async move { - let r: crate::quote::types::AssetAllocationResponse = ctx - .etf_asset_allocation(symbol) - .await - .map_err(ErrorNewType)? - .into(); - Ok(r) - }) - .map(|b| b.unbind()) - } } diff --git a/python/src/quote/mod.rs b/python/src/quote/mod.rs index d69458841..749f0deb0 100644 --- a/python/src/quote/mod.rs +++ b/python/src/quote/mod.rs @@ -71,11 +71,6 @@ pub(crate) fn register_types(parent: &Bound) -> PyResult<()> { parent.add_class::()?; parent.add_class::()?; parent.add_class::()?; - parent.add_class::()?; - parent.add_class::()?; - parent.add_class::()?; - parent.add_class::()?; - parent.add_class::()?; parent.add_class::()?; parent.add_class::()?; diff --git a/python/src/quote/types.rs b/python/src/quote/types.rs index aeb7a5339..d9849dac0 100644 --- a/python/src/quote/types.rs +++ b/python/src/quote/types.rs @@ -1,5 +1,3 @@ -use std::collections::HashMap; - use longbridge::quote::SubFlags; use longbridge_python_macros::{PyEnum, PyObject}; use pyo3::prelude::*; @@ -1623,122 +1621,3 @@ impl From for OptionVolumeDailyStat { } } } - -// ── etf_asset_allocation ────────────────────────────────────────── - -/// ETF asset allocation element type -#[pyclass(eq, eq_int, skip_from_py_object)] -#[derive(PyEnum, Debug, Copy, Clone, Hash, Eq, PartialEq)] -#[py(remote = "longbridge::quote::ElementType")] -pub(crate) enum ElementType { - /// Unknown - Unknown, - /// Holdings - Holdings, - /// Regional - Regional, - /// Asset class - AssetClass, - /// Industry - Industry, -} - -/// Holding detail of an ETF asset allocation element (holdings only) -#[pyclass(get_all, skip_from_py_object)] -#[derive(Debug, Clone)] -pub(crate) struct HoldingDetail { - /// Industry ID - pub industry_id: String, - /// Industry name - pub industry_name: String, - /// Index counter ID (e.g. `BK/US/CP99000`) - pub index: String, - /// Index name - pub index_name: String, - /// Holding type (e.g. `E` for stock) - pub holding_type: String, - /// Holding type name - pub holding_type_name: String, -} - -impl From for HoldingDetail { - fn from(v: longbridge::quote::HoldingDetail) -> Self { - Self { - industry_id: v.industry_id, - industry_name: v.industry_name, - index: v.index, - index_name: v.index_name, - holding_type: v.holding_type, - holding_type_name: v.holding_type_name, - } - } -} - -/// One element of an ETF asset allocation group -#[pyclass(get_all, skip_from_py_object)] -#[derive(Debug, Clone)] -pub(crate) struct AssetAllocationItem { - /// Element name - pub name: String, - /// Security code (holdings only, e.g. `NVDA`) - pub code: String, - /// Position ratio (e.g. `0.0861114`) - pub position_ratio: String, - /// Security symbol (holdings only, e.g. `NVDA.US`) - pub symbol: String, - /// Localized names (locale → name) - pub name_locales: HashMap, - /// Holding detail (holdings only) - pub holding_detail: Option, -} - -impl From for AssetAllocationItem { - fn from(v: longbridge::quote::AssetAllocationItem) -> Self { - Self { - name: v.name, - code: v.code, - position_ratio: v.position_ratio, - symbol: v.symbol, - name_locales: v.name_locales, - holding_detail: v.holding_detail.map(Into::into), - } - } -} - -/// One ETF asset allocation group (grouped by element type) -#[pyclass(get_all, skip_from_py_object)] -#[derive(Debug, Clone)] -pub(crate) struct AssetAllocationGroup { - /// Report date (e.g. `20260601`) - pub report_date: String, - /// Element type of this group - pub asset_type: ElementType, - /// Elements - pub lists: Vec, -} - -impl From for AssetAllocationGroup { - fn from(v: longbridge::quote::AssetAllocationGroup) -> Self { - Self { - report_date: v.report_date, - asset_type: v.asset_type.into(), - lists: v.lists.into_iter().map(Into::into).collect(), - } - } -} - -/// ETF asset allocation response -#[pyclass(get_all, skip_from_py_object)] -#[derive(Debug, Clone)] -pub(crate) struct AssetAllocationResponse { - /// Asset allocation groups - pub info: Vec, -} - -impl From for AssetAllocationResponse { - fn from(v: longbridge::quote::AssetAllocationResponse) -> Self { - Self { - info: v.info.into_iter().map(Into::into).collect(), - } - } -} diff --git a/rust/src/blocking/fundamental.rs b/rust/src/blocking/fundamental.rs index 90b209f48..e2fb48d04 100644 --- a/rust/src/blocking/fundamental.rs +++ b/rust/src/blocking/fundamental.rs @@ -280,4 +280,14 @@ impl FundamentalContextSync { .await }) } + + /// Get ETF asset allocation (holdings / regional / asset class / + /// industry) + pub fn etf_asset_allocation( + &self, + symbol: impl Into + Send + 'static, + ) -> Result { + self.rt + .call(move |ctx| async move { ctx.etf_asset_allocation(symbol).await }) + } } diff --git a/rust/src/blocking/quote.rs b/rust/src/blocking/quote.rs index ba47fe6ab..fbba09273 100644 --- a/rust/src/blocking/quote.rs +++ b/rust/src/blocking/quote.rs @@ -6,8 +6,8 @@ use crate::{ Config, Market, QuoteContext, Result, blocking::runtime::BlockingRuntime, quote::{ - AdjustType, AssetAllocationResponse, CalcIndex, Candlestick, CapitalDistributionResponse, - CapitalFlowLine, FilingItem, FilterWarrantExpiryDate, FilterWarrantInOutBoundsType, + AdjustType, CalcIndex, Candlestick, CapitalDistributionResponse, CapitalFlowLine, + FilingItem, FilterWarrantExpiryDate, FilterWarrantInOutBoundsType, HistoryMarketTemperatureResponse, IntradayLine, IssuerInfo, MarketTemperature, MarketTradingDays, MarketTradingSession, OptionQuote, OptionVolumeDaily, OptionVolumeStats, ParticipantInfo, Period, PinnedMode, PushEvent, QuotePackageDetail, RealtimeQuote, @@ -1213,14 +1213,4 @@ impl QuoteContextSync { self.rt .call(move |ctx| async move { ctx.short_trades(symbol, count).await }) } - - /// Get ETF asset allocation (holdings / regional / asset class / - /// industry) - pub fn etf_asset_allocation( - &self, - symbol: impl Into + Send + 'static, - ) -> Result { - self.rt - .call(move |ctx| async move { ctx.etf_asset_allocation(symbol).await }) - } } diff --git a/rust/src/fundamental/context.rs b/rust/src/fundamental/context.rs index b7c23aff4..a5d9e64b5 100644 --- a/rust/src/fundamental/context.rs +++ b/rust/src/fundamental/context.rs @@ -806,4 +806,27 @@ impl FundamentalContext { .collect(); Ok(ValuationComparisonResponse { list }) } + + // ── etf_asset_allocation ───────────────────────────────────── + + /// Get ETF asset allocation (holdings / regional / asset class / + /// industry). + /// + /// Path: `GET /v1/quote/etf-asset-allocation` + pub async fn etf_asset_allocation( + &self, + symbol: impl Into, + ) -> Result { + #[derive(Serialize)] + struct Query { + counter_id: String, + } + self.get( + "/v1/quote/etf-asset-allocation", + Query { + counter_id: symbol_to_counter_id(&symbol.into()), + }, + ) + .await + } } diff --git a/rust/src/fundamental/types.rs b/rust/src/fundamental/types.rs index bbae2ec51..929f8ce98 100644 --- a/rust/src/fundamental/types.rs +++ b/rust/src/fundamental/types.rs @@ -1,5 +1,8 @@ #![allow(missing_docs)] +use std::collections::HashMap; + +use num_enum::{FromPrimitive, IntoPrimitive}; use rust_decimal::Decimal; use serde::{Deserialize, Serialize}; use strum_macros::{Display, EnumString}; @@ -1454,3 +1457,108 @@ pub enum FinancialReportPeriod { #[serde(rename = "3q")] ThreeQ, } + +// ── etf_asset_allocation ────────────────────────────────────────── + +/// ETF asset allocation element type +#[derive(Debug, FromPrimitive, IntoPrimitive, Copy, Clone, Hash, Eq, PartialEq)] +#[repr(i32)] +pub enum ElementType { + /// Unknown + #[num_enum(default)] + Unknown = 0, + /// Holdings + Holdings = 1, + /// Regional + Regional = 2, + /// Asset class + AssetClass = 3, + /// Industry + Industry = 4, +} + +impl Serialize for ElementType { + fn serialize(&self, serializer: S) -> std::result::Result + where + S: serde::Serializer, + { + serializer.serialize_i32((*self).into()) + } +} + +impl<'de> Deserialize<'de> for ElementType { + fn deserialize(deserializer: D) -> std::result::Result + where + D: serde::Deserializer<'de>, + { + Ok(ElementType::from(i32::deserialize(deserializer)?)) + } +} + +/// Holding detail of an ETF asset allocation element (holdings only) +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct HoldingDetail { + /// Industry ID + #[serde(default)] + pub industry_id: String, + /// Industry name + #[serde(default)] + pub industry_name: String, + /// Index counter ID (e.g. `BK/US/CP99000`) + #[serde(default)] + pub index: String, + /// Index name + #[serde(default)] + pub index_name: String, + /// Holding type (e.g. `E` for stock) + #[serde(default)] + pub holding_type: String, + /// Holding type name + #[serde(default)] + pub holding_type_name: String, +} + +/// One element of an ETF asset allocation group +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct AssetAllocationItem { + /// Element name + pub name: String, + /// Security code (holdings only, e.g. `NVDA`) + #[serde(default)] + pub code: String, + /// Position ratio (e.g. `0.0861114`) + pub position_ratio: String, + /// Security symbol (holdings only, e.g. `NVDA.US`) + #[serde( + rename = "counter_id", + deserialize_with = "deserialize_counter_id_as_symbol", + default + )] + pub symbol: String, + /// Localized names (locale → name, e.g. `zh-CN` → `英伟达`) + #[serde(rename = "name_locales_map", default)] + pub name_locales: HashMap, + /// Holding detail (holdings only) + #[serde(default)] + pub holding_detail: Option, +} + +/// One ETF asset allocation group (grouped by element type) +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct AssetAllocationGroup { + /// Report date (e.g. `20260601`) + pub report_date: String, + /// Element type of this group + pub asset_type: ElementType, + /// Elements + #[serde(default)] + pub lists: Vec, +} + +/// Response for [`crate::FundamentalContext::etf_asset_allocation`] +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct AssetAllocationResponse { + /// Asset allocation groups + #[serde(default)] + pub info: Vec, +} diff --git a/rust/src/quote/context.rs b/rust/src/quote/context.rs index 916a41a7e..168525c95 100644 --- a/rust/src/quote/context.rs +++ b/rust/src/quote/context.rs @@ -14,10 +14,10 @@ use tracing::{Subscriber, dispatcher, instrument::WithSubscriber}; use crate::{ Config, Error, Language, Market, Result, quote::{ - AdjustType, AssetAllocationResponse, CalcIndex, Candlestick, CapitalDistributionResponse, - CapitalFlowLine, FilingItem, HistoryMarketTemperatureResponse, IntradayLine, IssuerInfo, - MarketTemperature, MarketTradingDays, MarketTradingSession, OptionQuote, OptionVolumeDaily, - OptionVolumeStats, ParticipantInfo, Period, PushEvent, QuotePackageDetail, RealtimeQuote, + AdjustType, CalcIndex, Candlestick, CapitalDistributionResponse, CapitalFlowLine, + FilingItem, HistoryMarketTemperatureResponse, IntradayLine, IssuerInfo, MarketTemperature, + MarketTradingDays, MarketTradingSession, OptionQuote, OptionVolumeDaily, OptionVolumeStats, + ParticipantInfo, Period, PushEvent, QuotePackageDetail, RealtimeQuote, RequestCreateWatchlistGroup, RequestUpdateWatchlistGroup, Security, SecurityBrokers, SecurityCalcIndex, SecurityDepth, SecurityListCategory, SecurityQuote, SecurityStaticInfo, ShortPositionsItem, ShortPositionsResponse, ShortTradesItem, ShortTradesResponse, @@ -2198,35 +2198,6 @@ impl QuoteContext { Ok(()) } - - // ── etf_asset_allocation ────────────────────────────────────── - - /// Get ETF asset allocation (holdings / regional / asset class / - /// industry). - /// - /// Path: `GET /v1/quote/etf-asset-allocation` - pub async fn etf_asset_allocation( - &self, - symbol: impl Into, - ) -> Result { - use crate::utils::counter::symbol_to_counter_id; - #[derive(serde::Serialize)] - struct Query { - counter_id: String, - } - let resp = self - .0 - .http_cli - .request(Method::GET, "/v1/quote/etf-asset-allocation") - .query_params(Query { - counter_id: symbol_to_counter_id(&symbol.into()), - }) - .response::>() - .send() - .with_subscriber(self.0.log_subscriber.clone()) - .await?; - Ok(resp.0) - } } fn normalize_symbol(symbol: &str) -> &str { diff --git a/rust/src/quote/mod.rs b/rust/src/quote/mod.rs index 6f91193fc..78dcba0cb 100644 --- a/rust/src/quote/mod.rs +++ b/rust/src/quote/mod.rs @@ -17,9 +17,6 @@ pub use push_types::{ }; pub use sub_flags::SubFlags; pub use types::{ - AssetAllocationGroup, - AssetAllocationItem, - AssetAllocationResponse, Brokers, CalcIndex, Candlestick, @@ -28,13 +25,11 @@ pub use types::{ CapitalFlowLine, Depth, DerivativeType, - ElementType, FilingItem, FilterWarrantExpiryDate, FilterWarrantInOutBoundsType, Granularity, HistoryMarketTemperatureResponse, - HoldingDetail, IntradayLine, IssuerInfo, MarketTemperature, diff --git a/rust/src/quote/types.rs b/rust/src/quote/types.rs index 3407b1a62..08df9b007 100644 --- a/rust/src/quote/types.rs +++ b/rust/src/quote/types.rs @@ -1,5 +1,3 @@ -use std::collections::HashMap; - use longbridge_candlesticks::CandlestickComponents; use longbridge_proto::quote::{self, Period, TradeStatus}; use num_enum::{FromPrimitive, IntoPrimitive, TryFromPrimitive}; @@ -2166,111 +2164,6 @@ pub enum PinnedMode { Remove, } -// ── etf_asset_allocation ────────────────────────────────────────── - -/// ETF asset allocation element type -#[derive(Debug, FromPrimitive, IntoPrimitive, Copy, Clone, Hash, Eq, PartialEq)] -#[repr(i32)] -pub enum ElementType { - /// Unknown - #[num_enum(default)] - Unknown = 0, - /// Holdings - Holdings = 1, - /// Regional - Regional = 2, - /// Asset class - AssetClass = 3, - /// Industry - Industry = 4, -} - -impl Serialize for ElementType { - fn serialize(&self, serializer: S) -> std::result::Result - where - S: serde::Serializer, - { - serializer.serialize_i32((*self).into()) - } -} - -impl<'de> Deserialize<'de> for ElementType { - fn deserialize(deserializer: D) -> std::result::Result - where - D: serde::Deserializer<'de>, - { - Ok(ElementType::from(i32::deserialize(deserializer)?)) - } -} - -/// Holding detail of an ETF asset allocation element (holdings only) -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct HoldingDetail { - /// Industry ID - #[serde(default)] - pub industry_id: String, - /// Industry name - #[serde(default)] - pub industry_name: String, - /// Index counter ID (e.g. `BK/US/CP99000`) - #[serde(default)] - pub index: String, - /// Index name - #[serde(default)] - pub index_name: String, - /// Holding type (e.g. `E` for stock) - #[serde(default)] - pub holding_type: String, - /// Holding type name - #[serde(default)] - pub holding_type_name: String, -} - -/// One element of an ETF asset allocation group -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct AssetAllocationItem { - /// Element name - pub name: String, - /// Security code (holdings only, e.g. `NVDA`) - #[serde(default)] - pub code: String, - /// Position ratio (e.g. `0.0861114`) - pub position_ratio: String, - /// Security symbol (holdings only, e.g. `NVDA.US`) - #[serde( - rename = "counter_id", - deserialize_with = "crate::utils::counter::deserialize_counter_id_as_symbol", - default - )] - pub symbol: String, - /// Localized names (locale → name, e.g. `zh-CN` → `英伟达`) - #[serde(rename = "name_locales_map", default)] - pub name_locales: HashMap, - /// Holding detail (holdings only) - #[serde(default)] - pub holding_detail: Option, -} - -/// One ETF asset allocation group (grouped by element type) -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct AssetAllocationGroup { - /// Report date (e.g. `20260601`) - pub report_date: String, - /// Element type of this group - pub asset_type: ElementType, - /// Elements - #[serde(default)] - pub lists: Vec, -} - -/// Response for [`crate::QuoteContext::etf_asset_allocation`] -#[derive(Debug, Clone, Serialize, Deserialize)] -pub struct AssetAllocationResponse { - /// Asset allocation groups - #[serde(default)] - pub info: Vec, -} - #[cfg(test)] mod tests { use serde::Deserialize; From 89e44368eba0d1ba107fd98d5988ab3a2ee0e7ec Mon Sep 17 00:00:00 2001 From: Jason Lee Date: Thu, 4 Jun 2026 14:45:49 +0800 Subject: [PATCH 19/26] feat: full counter_id directory + public counter module (#537) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary 1. **Refresh & extend the embedded counter directories** (from the instrument-management export): - `US-ETF.csv`: 4574 → 7250 entries (drops 14 misclassified non-ETF entries) - New `US-IX.csv` (648 index entries) and `US-WT.csv` (17693 warrant entries) 2. **Reimplement `symbol_to_counter_id`** with the complete special-set lookup: ETF + IX + WT directories, leading-dot US indexes (`.DJI.US` → `IX/US/.DJI`), HK leading-zero stripping (`00700.HK` → `ST/HK/700`; A-share codes keep zeros: `000001.SZ` → `ST/SZ/000001`) 3. **Expose the public `longbridge::counter` module** — `symbol_to_counter_id` / `index_symbol_to_counter_id` / `counter_id_to_symbol` / `is_etf` — so downstream consumers (CLI / MCP) can drop their own copies of this logic and data ## Why The outdated embedded ETF dictionary caused newer ETFs (e.g. `DRAM.US`) to resolve to `ST/US/DRAM` instead of `ETF/US/DRAM`, breaking ETF-specific APIs like `etf_asset_allocation`. Centralizing the full directory + conversion in the SDK keeps CLI / MCP / SDK behavior consistent. ## Verification - `cargo test -p longbridge --lib utils::counter`: 22 passed (ported from the CLI's test suite + A-share leading-zero case) - `cargo clippy --all --all-features`: clean - Verified end-to-end against staging via the CLI: `constituent DRAM.US` returns all allocation groups 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.8 (1M context) --- CHANGELOG.md | 9 + rust/src/lib.rs | 2 + rust/src/utils/US-ETF.csv | 2704 +++++- rust/src/utils/US-IX.csv | 648 ++ rust/src/utils/US-WT.csv | 17693 ++++++++++++++++++++++++++++++++++++ rust/src/utils/counter.rs | 178 +- rust/src/utils/mod.rs | 2 +- 7 files changed, 21201 insertions(+), 35 deletions(-) create mode 100644 rust/src/utils/US-IX.csv create mode 100644 rust/src/utils/US-WT.csv diff --git a/CHANGELOG.md b/CHANGELOG.md index 415603edb..7715d3a56 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - **All languages:** `FundamentalContext` gains `etf_asset_allocation(symbol)` — queries `GET /v1/quote/etf-asset-allocation` for ETF asset allocation grouped by element type (`Holdings` / `Regional` / `AssetClass` / `Industry`); returns `AssetAllocationResponse` with report date, position ratios, localized names, and per-holding detail +- **Rust:** new public `longbridge::counter` module — `symbol_to_counter_id`, `index_symbol_to_counter_id`, `counter_id_to_symbol`, and `is_etf`, backed by the embedded ETF + index + warrant directory, so downstream consumers (CLI / MCP) no longer need their own copies + +### Changed + +- `symbol_to_counter_id` now also consults the embedded index and warrant directories — e.g. `HSI.HK` → `IX/HK/HSI`, `10005.HK` → `WT/HK/10005`; leading zeros are stripped from numeric `.HK` codes (`00700.HK` → `ST/HK/700`, A-share codes are kept verbatim) + +### Fixed + +- Refreshed the embedded US ETF list (4574 → 7250 entries, from the instrument-management export) and added index (648) + warrant (17693) directories — newer ETFs (e.g. `DRAM.US`) were resolved to `ST/...` instead of `ETF/...` counter IDs, breaking ETF-specific APIs such as `etf_asset_allocation` ## [4.2.2] diff --git a/rust/src/lib.rs b/rust/src/lib.rs index a69999d3c..df996bbd3 100644 --- a/rust/src/lib.rs +++ b/rust/src/lib.rs @@ -16,6 +16,8 @@ mod serde_utils; mod types; mod utils; +pub use utils::counter; + #[cfg(feature = "blocking")] #[cfg_attr(docsrs, doc(cfg(feature = "blocking")))] pub mod blocking; diff --git a/rust/src/utils/US-ETF.csv b/rust/src/utils/US-ETF.csv index 72b2d0ab1..887c9471c 100644 --- a/rust/src/utils/US-ETF.csv +++ b/rust/src/utils/US-ETF.csv @@ -1,6 +1,18 @@ +ETF/US/25460G187 +ETF/US/2581803D +ETF/US/74347G143 +ETF/US/86172B882 +ETF/US/88636W247 ETF/US/AAA +ETF/US/AAAA +ETF/US/AAAC +ETF/US/AAAD ETF/US/AAAU ETF/US/AADR +ETF/US/AAEQ +ETF/US/AALG +ETF/US/AAOG +ETF/US/AAOX ETF/US/AAPB ETF/US/AAPD ETF/US/AAPR @@ -8,123 +20,218 @@ ETF/US/AAPU ETF/US/AAPW ETF/US/AAPX ETF/US/AAPY +ETF/US/AAUA +ETF/US/AAUM +ETF/US/AAUS ETF/US/AAVM ETF/US/AAXJ ETF/US/ABCS ETF/US/ABEQ ETF/US/ABFL ETF/US/ABHY +ETF/US/ABI +ETF/US/ABIG ETF/US/ABLD ETF/US/ABLG ETF/US/ABLS +ETF/US/ABNG ETF/US/ABNY ETF/US/ABOT +ETF/US/ABUF +ETF/US/ABXB +ETF/US/ACEI +ETF/US/ACEP ETF/US/ACES +ETF/US/ACGO ETF/US/ACGR +ETF/US/ACII +ETF/US/ACIM ETF/US/ACIO +ETF/US/ACKY ETF/US/ACLC ETF/US/ACLO ETF/US/ACP +ETF/US/ACSG ETF/US/ACSI +ETF/US/ACSV +ETF/US/ACT +ETF/US/ACTS ETF/US/ACTV ETF/US/ACV ETF/US/ACVF +ETF/US/ACVT +ETF/US/ACVU ETF/US/ACWI ETF/US/ACWV ETF/US/ACWX +ETF/US/ACYN +ETF/US/ACYS ETF/US/ADBG +ETF/US/ADBU +ETF/US/ADDS ETF/US/ADFI ETF/US/ADIV ETF/US/ADME ETF/US/ADPV +ETF/US/ADRA +ETF/US/ADRD +ETF/US/ADRE +ETF/US/ADRU ETF/US/ADVE ETF/US/ADX ETF/US/AEF +ETF/US/AEMB +ETF/US/AEMS ETF/US/AESR ETF/US/AETH ETF/US/AFB +ETF/US/AFGR ETF/US/AFIF ETF/US/AFIX ETF/US/AFK ETF/US/AFLG ETF/US/AFMC +ETF/US/AFOS +ETF/US/AFRU ETF/US/AFSC ETF/US/AFSM +ETF/US/AFT +ETF/US/AFTY ETF/US/AGD ETF/US/AGEM ETF/US/AGG +ETF/US/AGGA +ETF/US/AGGE ETF/US/AGGH +ETF/US/AGGP ETF/US/AGGS ETF/US/AGGY ETF/US/AGIH +ETF/US/AGIQ ETF/US/AGIX ETF/US/AGMI +ETF/US/AGND ETF/US/AGNG +ETF/US/AGOV ETF/US/AGOX ETF/US/AGQ ETF/US/AGQI ETF/US/AGRH ETF/US/AGRW +ETF/US/AGT ETF/US/AGZ ETF/US/AGZD +ETF/US/AHD +ETF/US/AHHX ETF/US/AHLT ETF/US/AHOY ETF/US/AHYB ETF/US/AIA ETF/US/AIBD ETF/US/AIBU +ETF/US/AIDB ETF/US/AIEQ +ETF/US/AIF ETF/US/AIFD +ETF/US/AIIQ +ETF/US/AILG +ETF/US/AILV +ETF/US/AIMS ETF/US/AINP +ETF/US/AINT +ETF/US/AINV +ETF/US/AIOO ETF/US/AIPI +ETF/US/AIPO ETF/US/AIQ +ETF/US/AIQD +ETF/US/AIQU ETF/US/AIRL ETF/US/AIRR ETF/US/AIS +ETF/US/AIUP ETF/US/AIVC ETF/US/AIVI ETF/US/AIVL ETF/US/AIYY ETF/US/AJAN ETF/US/AJUL +ETF/US/AKAF +ETF/US/AKRE ETF/US/ALAI +ETF/US/ALBG +ETF/US/ALDB +ETF/US/ALFA +ETF/US/ALIL ETF/US/ALLW +ETF/US/ALRG ETF/US/ALTL +ETF/US/ALTS ETF/US/ALTY +ETF/US/ALUM +ETF/US/AMA +ETF/US/AMAU +ETF/US/AMCA ETF/US/AMDD ETF/US/AMDG ETF/US/AMDL ETF/US/AMDS +ETF/US/AMDU +ETF/US/AMDW ETF/US/AMDY +ETF/US/AMER +ETF/US/AMJ ETF/US/AMJB +ETF/US/AMJL +ETF/US/AMKL ETF/US/AMLP +ETF/US/AMNA +ETF/US/AMND ETF/US/AMOM ETF/US/AMPD +ETF/US/AMPU +ETF/US/AMTR +ETF/US/AMU ETF/US/AMUB +ETF/US/AMUN ETF/US/AMUU +ETF/US/AMYY ETF/US/AMZA ETF/US/AMZD +ETF/US/AMZO ETF/US/AMZP ETF/US/AMZU +ETF/US/AMZW ETF/US/AMZY ETF/US/AMZZ +ETF/US/AND +ETF/US/ANEL ETF/US/ANEW ETF/US/ANGL +ETF/US/ANV ETF/US/AOA ETF/US/AOCT ETF/US/AOD ETF/US/AOHY +ETF/US/AOIL ETF/US/AOK ETF/US/AOM ETF/US/AOR ETF/US/AOTG +ETF/US/AOTS ETF/US/APCB +ETF/US/APDB ETF/US/APED +ETF/US/APHU ETF/US/APIE ETF/US/APLU +ETF/US/APLX ETF/US/APLY +ETF/US/APLZ ETF/US/APMU ETF/US/APOC +ETF/US/APPX +ETF/US/APRB ETF/US/APRD ETF/US/APRH ETF/US/APRJ @@ -134,10 +241,15 @@ ETF/US/APRT ETF/US/APRW ETF/US/APRZ ETF/US/APUE +ETF/US/APXH +ETF/US/APXM +ETF/US/AQEC +ETF/US/AQGX ETF/US/AQLT ETF/US/AQWA ETF/US/ARB ETF/US/ARCM +ETF/US/ARCX ETF/US/ARDC ETF/US/AREA ETF/US/ARGT @@ -147,31 +259,56 @@ ETF/US/ARKC ETF/US/ARKD ETF/US/ARKF ETF/US/ARKG +ETF/US/ARKI ETF/US/ARKK ETF/US/ARKQ +ETF/US/ARKT ETF/US/ARKW ETF/US/ARKX ETF/US/ARKY ETF/US/ARKZ +ETF/US/ARLI ETF/US/ARLU ETF/US/ARMG ETF/US/ARMH +ETF/US/ARMR ETF/US/ARMU +ETF/US/ARMW +ETF/US/ARMY ETF/US/ARP ETF/US/ARTY ETF/US/ARVR +ETF/US/ARWG ETF/US/ASA +ETF/US/ASCE +ETF/US/ASCI +ETF/US/ASD ETF/US/ASEA +ETF/US/ASEC ETF/US/ASET ETF/US/ASG ETF/US/ASGI +ETF/US/ASGM ETF/US/ASHR ETF/US/ASHS +ETF/US/ASHX ETF/US/ASLV ETF/US/ASMF ETF/US/ASMG ETF/US/ASMH +ETF/US/ASMU +ETF/US/ASPY +ETF/US/ASTN +ETF/US/ASTX +ETF/US/ASTY +ETF/US/ASUP +ETF/US/ATC +ETF/US/ATCL ETF/US/ATMP +ETF/US/ATTR +ETF/US/ATY +ETF/US/AUAU +ETF/US/AUD ETF/US/AUGM ETF/US/AUGP ETF/US/AUGT @@ -179,15 +316,25 @@ ETF/US/AUGU ETF/US/AUGW ETF/US/AUGZ ETF/US/AUMI +ETF/US/AURU ETF/US/AUSF +ETF/US/AUSM +ETF/US/AV +ETF/US/AVAZ ETF/US/AVDE +ETF/US/AVDG +ETF/US/AVDR ETF/US/AVDS ETF/US/AVDV ETF/US/AVEE ETF/US/AVEM ETF/US/AVES +ETF/US/AVGB ETF/US/AVGE +ETF/US/AVGG +ETF/US/AVGU ETF/US/AVGV +ETF/US/AVGW ETF/US/AVGX ETF/US/AVIE ETF/US/AVIG @@ -202,29 +349,67 @@ ETF/US/AVMU ETF/US/AVMV ETF/US/AVNM ETF/US/AVNV +ETF/US/AVOS ETF/US/AVRE +ETF/US/AVRY ETF/US/AVS ETF/US/AVSC ETF/US/AVSD ETF/US/AVSE ETF/US/AVSF ETF/US/AVSU +ETF/US/AVTM ETF/US/AVUQ ETF/US/AVUS ETF/US/AVUV ETF/US/AVXC +ETF/US/AVXX ETF/US/AWAY ETF/US/AWEG ETF/US/AWF ETF/US/AWP +ETF/US/AWTM +ETF/US/AWYX +ETF/US/AXEN +ETF/US/AXFN +ETF/US/AXHE +ETF/US/AXID +ETF/US/AXIT +ETF/US/AXJL +ETF/US/AXJV +ETF/US/AXMT +ETF/US/AXPG +ETF/US/AXSL +ETF/US/AXTE +ETF/US/AXTU +ETF/US/AXTX +ETF/US/AXUP +ETF/US/AXUT +ETF/US/AZAA +ETF/US/AZAJ +ETF/US/AZAL +ETF/US/AZAO +ETF/US/AZBA +ETF/US/AZBJ +ETF/US/AZBL +ETF/US/AZBO ETF/US/AZNH ETF/US/AZTD +ETF/US/AZYY ETF/US/BAB ETF/US/BABO +ETF/US/BABU +ETF/US/BABW ETF/US/BABX +ETF/US/BAD ETF/US/BAFE +ETF/US/BAGY ETF/US/BAI +ETF/US/BAIG +ETF/US/BAIV +ETF/US/BAL ETF/US/BALI +ETF/US/BALQ ETF/US/BALT ETF/US/BAMA ETF/US/BAMB @@ -236,10 +421,15 @@ ETF/US/BAMV ETF/US/BAMY ETF/US/BAPR ETF/US/BAR +ETF/US/BASG +ETF/US/BASV ETF/US/BATT ETF/US/BAUG +ETF/US/BAVA +ETF/US/BAY ETF/US/BBAG ETF/US/BBAX +ETF/US/BBB ETF/US/BBBI ETF/US/BBBL ETF/US/BBBS @@ -249,60 +439,106 @@ ETF/US/BBCB ETF/US/BBEM ETF/US/BBEU ETF/US/BBH +ETF/US/BBHL +ETF/US/BBHM ETF/US/BBHY ETF/US/BBIB ETF/US/BBIN ETF/US/BBIP ETF/US/BBJP +ETF/US/BBK ETF/US/BBLB ETF/US/BBLU ETF/US/BBMC ETF/US/BBN ETF/US/BBP ETF/US/BBRE +ETF/US/BBSA ETF/US/BBSB ETF/US/BBSC ETF/US/BBUS +ETF/US/BBYY ETF/US/BCAT +ETF/US/BCCC ETF/US/BCD ETF/US/BCDF +ETF/US/BCEM +ETF/US/BCFN +ETF/US/BCGD +ETF/US/BCGS ETF/US/BCHI ETF/US/BCHP ETF/US/BCI ETF/US/BCIL ETF/US/BCIM +ETF/US/BCKT ETF/US/BCLO +ETF/US/BCM +ETF/US/BCNA +ETF/US/BCOR +ETF/US/BCPL +ETF/US/BCSM +ETF/US/BCTK ETF/US/BCUS ETF/US/BCV ETF/US/BCX +ETF/US/BDBT +ETF/US/BDCL +ETF/US/BDCS ETF/US/BDCX +ETF/US/BDCY ETF/US/BDCZ ETF/US/BDEC ETF/US/BDGS ETF/US/BDIV ETF/US/BDRY ETF/US/BDVG +ETF/US/BDVL +ETF/US/BDYN +ETF/US/BECO +ETF/US/BEDY ETF/US/BEDZ ETF/US/BEEX ETF/US/BEEZ +ETF/US/BEG ETF/US/BEGS ETF/US/BELT ETF/US/BEMB ETF/US/BENJ ETF/US/BERZ +ETF/US/BESF +ETF/US/BESO ETF/US/BETE ETF/US/BETH ETF/US/BETZ +ETF/US/BEX +ETF/US/BEZ ETF/US/BFAP ETF/US/BFEB +ETF/US/BFEW +ETF/US/BFIT ETF/US/BFIX +ETF/US/BFJA +ETF/US/BFJL ETF/US/BFK +ETF/US/BFLB +ETF/US/BFLX +ETF/US/BFOC ETF/US/BFOR ETF/US/BFRE +ETF/US/BFRZ +ETF/US/BFTR +ETF/US/BFXU +ETF/US/BFY ETF/US/BGB +ETF/US/BGCG ETF/US/BGDV +ETF/US/BGEG +ETF/US/BGGG ETF/US/BGH +ETF/US/BGIA ETF/US/BGIG +ETF/US/BGIO ETF/US/BGLD ETF/US/BGR ETF/US/BGRN @@ -310,33 +546,46 @@ ETF/US/BGRO ETF/US/BGT ETF/US/BGX ETF/US/BGY +ETF/US/BHDG ETF/US/BHK ETF/US/BHV ETF/US/BHYB +ETF/US/BHYP ETF/US/BIB ETF/US/BIBL +ETF/US/BICK ETF/US/BIDD +ETF/US/BIDG +ETF/US/BIDS +ETF/US/BIF +ETF/US/BIGB ETF/US/BIGY ETF/US/BIGZ ETF/US/BIL ETF/US/BILD ETF/US/BILS +ETF/US/BILT ETF/US/BILZ ETF/US/BINC +ETF/US/BINT ETF/US/BINV +ETF/US/BIOY ETF/US/BIS ETF/US/BIT ETF/US/BITB ETF/US/BITC +ETF/US/BITK ETF/US/BITO ETF/US/BITQ ETF/US/BITU ETF/US/BITW ETF/US/BITX +ETF/US/BITY ETF/US/BIV ETF/US/BIZD ETF/US/BJAN ETF/US/BJK +ETF/US/BJU ETF/US/BJUL ETF/US/BJUN ETF/US/BKAG @@ -345,28 +594,48 @@ ETF/US/BKCH ETF/US/BKCI ETF/US/BKDV ETF/US/BKEM +ETF/US/BKES ETF/US/BKF +ETF/US/BKFI ETF/US/BKGI ETF/US/BKHY ETF/US/BKIE +ETF/US/BKIS ETF/US/BKIV +ETF/US/BKK ETF/US/BKLC ETF/US/BKLN ETF/US/BKMC +ETF/US/BKMI +ETF/US/BKMS ETF/US/BKN +ETF/US/BKNU +ETF/US/BKSB ETF/US/BKSE ETF/US/BKT ETF/US/BKUI +ETF/US/BKUS ETF/US/BKWO +ETF/US/BLCK ETF/US/BLCN ETF/US/BLCR ETF/US/BLCV ETF/US/BLDG +ETF/US/BLDX ETF/US/BLE ETF/US/BLES +ETF/US/BLGR ETF/US/BLKC ETF/US/BLLD ETF/US/BLOK +ETF/US/BLOX +ETF/US/BLSG +ETF/US/BLST +ETF/US/BLSX +ETF/US/BLTD +ETF/US/BLUC +ETF/US/BLUI +ETF/US/BLUX ETF/US/BLV ETF/US/BLW ETF/US/BMAR @@ -375,26 +644,41 @@ ETF/US/BMAY ETF/US/BMDL ETF/US/BME ETF/US/BMED +ETF/US/BMLP ETF/US/BMN +ETF/US/BMNG +ETF/US/BMNU +ETF/US/BMNZ +ETF/US/BMOP ETF/US/BMVP ETF/US/BND ETF/US/BNDC ETF/US/BNDD ETF/US/BNDI +ETF/US/BNDP ETF/US/BNDS ETF/US/BNDW ETF/US/BNDX +ETF/US/BNDY +ETF/US/BNE ETF/US/BNGE ETF/US/BNKD +ETF/US/BNKO ETF/US/BNKU +ETF/US/BNKZ ETF/US/BNO ETF/US/BNOV -ETF/US/BNY ETF/US/BOAT +ETF/US/BOB +ETF/US/BOBP ETF/US/BOCT ETF/US/BOE +ETF/US/BOED +ETF/US/BOEG +ETF/US/BOEU ETF/US/BOIL ETF/US/BOND +ETF/US/BOSS ETF/US/BOTT ETF/US/BOTZ ETF/US/BOUT @@ -403,18 +687,42 @@ ETF/US/BOXX ETF/US/BPAY ETF/US/BPH ETF/US/BPI +ETF/US/BPRE +ETF/US/BPRO ETF/US/BRAZ +ETF/US/BRCE +ETF/US/BREE +ETF/US/BREM +ETF/US/BRES +ETF/US/BREW ETF/US/BRF ETF/US/BRHY +ETF/US/BRIB +ETF/US/BRIE ETF/US/BRIF +ETF/US/BRKC ETF/US/BRKD ETF/US/BRKU +ETF/US/BRKW +ETF/US/BRKY ETF/US/BRLN ETF/US/BRNY +ETF/US/BROL ETF/US/BRRR ETF/US/BRTR ETF/US/BRW ETF/US/BRZU +ETF/US/BRZX +ETF/US/BSAE +ETF/US/BSBE +ETF/US/BSCC +ETF/US/BSCD +ETF/US/BSCE +ETF/US/BSCJ +ETF/US/BSCK +ETF/US/BSCL +ETF/US/BSCM +ETF/US/BSCO ETF/US/BSCP ETF/US/BSCQ ETF/US/BSCR @@ -425,7 +733,17 @@ ETF/US/BSCV ETF/US/BSCW ETF/US/BSCX ETF/US/BSCY +ETF/US/BSCZ +ETF/US/BSD +ETF/US/BSDE +ETF/US/BSE +ETF/US/BSEA ETF/US/BSEP +ETF/US/BSJJ +ETF/US/BSJK +ETF/US/BSJL +ETF/US/BSJM +ETF/US/BSJN ETF/US/BSJO ETF/US/BSJP ETF/US/BSJQ @@ -435,8 +753,13 @@ ETF/US/BSJT ETF/US/BSJU ETF/US/BSJV ETF/US/BSJW +ETF/US/BSJX ETF/US/BSL ETF/US/BSMC +ETF/US/BSML +ETF/US/BSMM +ETF/US/BSMN +ETF/US/BSMO ETF/US/BSMP ETF/US/BSMQ ETF/US/BSMR @@ -446,6 +769,8 @@ ETF/US/BSMU ETF/US/BSMV ETF/US/BSMW ETF/US/BSMY +ETF/US/BSMZ +ETF/US/BSOL ETF/US/BSR ETF/US/BSSX ETF/US/BST @@ -454,27 +779,43 @@ ETF/US/BSV ETF/US/BSVO ETF/US/BTA ETF/US/BTAL +ETF/US/BTC ETF/US/BTCC ETF/US/BTCI +ETF/US/BTCK ETF/US/BTCL ETF/US/BTCO +ETF/US/BTCR +ETF/US/BTCU ETF/US/BTCW ETF/US/BTCZ +ETF/US/BTEC +ETF/US/BTEK ETF/US/BTF +ETF/US/BTFD +ETF/US/BTFL ETF/US/BTFX ETF/US/BTGD +ETF/US/BTHM ETF/US/BTO ETF/US/BTOP +ETF/US/BTOT ETF/US/BTR ETF/US/BTRN ETF/US/BTT +ETF/US/BTYB +ETF/US/BTYS ETF/US/BTZ +ETF/US/BU ETF/US/BUCK +ETF/US/BUDX ETF/US/BUFB ETF/US/BUFC ETF/US/BUFD +ETF/US/BUFE ETF/US/BUFF ETF/US/BUFG +ETF/US/BUFH ETF/US/BUFI ETF/US/BUFM ETF/US/BUFP @@ -482,44 +823,64 @@ ETF/US/BUFQ ETF/US/BUFR ETF/US/BUFS ETF/US/BUFT +ETF/US/BUFX ETF/US/BUFY ETF/US/BUFZ ETF/US/BUG ETF/US/BUI ETF/US/BUL ETF/US/BULD +ETF/US/BULG +ETF/US/BULU +ETF/US/BULX ETF/US/BULZ ETF/US/BUSA ETF/US/BUXX +ETF/US/BUY +ETF/US/BUYB +ETF/US/BUYN ETF/US/BUYO ETF/US/BUYW ETF/US/BUYZ ETF/US/BUZZ +ETF/US/BVAL ETF/US/BWEB ETF/US/BWET ETF/US/BWG +ETF/US/BWOW ETF/US/BWTG ETF/US/BWX ETF/US/BWZ ETF/US/BXMX -ETF/US/BXSL ETF/US/BYLD ETF/US/BYM +ETF/US/BYOB ETF/US/BYRE +ETF/US/BYTE +ETF/US/BZM ETF/US/BZQ +ETF/US/BZZ ETF/US/CA ETF/US/CAAA +ETF/US/CABZ +ETF/US/CACG ETF/US/CAF ETF/US/CAFG ETF/US/CAFX +ETF/US/CAGE +ETF/US/CAIE +ETF/US/CAIQ ETF/US/CALF ETF/US/CALI +ETF/US/CALY +ETF/US/CAM ETF/US/CAML ETF/US/CAMX ETF/US/CANC ETF/US/CANE ETF/US/CANQ ETF/US/CAOS +ETF/US/CAPD ETF/US/CAPE ETF/US/CARD ETF/US/CARK @@ -528,37 +889,75 @@ ETF/US/CARZ ETF/US/CAS ETF/US/CATF ETF/US/CATH +ETF/US/CBH ETF/US/CBLS +ETF/US/CBND +ETF/US/CBOA ETF/US/CBOJ +ETF/US/CBOL ETF/US/CBON +ETF/US/CBOO +ETF/US/CBOT +ETF/US/CBOX +ETF/US/CBOY +ETF/US/CBRG +ETF/US/CBRX +ETF/US/CBRZ ETF/US/CBSE +ETF/US/CBTA +ETF/US/CBTG ETF/US/CBTJ +ETF/US/CBTL +ETF/US/CBTO +ETF/US/CBTY +ETF/US/CBXA ETF/US/CBXJ +ETF/US/CBXL +ETF/US/CBXO +ETF/US/CBXY ETF/US/CCD ETF/US/CCEF +ETF/US/CCFE ETF/US/CCIF ETF/US/CCMG ETF/US/CCNR +ETF/US/CCOM +ETF/US/CCON ETF/US/CCOR +ETF/US/CCPX +ETF/US/CCRP ETF/US/CCRV ETF/US/CCSB ETF/US/CCSO +ETF/US/CCUP ETF/US/CDC ETF/US/CDEI +ETF/US/CDIG ETF/US/CDL ETF/US/CEE ETF/US/CEF ETF/US/CEFA ETF/US/CEFD +ETF/US/CEFL ETF/US/CEFS +ETF/US/CEFZ +ETF/US/CEGX +ETF/US/CELT +ETF/US/CEM ETF/US/CEMB +ETF/US/CEN ETF/US/CEPI ETF/US/CERY ETF/US/CET +ETF/US/CETF ETF/US/CETH ETF/US/CEV ETF/US/CEW +ETF/US/CEY +ETF/US/CEZ ETF/US/CFA +ETF/US/CFCV +ETF/US/CFGE ETF/US/CFIT ETF/US/CFO ETF/US/CGBL @@ -568,9 +967,11 @@ ETF/US/CGCV ETF/US/CGDG ETF/US/CGDV ETF/US/CGGE +ETF/US/CGGG ETF/US/CGGO ETF/US/CGGR ETF/US/CGHM +ETF/US/CGHY ETF/US/CGIB ETF/US/CGIC ETF/US/CGIE @@ -585,78 +986,154 @@ ETF/US/CGSM ETF/US/CGUI ETF/US/CGUS ETF/US/CGV +ETF/US/CGVV ETF/US/CGW ETF/US/CGXU +ETF/US/CHAD +ETF/US/CHAI ETF/US/CHAT ETF/US/CHAU +ETF/US/CHB +ETF/US/CHEP ETF/US/CHGX ETF/US/CHI +ETF/US/CHIC +ETF/US/CHIE +ETF/US/CHIH +ETF/US/CHII +ETF/US/CHIK +ETF/US/CHIL +ETF/US/CHIM ETF/US/CHIQ +ETF/US/CHIR +ETF/US/CHIS +ETF/US/CHIU +ETF/US/CHIX +ETF/US/CHLD ETF/US/CHN +ETF/US/CHNA +ETF/US/CHNL +ETF/US/CHNU ETF/US/CHPS +ETF/US/CHPX +ETF/US/CHPY +ETF/US/CHRG +ETF/US/CHRI ETF/US/CHW ETF/US/CHY ETF/US/CIBR +ETF/US/CID +ETF/US/CIEG ETF/US/CIF -ETF/US/CII +ETF/US/CIFG +ETF/US/CIFU ETF/US/CIK ETF/US/CIL +ETF/US/CIRC +ETF/US/CIZ +ETF/US/CJNK +ETF/US/CJUN +ETF/US/CLCG +ETF/US/CLCV ETF/US/CLDL +ETF/US/CLDS +ETF/US/CLIA +ETF/US/CLIM ETF/US/CLIP ETF/US/CLIX ETF/US/CLM +ETF/US/CLMA +ETF/US/CLNK ETF/US/CLNR ETF/US/CLOA ETF/US/CLOB +ETF/US/CLOC ETF/US/CLOD ETF/US/CLOI +ETF/US/CLOO ETF/US/CLOU ETF/US/CLOX ETF/US/CLOZ +ETF/US/CLRG +ETF/US/CLSA +ETF/US/CLSC ETF/US/CLSE ETF/US/CLSM +ETF/US/CLSX +ETF/US/CLSZ +ETF/US/CLUB +ETF/US/CMAG +ETF/US/CMAY +ETF/US/CMBO ETF/US/CMBS ETF/US/CMCI ETF/US/CMDT ETF/US/CMDY ETF/US/CMF +ETF/US/CMGG ETF/US/CMU +ETF/US/CN ETF/US/CNAV ETF/US/CNBS +ETF/US/CNCG ETF/US/CNCR ETF/US/CNEQ +ETF/US/CNHX +ETF/US/CNQQ ETF/US/CNRG ETF/US/CNXT +ETF/US/CNY ETF/US/CNYA ETF/US/COAL +ETF/US/COHH +ETF/US/COHX +ETF/US/COIA ETF/US/COIG +ETF/US/COII +ETF/US/COIO ETF/US/COIW +ETF/US/COLO ETF/US/COM ETF/US/COMB +ETF/US/COMD +ETF/US/COMG ETF/US/COMT ETF/US/CONI ETF/US/CONL +ETF/US/CONX ETF/US/CONY ETF/US/COPA ETF/US/COPJ ETF/US/COPP ETF/US/COPX ETF/US/COPY +ETF/US/COPZ +ETF/US/CORB +ETF/US/CORD ETF/US/CORN ETF/US/CORO ETF/US/CORP ETF/US/CORX +ETF/US/COSW +ETF/US/COTG +ETF/US/COW ETF/US/COWG ETF/US/COWS ETF/US/COWZ +ETF/US/COYY +ETF/US/COZX +ETF/US/CPAG ETF/US/CPAI ETF/US/CPER +ETF/US/CPHY +ETF/US/CPI ETF/US/CPLB ETF/US/CPLS ETF/US/CPNJ ETF/US/CPNM ETF/US/CPNQ ETF/US/CPNS +ETF/US/CPNX ETF/US/CPRA ETF/US/CPRJ ETF/US/CPRO @@ -672,65 +1149,120 @@ ETF/US/CPSO ETF/US/CPSP ETF/US/CPSR ETF/US/CPST +ETF/US/CPSU ETF/US/CPSY ETF/US/CPXR ETF/US/CQQQ +ETF/US/CQTM ETF/US/CRAK ETF/US/CRBN +ETF/US/CRCA +ETF/US/CRCD +ETF/US/CRCG +ETF/US/CRCO +ETF/US/CRDD ETF/US/CRDT +ETF/US/CRDU +ETF/US/CRDX ETF/US/CRED ETF/US/CRF ETF/US/CRIT +ETF/US/CRMG +ETF/US/CRMU +ETF/US/CRMX +ETF/US/CROC +ETF/US/CROP ETF/US/CRPT ETF/US/CRSH ETF/US/CRTC +ETF/US/CRUX ETF/US/CRUZ +ETF/US/CRWG ETF/US/CRWL +ETF/US/CRWU +ETF/US/CRXP +ETF/US/CRY +ETF/US/CRYP ETF/US/CSA ETF/US/CSB +ETF/US/CSCL +ETF/US/CSCS ETF/US/CSD +ETF/US/CSEX ETF/US/CSF ETF/US/CSHI ETF/US/CSHP +ETF/US/CSIO ETF/US/CSM ETF/US/CSMD +ETF/US/CSML ETF/US/CSNR ETF/US/CSPF ETF/US/CSQ ETF/US/CSRE +ETF/US/CSSD +ETF/US/CSTK ETF/US/CSTNL ETF/US/CTA +ETF/US/CTAP ETF/US/CTEC +ETF/US/CTEF ETF/US/CTEX +ETF/US/CTIF +ETF/US/CTJN +ETF/US/CTMA +ETF/US/CTR +ETF/US/CTRU ETF/US/CUBA +ETF/US/CUBS +ETF/US/CUMB ETF/US/CURE +ETF/US/CUSD ETF/US/CUT ETF/US/CVAR +ETF/US/CVGD ETF/US/CVIE ETF/US/CVLC ETF/US/CVMC +ETF/US/CVNX ETF/US/CVNY ETF/US/CVRD ETF/US/CVRT ETF/US/CVSB ETF/US/CVSE +ETF/US/CVSM ETF/US/CVY +ETF/US/CWAI ETF/US/CWB +ETF/US/CWC ETF/US/CWEB ETF/US/CWI +ETF/US/CWII ETF/US/CWS +ETF/US/CWVX +ETF/US/CWY ETF/US/CXE ETF/US/CXH ETF/US/CXRN ETF/US/CXSE +ETF/US/CYA +ETF/US/CYB ETF/US/CZA ETF/US/CZAR ETF/US/DABS +ETF/US/DADS +ETF/US/DAK ETF/US/DALI +ETF/US/DALT +ETF/US/DAM +ETF/US/DAMD +ETF/US/DANA ETF/US/DAPP ETF/US/DAPR ETF/US/DARP +ETF/US/DASX ETF/US/DAT +ETF/US/DAUD ETF/US/DAUG ETF/US/DAX ETF/US/DBA @@ -739,24 +1271,66 @@ ETF/US/DBB ETF/US/DBC ETF/US/DBE ETF/US/DBEF +ETF/US/DBEH ETF/US/DBEM ETF/US/DBEU ETF/US/DBEZ +ETF/US/DBGR +ETF/US/DBJA ETF/US/DBJP +ETF/US/DBKO ETF/US/DBL +ETF/US/DBLV ETF/US/DBMF ETF/US/DBND ETF/US/DBO +ETF/US/DBOC ETF/US/DBP +ETF/US/DBS +ETF/US/DBSC +ETF/US/DBV ETF/US/DCAP +ETF/US/DCF +ETF/US/DCHF ETF/US/DCMT ETF/US/DCOR +ETF/US/DCPE ETF/US/DCRE +ETF/US/DDDD ETF/US/DDEC +ETF/US/DDF +ETF/US/DDFA +ETF/US/DDFD +ETF/US/DDFF +ETF/US/DDFJ +ETF/US/DDFL +ETF/US/DDFM +ETF/US/DDFN +ETF/US/DDFO +ETF/US/DDFS +ETF/US/DDFY +ETF/US/DDFZ +ETF/US/DDG ETF/US/DDIV ETF/US/DDLS ETF/US/DDM +ETF/US/DDNQ +ETF/US/DDSQ +ETF/US/DDTA +ETF/US/DDTD +ETF/US/DDTF +ETF/US/DDTJ +ETF/US/DDTL +ETF/US/DDTM +ETF/US/DDTN +ETF/US/DDTO +ETF/US/DDTS +ETF/US/DDTY +ETF/US/DDTZ +ETF/US/DDV ETF/US/DDWM +ETF/US/DDX +ETF/US/DDXX ETF/US/DECM ETF/US/DECO ETF/US/DECP @@ -767,15 +1341,25 @@ ETF/US/DECZ ETF/US/DEED ETF/US/DEEF ETF/US/DEEP +ETF/US/DEFA ETF/US/DEFI +ETF/US/DEFN +ETF/US/DEFR ETF/US/DEHP +ETF/US/DEIF ETF/US/DEM +ETF/US/DEMG ETF/US/DEMZ ETF/US/DES +ETF/US/DESC ETF/US/DESK +ETF/US/DEUR ETF/US/DEUS ETF/US/DEW +ETF/US/DEWJ +ETF/US/DEX ETF/US/DEXC +ETF/US/DEZU ETF/US/DFAC ETF/US/DFAE ETF/US/DFAI @@ -795,28 +1379,42 @@ ETF/US/DFEV ETF/US/DFGP ETF/US/DFGR ETF/US/DFGX +ETF/US/DFHY ETF/US/DFIC +ETF/US/DFII ETF/US/DFIP ETF/US/DFIS ETF/US/DFIV ETF/US/DFJ ETF/US/DFLV +ETF/US/DFMC ETF/US/DFND ETF/US/DFNL ETF/US/DFNM +ETF/US/DFNV ETF/US/DFP +ETF/US/DFRA ETF/US/DFSB ETF/US/DFSD ETF/US/DFSE ETF/US/DFSI ETF/US/DFSU ETF/US/DFSV +ETF/US/DFTT ETF/US/DFUS ETF/US/DFUV ETF/US/DFVE +ETF/US/DFVL +ETF/US/DFVS ETF/US/DFVX +ETF/US/DGAP +ETF/US/DGBP ETF/US/DGCB ETF/US/DGIN +ETF/US/DGJA +ETF/US/DGL +ETF/US/DGLO +ETF/US/DGOC ETF/US/DGP ETF/US/DGRE ETF/US/DGRO @@ -827,6 +1425,7 @@ ETF/US/DGT ETF/US/DGZ ETF/US/DHDG ETF/US/DHF +ETF/US/DHLX ETF/US/DHS ETF/US/DHSB ETF/US/DHY @@ -834,36 +1433,57 @@ ETF/US/DIA ETF/US/DIAL ETF/US/DIAX ETF/US/DIEM +ETF/US/DIET ETF/US/DIG -ETF/US/DIGI ETF/US/DIHP ETF/US/DIM +ETF/US/DIME +ETF/US/DINE ETF/US/DINT ETF/US/DIP +ETF/US/DIPR ETF/US/DIPS ETF/US/DISO ETF/US/DISV ETF/US/DIV +ETF/US/DIVA ETF/US/DIVB +ETF/US/DIVC ETF/US/DIVD +ETF/US/DIVE ETF/US/DIVG ETF/US/DIVI ETF/US/DIVL +ETF/US/DIVN ETF/US/DIVO ETF/US/DIVP ETF/US/DIVS ETF/US/DIVY ETF/US/DIVZ ETF/US/DJAN +ETF/US/DJCB +ETF/US/DJCI ETF/US/DJD ETF/US/DJIA ETF/US/DJP +ETF/US/DJPY ETF/US/DJTU +ETF/US/DJU ETF/US/DJUL ETF/US/DJUN +ETF/US/DKNX +ETF/US/DKRB +ETF/US/DKUP +ETF/US/DLAG +ETF/US/DLBR +ETF/US/DLBS +ETF/US/DLFE ETF/US/DLLL +ETF/US/DLMY ETF/US/DLN +ETF/US/DLNV ETF/US/DLS +ETF/US/DLUX ETF/US/DMAR ETF/US/DMAT ETF/US/DMAX @@ -871,47 +1491,88 @@ ETF/US/DMAY ETF/US/DMB ETF/US/DMBS ETF/US/DMCY +ETF/US/DMDV ETF/US/DMF ETF/US/DMO +ETF/US/DMRE +ETF/US/DMRI +ETF/US/DMRL +ETF/US/DMRM +ETF/US/DMRS ETF/US/DMX ETF/US/DMXF ETF/US/DNL +ETF/US/DNNG ETF/US/DNOV ETF/US/DNP +ETF/US/DOCK ETF/US/DOCT ETF/US/DOG +ETF/US/DOGD ETF/US/DOGG +ETF/US/DOGS +ETF/US/DOJE ETF/US/DOL ETF/US/DON +ETF/US/DOO +ETF/US/DOZR ETF/US/DPG +ETF/US/DPK +ETF/US/DPRE ETF/US/DPST +ETF/US/DQML ETF/US/DRAG ETF/US/DRAI +ETF/US/DRAM +ETF/US/DRAY +ETF/US/DRES +ETF/US/DRGN ETF/US/DRIP ETF/US/DRIV +ETF/US/DRKY ETF/US/DRLL ETF/US/DRN +ETF/US/DRNL +ETF/US/DRNZ +ETF/US/DRR ETF/US/DRSK ETF/US/DRUP ETF/US/DRV +ETF/US/DRW ETF/US/DSCF +ETF/US/DSCO +ETF/US/DSE ETF/US/DSEP ETF/US/DSI +ETF/US/DSJA ETF/US/DSL ETF/US/DSM ETF/US/DSMC +ETF/US/DSOC +ETF/US/DSPC ETF/US/DSPY ETF/US/DSTL ETF/US/DSTX ETF/US/DSU +ETF/US/DSUM ETF/US/DTAN ETF/US/DTCR ETF/US/DTD ETF/US/DTEC ETF/US/DTF ETF/US/DTH +ETF/US/DTN +ETF/US/DTO +ETF/US/DTOX ETF/US/DTRE +ETF/US/DTUL +ETF/US/DTUS +ETF/US/DTYL +ETF/US/DTYS +ETF/US/DUAL ETF/US/DUBS +ETF/US/DUC +ETF/US/DUDE ETF/US/DUG ETF/US/DUHP ETF/US/DUKH @@ -919,44 +1580,83 @@ ETF/US/DUKQ ETF/US/DUKX ETF/US/DUKZ ETF/US/DULL +ETF/US/DUNK +ETF/US/DUOG ETF/US/DURA ETF/US/DUSA ETF/US/DUSB +ETF/US/DUSG ETF/US/DUSL ETF/US/DUST +ETF/US/DUTY ETF/US/DVAL ETF/US/DVDN +ETF/US/DVEM +ETF/US/DVGR +ETF/US/DVHL +ETF/US/DVIN ETF/US/DVLU ETF/US/DVND ETF/US/DVOL +ETF/US/DVOP +ETF/US/DVP ETF/US/DVQQ +ETF/US/DVRE ETF/US/DVSP +ETF/US/DVUT +ETF/US/DVVY +ETF/US/DVXB +ETF/US/DVXC +ETF/US/DVXE +ETF/US/DVXF +ETF/US/DVXK +ETF/US/DVXP +ETF/US/DVXV +ETF/US/DVXY ETF/US/DVY ETF/US/DVYA ETF/US/DVYE +ETF/US/DVYL +ETF/US/DWAQ ETF/US/DWAS ETF/US/DWAT ETF/US/DWAW ETF/US/DWCR +ETF/US/DWEQ +ETF/US/DWFI +ETF/US/DWIN ETF/US/DWLD ETF/US/DWM +ETF/US/DWMC ETF/US/DWMF +ETF/US/DWPP ETF/US/DWSH +ETF/US/DWT +ETF/US/DWTR ETF/US/DWUS +ETF/US/DWWN ETF/US/DWX ETF/US/DXD +ETF/US/DXGE ETF/US/DXIV ETF/US/DXJ ETF/US/DXJS ETF/US/DXUV +ETF/US/DYB ETF/US/DYFI +ETF/US/DYFN +ETF/US/DYHG ETF/US/DYLD ETF/US/DYLG +ETF/US/DYLS +ETF/US/DYNB ETF/US/DYNF ETF/US/DYNI ETF/US/DYTA +ETF/US/DZK ETF/US/DZZ ETF/US/EAD +ETF/US/EAFD ETF/US/EAFG ETF/US/EAGG ETF/US/EAGL @@ -966,12 +1666,16 @@ ETF/US/EAOK ETF/US/EAOM ETF/US/EAOR ETF/US/EAPR +ETF/US/EART ETF/US/EASG +ETF/US/EASI +ETF/US/EASY ETF/US/EATV ETF/US/EATZ ETF/US/EBI ETF/US/EBIT ETF/US/EBIZ +ETF/US/EBLU ETF/US/EBND ETF/US/EBUF ETF/US/ECAT @@ -983,6 +1687,7 @@ ETF/US/ECML ETF/US/ECNS ETF/US/ECON ETF/US/ECOW +ETF/US/ECOZ ETF/US/EDC ETF/US/EDD ETF/US/EDEN @@ -991,21 +1696,30 @@ ETF/US/EDGE ETF/US/EDGF ETF/US/EDGH ETF/US/EDGI +ETF/US/EDGQ ETF/US/EDGU +ETF/US/EDGX +ETF/US/EDI ETF/US/EDIV ETF/US/EDOC ETF/US/EDOG ETF/US/EDOW +ETF/US/EDUT ETF/US/EDV ETF/US/EDZ ETF/US/EEA +ETF/US/EEB +ETF/US/EEE +ETF/US/EEH ETF/US/EELV ETF/US/EEM ETF/US/EEMA +ETF/US/EEMD ETF/US/EEMO ETF/US/EEMS ETF/US/EEMV ETF/US/EEMX +ETF/US/EERN ETF/US/EES ETF/US/EET ETF/US/EETH @@ -1016,26 +1730,35 @@ ETF/US/EFAD ETF/US/EFAS ETF/US/EFAV ETF/US/EFAX +ETF/US/EFF ETF/US/EFFE ETF/US/EFFI ETF/US/EFG ETF/US/EFIV ETF/US/EFIX +ETF/US/EFL ETF/US/EFNL ETF/US/EFO ETF/US/EFR ETF/US/EFRA ETF/US/EFT ETF/US/EFU +ETF/US/EFUT ETF/US/EFV ETF/US/EFZ ETF/US/EGF ETF/US/EGGQ ETF/US/EGGS ETF/US/EGGY +ETF/US/EGIS +ETF/US/EGLE +ETF/US/EGPT ETF/US/EGUS +ETF/US/EHCC ETF/US/EHI ETF/US/EHLS +ETF/US/EHT +ETF/US/EHY ETF/US/EIDO ETF/US/EIM ETF/US/EINC @@ -1045,58 +1768,101 @@ ETF/US/EIRL ETF/US/EIS ETF/US/EJAN ETF/US/EJUL +ETF/US/EKAR ETF/US/EKG ETF/US/ELCV ETF/US/ELD +ETF/US/ELFY ETF/US/ELIL ETF/US/ELIS ETF/US/ELM ETF/US/ELON ETF/US/ELQD +ETF/US/EMAG ETF/US/EMB ETF/US/EMBD +ETF/US/EMBH +ETF/US/EMBX +ETF/US/EMCA ETF/US/EMCB ETF/US/EMCC +ETF/US/EMCG +ETF/US/EMCH ETF/US/EMCR ETF/US/EMCS ETF/US/EMD ETF/US/EMDM ETF/US/EMDV +ETF/US/EMEM ETF/US/EMEQ +ETF/US/EMES +ETF/US/EMET ETF/US/EMF +ETF/US/EMFI +ETF/US/EMFM +ETF/US/EMFQ +ETF/US/EMGC +ETF/US/EMGD ETF/US/EMGF ETF/US/EMHC ETF/US/EMHY ETF/US/EMIF +ETF/US/EMIH +ETF/US/EMJN +ETF/US/EMKT ETF/US/EMLC ETF/US/EMLP ETF/US/EMM ETF/US/EMMF +ETF/US/EMMY ETF/US/EMNT ETF/US/EMO +ETF/US/EMOP ETF/US/EMOT ETF/US/EMPB +ETF/US/EMPW ETF/US/EMQQ +ETF/US/EMSC ETF/US/EMSF +ETF/US/EMSG +ETF/US/EMSH ETF/US/EMTL ETF/US/EMTY ETF/US/EMXC ETF/US/EMXF +ETF/US/EMXX +ETF/US/EMZA +ETF/US/ENDW ETF/US/ENFR +ETF/US/ENHI +ETF/US/ENHU ETF/US/ENOR +ETF/US/ENPX +ETF/US/ENRG +ETF/US/ENTR ETF/US/ENX ETF/US/ENZL ETF/US/EOCT ETF/US/EOD ETF/US/EOI +ETF/US/EOPS ETF/US/EOS +ETF/US/EOSU ETF/US/EOT +ETF/US/EPAI +ETF/US/EPEM ETF/US/EPHE ETF/US/EPI +ETF/US/EPIN +ETF/US/EPMB +ETF/US/EPMV ETF/US/EPOL ETF/US/EPP +ETF/US/EPRE ETF/US/EPRF ETF/US/EPS +ETF/US/EPSB +ETF/US/EPSV ETF/US/EPU ETF/US/EPV ETF/US/EQAL @@ -1104,89 +1870,145 @@ ETF/US/EQIN ETF/US/EQL ETF/US/EQLS ETF/US/EQLT +ETF/US/EQOP ETF/US/EQRR ETF/US/EQTY +ETF/US/EQUL ETF/US/EQWL ETF/US/ERC ETF/US/ERET ETF/US/ERH +ETF/US/ERM ETF/US/ERNZ +ETF/US/ERSX ETF/US/ERTH +ETF/US/ERUS ETF/US/ERUS.ESC ETF/US/ERX ETF/US/ERY +ETF/US/ESBG +ETF/US/ESCR +ETF/US/ESEB ETF/US/ESG +ETF/US/ESGA +ETF/US/ESGB ETF/US/ESGD ETF/US/ESGE +ETF/US/ESGF ETF/US/ESGG ETF/US/ESGL +ETF/US/ESGN +ETF/US/ESGS ETF/US/ESGU ETF/US/ESGV +ETF/US/ESGW ETF/US/ESGX +ETF/US/ESGY +ETF/US/ESHY +ETF/US/ESIM ETF/US/ESIX +ETF/US/ESK +ETF/US/ESLG +ETF/US/ESLV ETF/US/ESML ETF/US/ESMV ETF/US/ESN +ETF/US/ESNG ETF/US/ESPO +ETF/US/ESSC +ETF/US/ESUM +ETF/US/ESUS ETF/US/ETB ETF/US/ETCG +ETF/US/ETCO ETF/US/ETEC +ETF/US/ETFT ETF/US/ETG ETF/US/ETH ETF/US/ETHA +ETF/US/ETHB ETF/US/ETHD +ETF/US/ETHI ETF/US/ETHO ETF/US/ETHT ETF/US/ETHU ETF/US/ETHV ETF/US/ETHW ETF/US/ETJ +ETF/US/ETNG ETF/US/ETO +ETF/US/ETPA ETF/US/ETQ +ETF/US/ETRL +ETF/US/ETTY ETF/US/ETU ETF/US/ETV ETF/US/ETW ETF/US/ETX ETF/US/ETY -ETF/US/EU ETF/US/EUAD +ETF/US/EUCG ETF/US/EUDG ETF/US/EUDV +ETF/US/EUFL ETF/US/EUFN +ETF/US/EUFX +ETF/US/EUHY +ETF/US/EUIG ETF/US/EUM +ETF/US/EUMF +ETF/US/EUMV ETF/US/EUO ETF/US/EURL +ETF/US/EURZ ETF/US/EUSA ETF/US/EUSB ETF/US/EUSC ETF/US/EUSM +ETF/US/EUV +ETF/US/EUVX +ETF/US/EUXL ETF/US/EVAV +ETF/US/EVEN ETF/US/EVF ETF/US/EVG +ETF/US/EVGBC ETF/US/EVHY ETF/US/EVIM +ETF/US/EVIX +ETF/US/EVLMC ETF/US/EVLN ETF/US/EVLU ETF/US/EVM +ETF/US/EVMO ETF/US/EVMT +ETF/US/EVMU ETF/US/EVN ETF/US/EVNT +ETF/US/EVPF ETF/US/EVSB ETF/US/EVSD ETF/US/EVSM +ETF/US/EVSTC ETF/US/EVT ETF/US/EVTR ETF/US/EVUS ETF/US/EVV ETF/US/EVX +ETF/US/EVXX +ETF/US/EVY ETF/US/EVYM ETF/US/EWA ETF/US/EWC ETF/US/EWD +ETF/US/EWEB +ETF/US/EWEM ETF/US/EWG +ETF/US/EWGS ETF/US/EWH ETF/US/EWI ETF/US/EWJ +ETF/US/EWJE ETF/US/EWJV ETF/US/EWK ETF/US/EWL @@ -1195,7 +2017,9 @@ ETF/US/EWN ETF/US/EWO ETF/US/EWP ETF/US/EWQ +ETF/US/EWRI ETF/US/EWS +ETF/US/EWSC ETF/US/EWT ETF/US/EWU ETF/US/EWUS @@ -1205,17 +2029,26 @@ ETF/US/EWX ETF/US/EWY ETF/US/EWZ ETF/US/EWZS +ETF/US/EXD +ETF/US/EXEQ ETF/US/EXG ETF/US/EXI +ETF/US/EXIV +ETF/US/EXT +ETF/US/EXUS ETF/US/EYEG +ETF/US/EYES ETF/US/EYLD ETF/US/EZA ETF/US/EZBC ETF/US/EZET ETF/US/EZJ ETF/US/EZM +ETF/US/EZMO ETF/US/EZPZ +ETF/US/EZRO ETF/US/EZU +ETF/US/FAAA ETF/US/FAAR ETF/US/FAB ETF/US/FAD @@ -1227,11 +2060,16 @@ ETF/US/FAN ETF/US/FAPR ETF/US/FARX ETF/US/FAS +ETF/US/FATT ETF/US/FAUG +ETF/US/FAUS ETF/US/FAX ETF/US/FAZ +ETF/US/FB ETF/US/FBCG ETF/US/FBCV +ETF/US/FBDC +ETF/US/FBGX ETF/US/FBL ETF/US/FBND ETF/US/FBOT @@ -1239,14 +2077,17 @@ ETF/US/FBT ETF/US/FBTC ETF/US/FBUF ETF/US/FBY +ETF/US/FBYY ETF/US/FBZ ETF/US/FCA ETF/US/FCAL +ETF/US/FCAN ETF/US/FCBD ETF/US/FCEF ETF/US/FCFY ETF/US/FCG ETF/US/FCLD +ETF/US/FCLO ETF/US/FCO ETF/US/FCOM ETF/US/FCOR @@ -1257,12 +2098,14 @@ ETF/US/FCTE ETF/US/FCTR ETF/US/FCUS ETF/US/FCVT +ETF/US/FCXG ETF/US/FDAT ETF/US/FDCE ETF/US/FDCF ETF/US/FDD ETF/US/FDEC ETF/US/FDEM +ETF/US/FDEU ETF/US/FDEV ETF/US/FDFF ETF/US/FDG @@ -1271,6 +2114,7 @@ ETF/US/FDHT ETF/US/FDHY ETF/US/FDIF ETF/US/FDIG +ETF/US/FDIQ ETF/US/FDIS ETF/US/FDIV ETF/US/FDL @@ -1282,7 +2126,9 @@ ETF/US/FDN ETF/US/FDND ETF/US/FDNI ETF/US/FDRR +ETF/US/FDRS ETF/US/FDRV +ETF/US/FDRX ETF/US/FDT ETF/US/FDTB ETF/US/FDTS @@ -1299,25 +2145,38 @@ ETF/US/FEBT ETF/US/FEBU ETF/US/FEBW ETF/US/FEBZ +ETF/US/FEDL ETF/US/FEDM +ETF/US/FEDX +ETF/US/FEEM ETF/US/FEGE +ETF/US/FEHY +ETF/US/FEI ETF/US/FEIG ETF/US/FELC ETF/US/FELG ETF/US/FELV ETF/US/FEM ETF/US/FEMB +ETF/US/FEMD +ETF/US/FEMG ETF/US/FEMR ETF/US/FEMS +ETF/US/FEMV +ETF/US/FEN ETF/US/FENI ETF/US/FENY +ETF/US/FEO ETF/US/FEOE ETF/US/FEP ETF/US/FEPI ETF/US/FESM ETF/US/FETH +ETF/US/FEU +ETF/US/FEUL ETF/US/FEUS ETF/US/FEUZ +ETF/US/FEVR ETF/US/FEX ETF/US/FEZ ETF/US/FFA @@ -1325,7 +2184,10 @@ ETF/US/FFC ETF/US/FFDI ETF/US/FFEB ETF/US/FFEM +ETF/US/FFEU +ETF/US/FFF ETF/US/FFGX +ETF/US/FFHG ETF/US/FFIU ETF/US/FFLC ETF/US/FFLG @@ -1333,15 +2195,24 @@ ETF/US/FFLS ETF/US/FFLV ETF/US/FFND ETF/US/FFOG +ETF/US/FFOX +ETF/US/FFR +ETF/US/FFSG ETF/US/FFSM +ETF/US/FFTG +ETF/US/FFTI ETF/US/FFTY +ETF/US/FFUT ETF/US/FGB ETF/US/FGD ETF/US/FGDL ETF/US/FGM +ETF/US/FGRU +ETF/US/FGSI ETF/US/FGSM ETF/US/FHDG ETF/US/FHEQ +ETF/US/FHK ETF/US/FHLC ETF/US/FHYS ETF/US/FIAT @@ -1350,28 +2221,46 @@ ETF/US/FICS ETF/US/FID ETF/US/FIDI ETF/US/FIDU +ETF/US/FIEE +ETF/US/FIF ETF/US/FIGB +ETF/US/FIGG +ETF/US/FIHD ETF/US/FIIG ETF/US/FILL ETF/US/FINE ETF/US/FINS ETF/US/FINT +ETF/US/FINU ETF/US/FINX +ETF/US/FINY +ETF/US/FINZ ETF/US/FIRI ETF/US/FIRS ETF/US/FISR ETF/US/FITE +ETF/US/FITZ +ETF/US/FIV ETF/US/FIVA +ETF/US/FIVG +ETF/US/FIVR ETF/US/FIVY ETF/US/FIW ETF/US/FIXD ETF/US/FIXP +ETF/US/FIXT +ETF/US/FIYY ETF/US/FJAN +ETF/US/FJNK ETF/US/FJP +ETF/US/FJU ETF/US/FJUL ETF/US/FJUN +ETF/US/FKO ETF/US/FKU +ETF/US/FLAG ETF/US/FLAO +ETF/US/FLAT ETF/US/FLAU ETF/US/FLAX ETF/US/FLBL @@ -1390,40 +2279,56 @@ ETF/US/FLDR ETF/US/FLDZ ETF/US/FLEE ETF/US/FLEU +ETF/US/FLFR ETF/US/FLGB +ETF/US/FLGE ETF/US/FLGR ETF/US/FLGV ETF/US/FLHK ETF/US/FLHY ETF/US/FLIA ETF/US/FLIN +ETF/US/FLIO +ETF/US/FLIY ETF/US/FLJH ETF/US/FLJJ ETF/US/FLJP ETF/US/FLKR ETF/US/FLLA +ETF/US/FLLV +ETF/US/FLM ETF/US/FLMB ETF/US/FLMI ETF/US/FLMX ETF/US/FLN ETF/US/FLOT +ETF/US/FLQD +ETF/US/FLQE +ETF/US/FLQG +ETF/US/FLQH ETF/US/FLQL ETF/US/FLQM ETF/US/FLQS ETF/US/FLRG ETF/US/FLRN ETF/US/FLRT +ETF/US/FLRU ETF/US/FLSA ETF/US/FLSP ETF/US/FLSW ETF/US/FLTB +ETF/US/FLTN ETF/US/FLTR ETF/US/FLTW ETF/US/FLUD ETF/US/FLV +ETF/US/FLXI +ETF/US/FLXN ETF/US/FLXR ETF/US/FLYD +ETF/US/FLYT ETF/US/FLYU +ETF/US/FLZA ETF/US/FM ETF/US/FMAG ETF/US/FMAR @@ -1437,10 +2342,16 @@ ETF/US/FMED ETF/US/FMET ETF/US/FMF ETF/US/FMHI +ETF/US/FMK +ETF/US/FMKT ETF/US/FMN ETF/US/FMNY +ETF/US/FMO ETF/US/FMQQ +ETF/US/FMTL ETF/US/FMTM +ETF/US/FMUB +ETF/US/FMUN ETF/US/FMY ETF/US/FNCL ETF/US/FNDA @@ -1449,6 +2360,7 @@ ETF/US/FNDC ETF/US/FNDE ETF/US/FNDF ETF/US/FNDX +ETF/US/FNG ETF/US/FNGA ETF/US/FNGB ETF/US/FNGD @@ -1456,14 +2368,20 @@ ETF/US/FNGG ETF/US/FNGO ETF/US/FNGS ETF/US/FNGU +ETF/US/FNGZ +ETF/US/FNI ETF/US/FNK ETF/US/FNOV +ETF/US/FNTC ETF/US/FNX ETF/US/FNY ETF/US/FOCT ETF/US/FOF +ETF/US/FOL +ETF/US/FOMO ETF/US/FOPC ETF/US/FORH +ETF/US/FOTO ETF/US/FOVL ETF/US/FOWF ETF/US/FOXY @@ -1474,36 +2392,58 @@ ETF/US/FPE ETF/US/FPEI ETF/US/FPF ETF/US/FPFD +ETF/US/FPL ETF/US/FPRO +ETF/US/FPWR ETF/US/FPX ETF/US/FPXE ETF/US/FPXI ETF/US/FQAL ETF/US/FRA +ETF/US/FRAK +ETF/US/FRDD ETF/US/FRDM +ETF/US/FRDU ETF/US/FREL +ETF/US/FRGN ETF/US/FRI +ETF/US/FRIZ +ETF/US/FRLG +ETF/US/FRN ETF/US/FRNW ETF/US/FRTY +ETF/US/FRWD +ETF/US/FSA ETF/US/FSBD ETF/US/FSCC ETF/US/FSCO ETF/US/FSCS +ETF/US/FSD ETF/US/FSEC +ETF/US/FSEG ETF/US/FSEP +ETF/US/FSEV +ETF/US/FSG ETF/US/FSGS ETF/US/FSLD +ETF/US/FSLF ETF/US/FSMB ETF/US/FSMD +ETF/US/FSML +ETF/US/FSOL +ETF/US/FSSL ETF/US/FSST ETF/US/FSTA +ETF/US/FSU ETF/US/FSYD ETF/US/FSZ ETF/US/FT ETF/US/FTA ETF/US/FTAG ETF/US/FTBD +ETF/US/FTBI ETF/US/FTC +ETF/US/FTCA ETF/US/FTCB ETF/US/FTCE ETF/US/FTCS @@ -1512,37 +2452,57 @@ ETF/US/FTEC ETF/US/FTF ETF/US/FTGC ETF/US/FTGS +ETF/US/FTHB ETF/US/FTHF ETF/US/FTHI ETF/US/FTHY ETF/US/FTIF ETF/US/FTKI +ETF/US/FTLB ETF/US/FTLS +ETF/US/FTMA +ETF/US/FTMH +ETF/US/FTMN +ETF/US/FTMS +ETF/US/FTMU +ETF/US/FTNJ +ETF/US/FTNY +ETF/US/FTOH +ETF/US/FTPA ETF/US/FTQI ETF/US/FTRB ETF/US/FTRI ETF/US/FTSD ETF/US/FTSL ETF/US/FTSM +ETF/US/FTVA ETF/US/FTWO +ETF/US/FTXD ETF/US/FTXG ETF/US/FTXH ETF/US/FTXL ETF/US/FTXN ETF/US/FTXO ETF/US/FTXR +ETF/US/FUD +ETF/US/FUE ETF/US/FUMB ETF/US/FUND ETF/US/FUNL ETF/US/FUSI +ETF/US/FUT +ETF/US/FUTG ETF/US/FUTY ETF/US/FV ETF/US/FVAL ETF/US/FVC ETF/US/FVD +ETF/US/FVL +ETF/US/FWDB ETF/US/FXA ETF/US/FXB ETF/US/FXC +ETF/US/FXCH ETF/US/FXD ETF/US/FXE ETF/US/FXED @@ -1555,6 +2515,8 @@ ETF/US/FXN ETF/US/FXO ETF/US/FXP ETF/US/FXR +ETF/US/FXS +ETF/US/FXSG ETF/US/FXU ETF/US/FXY ETF/US/FXZ @@ -1568,17 +2530,33 @@ ETF/US/GAA ETF/US/GAB ETF/US/GABF ETF/US/GAEM +ETF/US/GAID ETF/US/GAL ETF/US/GAM ETF/US/GAMR ETF/US/GAPR +ETF/US/GARA +ETF/US/GARD ETF/US/GARP +ETF/US/GARS +ETF/US/GARY +ETF/US/GASL ETF/US/GAST +ETF/US/GASX +ETF/US/GASZ +ETF/US/GAUD ETF/US/GAUG +ETF/US/GAVA +ETF/US/GAZ ETF/US/GBAB +ETF/US/GBDV ETF/US/GBF +ETF/US/GBGR +ETF/US/GBHI ETF/US/GBIL ETF/US/GBLD +ETF/US/GBLO +ETF/US/GBND ETF/US/GBUG ETF/US/GBUY ETF/US/GBXA @@ -1587,66 +2565,108 @@ ETF/US/GBXC ETF/US/GCAD ETF/US/GCAL ETF/US/GCC +ETF/US/GCIG ETF/US/GCLN ETF/US/GCOR ETF/US/GCOW ETF/US/GCV +ETF/US/GDAT ETF/US/GDE ETF/US/GDEC +ETF/US/GDEF +ETF/US/GDFN +ETF/US/GDG ETF/US/GDIV ETF/US/GDL ETF/US/GDMA ETF/US/GDMN +ETF/US/GDNA ETF/US/GDO ETF/US/GDOC +ETF/US/GDOG +ETF/US/GDT ETF/US/GDV +ETF/US/GDVD ETF/US/GDX ETF/US/GDXD ETF/US/GDXJ ETF/US/GDXU +ETF/US/GDXW ETF/US/GDXY ETF/US/GEM ETF/US/GEMD ETF/US/GEME +ETF/US/GEMG ETF/US/GEND ETF/US/GENM ETF/US/GENT ETF/US/GENW +ETF/US/GENY +ETF/US/GENZ +ETF/US/GEOA +ETF/US/GER +ETF/US/GERM +ETF/US/GEVG +ETF/US/GEVX +ETF/US/GEW ETF/US/GF ETF/US/GFEB ETF/US/GFGF +ETF/US/GFIN ETF/US/GFLW +ETF/US/GFOF ETF/US/GGLL ETF/US/GGLS ETF/US/GGM ETF/US/GGME ETF/US/GGN +ETF/US/GGO +ETF/US/GGOV ETF/US/GGRW ETF/US/GGT +ETF/US/GGTL ETF/US/GGUS ETF/US/GGZ +ETF/US/GHEE +ETF/US/GHII ETF/US/GHMS ETF/US/GHTA ETF/US/GHY ETF/US/GHYB ETF/US/GHYG ETF/US/GIAX +ETF/US/GIEQ +ETF/US/GIF ETF/US/GIGB +ETF/US/GIGE +ETF/US/GIGL ETF/US/GII +ETF/US/GIND ETF/US/GINN ETF/US/GINX +ETF/US/GIVE ETF/US/GJAN ETF/US/GJUL ETF/US/GJUN ETF/US/GK +ETF/US/GKAT +ETF/US/GLAM ETF/US/GLBL +ETF/US/GLBY +ETF/US/GLCN ETF/US/GLCR ETF/US/GLD ETF/US/GLDI ETF/US/GLDM +ETF/US/GLDN +ETF/US/GLDW ETF/US/GLDY +ETF/US/GLGG +ETF/US/GLIF ETF/US/GLIN +ETF/US/GLIX ETF/US/GLL +ETF/US/GLNK ETF/US/GLO ETF/US/GLOF ETF/US/GLOV @@ -1656,55 +2676,84 @@ ETF/US/GLRY ETF/US/GLTR ETF/US/GLU ETF/US/GLV +ETF/US/GLWG +ETF/US/GLXU +ETF/US/GMAN ETF/US/GMAR ETF/US/GMAY ETF/US/GMET +ETF/US/GMEU +ETF/US/GMEY ETF/US/GMF ETF/US/GMMA ETF/US/GMMF ETF/US/GMNY +ETF/US/GMOC +ETF/US/GMOD ETF/US/GMOI ETF/US/GMOM ETF/US/GMOV ETF/US/GMUB ETF/US/GMUN +ETF/US/GNAF ETF/US/GNMA +ETF/US/GNMX ETF/US/GNOM ETF/US/GNOV ETF/US/GNR ETF/US/GNT +ETF/US/GOAT ETF/US/GOAU ETF/US/GOCT ETF/US/GOEX ETF/US/GOF +ETF/US/GOLS ETF/US/GOLY ETF/US/GOOP +ETF/US/GOOW ETF/US/GOOX ETF/US/GOOY ETF/US/GOP +ETF/US/GOU ETF/US/GOVI +ETF/US/GOVM ETF/US/GOVT ETF/US/GOVZ +ETF/US/GPAL ETF/US/GPIQ ETF/US/GPIX +ETF/US/GPM ETF/US/GPOW ETF/US/GPRF +ETF/US/GPT ETF/US/GPTY +ETF/US/GPZ +ETF/US/GQGU ETF/US/GQI ETF/US/GQQQ ETF/US/GQRE +ETF/US/GRAG ETF/US/GREI ETF/US/GREK +ETF/US/GRES ETF/US/GRF +ETF/US/GRI ETF/US/GRID +ETF/US/GRIN +ETF/US/GRMY ETF/US/GRN ETF/US/GRNB +ETF/US/GRNI +ETF/US/GRNJ +ETF/US/GRNR ETF/US/GRNY ETF/US/GROZ ETF/US/GRPM ETF/US/GRPZ +ETF/US/GRU ETF/US/GRW ETF/US/GRX +ETF/US/GRZZ ETF/US/GSC ETF/US/GSEE ETF/US/GSEP @@ -1712,6 +2761,7 @@ ETF/US/GSEU ETF/US/GSEW ETF/US/GSFP ETF/US/GSG +ETF/US/GSGO ETF/US/GSIB ETF/US/GSID ETF/US/GSIE @@ -1719,110 +2769,193 @@ ETF/US/GSIG ETF/US/GSJY ETF/US/GSKH ETF/US/GSLC +ETF/US/GSOL +ETF/US/GSP ETF/US/GSPY ETF/US/GSSC ETF/US/GSST +ETF/US/GSUI ETF/US/GSUS +ETF/US/GSWO +ETF/US/GSX ETF/US/GSY +ETF/US/GTAA ETF/US/GTEK ETF/US/GTIP +ETF/US/GTND ETF/US/GTO +ETF/US/GTOC +ETF/US/GTOH +ETF/US/GTOP +ETF/US/GTOQ ETF/US/GTOS +ETF/US/GTPE ETF/US/GTR +ETF/US/GUDB ETF/US/GUG +ETF/US/GULF ETF/US/GUMI ETF/US/GUNR ETF/US/GUNZ ETF/US/GURU ETF/US/GUSA +ETF/US/GUSE ETF/US/GUSH ETF/US/GUT ETF/US/GVAL ETF/US/GVI ETF/US/GVIP +ETF/US/GVLE ETF/US/GVLU ETF/US/GVUS ETF/US/GWX ETF/US/GXC ETF/US/GXDW +ETF/US/GXF ETF/US/GXG +ETF/US/GXIG +ETF/US/GXLC +ETF/US/GXPC +ETF/US/GXPD +ETF/US/GXPE +ETF/US/GXPS +ETF/US/GXPT +ETF/US/GXRP ETF/US/GXTG ETF/US/GXUS ETF/US/GYLD ETF/US/HACK ETF/US/HAIL +ETF/US/HAKY +ETF/US/HALX +ETF/US/HAO ETF/US/HAP ETF/US/HAPR ETF/US/HAPS ETF/US/HAPY ETF/US/HART +ETF/US/HAUD ETF/US/HAUS ETF/US/HAUZ ETF/US/HAWX +ETF/US/HBDC +ETF/US/HBMX +ETF/US/HBR +ETF/US/HBRD ETF/US/HBTA ETF/US/HBTC +ETF/US/HCAP ETF/US/HCMT ETF/US/HCOM ETF/US/HCOW ETF/US/HCRB +ETF/US/HDAW ETF/US/HDEF ETF/US/HDG ETF/US/HDGE +ETF/US/HDIV ETF/US/HDLB +ETF/US/HDLV ETF/US/HDMV ETF/US/HDRO ETF/US/HDUS ETF/US/HDV ETF/US/HEAL ETF/US/HEAT +ETF/US/HECA ETF/US/HECO +ETF/US/HEDG ETF/US/HEDJ ETF/US/HEEM +ETF/US/HEET ETF/US/HEFA +ETF/US/HEFT ETF/US/HEGD ETF/US/HEJD +ETF/US/HELS ETF/US/HELX +ETF/US/HEMI ETF/US/HEQ ETF/US/HEQQ ETF/US/HEQT ETF/US/HERD ETF/US/HERO +ETF/US/HEWC +ETF/US/HEWG +ETF/US/HEWI ETF/US/HEWJ +ETF/US/HEWL +ETF/US/HEWP +ETF/US/HEWU +ETF/US/HEWW +ETF/US/HEWY ETF/US/HEZU ETF/US/HF +ETF/US/HFEQ +ETF/US/HFGM ETF/US/HFGO +ETF/US/HFMF ETF/US/HFND ETF/US/HFRO ETF/US/HFSI ETF/US/HFSP +ETF/US/HFXE ETF/US/HFXI +ETF/US/HFXJ ETF/US/HGER ETF/US/HGLB +ETF/US/HGRO +ETF/US/HHH ETF/US/HIBL ETF/US/HIBS ETF/US/HIDE ETF/US/HIDV +ETF/US/HIE ETF/US/HIGH ETF/US/HIMU +ETF/US/HIMY ETF/US/HIMZ ETF/US/HIO +ETF/US/HIPR ETF/US/HIPS +ETF/US/HIS ETF/US/HISF ETF/US/HIX ETF/US/HIYS +ETF/US/HIYY ETF/US/HJAN +ETF/US/HJEN +ETF/US/HJPX ETF/US/HJUL +ETF/US/HJUN ETF/US/HKND ETF/US/HLAL ETF/US/HLGE +ETF/US/HLXX +ETF/US/HMAY ETF/US/HMOP +ETF/US/HMYY ETF/US/HNDL ETF/US/HNW ETF/US/HOCT ETF/US/HODL +ETF/US/HODU +ETF/US/HOII +ETF/US/HOLA +ETF/US/HOLD +ETF/US/HOM +ETF/US/HOML ETF/US/HOMZ +ETF/US/HONG +ETF/US/HONR ETF/US/HOOG +ETF/US/HOOI +ETF/US/HOOW ETF/US/HOOX +ETF/US/HOOY +ETF/US/HOOZ +ETF/US/HOTL +ETF/US/HOYY ETF/US/HPF ETF/US/HPI ETF/US/HPS @@ -1833,6 +2966,7 @@ ETF/US/HRTS ETF/US/HSBH ETF/US/HSCZ ETF/US/HSMV +ETF/US/HSPX ETF/US/HSRT ETF/US/HSUN ETF/US/HTAB @@ -1841,8 +2975,14 @@ ETF/US/HTD ETF/US/HTEC ETF/US/HTRB ETF/US/HTUS +ETF/US/HTY +ETF/US/HULL +ETF/US/HUMN +ETF/US/HUSE ETF/US/HUSV +ETF/US/HUTG ETF/US/HVAC +ETF/US/HVAL ETF/US/HWAY ETF/US/HWSM ETF/US/HYB @@ -1852,6 +2992,7 @@ ETF/US/HYBL ETF/US/HYBX ETF/US/HYD ETF/US/HYDB +ETF/US/HYDD ETF/US/HYDR ETF/US/HYDW ETF/US/HYEM @@ -1859,17 +3000,24 @@ ETF/US/HYFI ETF/US/HYG ETF/US/HYGH ETF/US/HYGI +ETF/US/HYGM ETF/US/HYGV ETF/US/HYGW ETF/US/HYHG ETF/US/HYI +ETF/US/HYIH ETF/US/HYIN ETF/US/HYKE ETF/US/HYLB +ETF/US/HYLD ETF/US/HYLG ETF/US/HYLS +ETF/US/HYLV ETF/US/HYMB ETF/US/HYMU +ETF/US/HYND +ETF/US/HYP +ETF/US/HYPG ETF/US/HYRM ETF/US/HYS ETF/US/HYSA @@ -1878,6 +3026,7 @@ ETF/US/HYT ETF/US/HYTI ETF/US/HYTR ETF/US/HYUP +ETF/US/HYXE ETF/US/HYXF ETF/US/HYXU ETF/US/HYZD @@ -1886,16 +3035,31 @@ ETF/US/IAF ETF/US/IAGG ETF/US/IAI ETF/US/IAK +ETF/US/IALT ETF/US/IAPR ETF/US/IAT ETF/US/IAU +ETF/US/IAUF ETF/US/IAUG +ETF/US/IAUI ETF/US/IAUM ETF/US/IBAT ETF/US/IBB +ETF/US/IBBJ ETF/US/IBBQ ETF/US/IBCA +ETF/US/IBCB +ETF/US/IBCD +ETF/US/IBCE ETF/US/IBD +ETF/US/IBDC +ETF/US/IBDD +ETF/US/IBDK +ETF/US/IBDL +ETF/US/IBDM +ETF/US/IBDN +ETF/US/IBDO +ETF/US/IBDP ETF/US/IBDQ ETF/US/IBDR ETF/US/IBDS @@ -1906,10 +3070,18 @@ ETF/US/IBDW ETF/US/IBDX ETF/US/IBDY ETF/US/IBDZ +ETF/US/IBET +ETF/US/IBFR ETF/US/IBGA ETF/US/IBGB +ETF/US/IBGC ETF/US/IBGK ETF/US/IBGL +ETF/US/IBGM +ETF/US/IBHA +ETF/US/IBHB +ETF/US/IBHC +ETF/US/IBHD ETF/US/IBHE ETF/US/IBHF ETF/US/IBHG @@ -1918,6 +3090,8 @@ ETF/US/IBHI ETF/US/IBHJ ETF/US/IBHK ETF/US/IBHL +ETF/US/IBHM +ETF/US/IBIA ETF/US/IBIB ETF/US/IBIC ETF/US/IBID @@ -1929,8 +3103,15 @@ ETF/US/IBII ETF/US/IBIJ ETF/US/IBIK ETF/US/IBIL +ETF/US/IBIM ETF/US/IBIT ETF/US/IBLC +ETF/US/IBMH +ETF/US/IBMI +ETF/US/IBMJ +ETF/US/IBMK +ETF/US/IBML +ETF/US/IBMM ETF/US/IBMN ETF/US/IBMO ETF/US/IBMP @@ -1938,9 +3119,16 @@ ETF/US/IBMQ ETF/US/IBMR ETF/US/IBMS ETF/US/IBMT +ETF/US/IBMU +ETF/US/IBMV +ETF/US/IBMW +ETF/US/IBMX ETF/US/IBND ETF/US/IBOT ETF/US/IBRN +ETF/US/IBTA +ETF/US/IBTB +ETF/US/IBTD ETF/US/IBTE ETF/US/IBTF ETF/US/IBTG @@ -1953,24 +3141,38 @@ ETF/US/IBTM ETF/US/IBTO ETF/US/IBTP ETF/US/IBTQ +ETF/US/IBTR ETF/US/IBUF ETF/US/IBUY +ETF/US/IBX ETF/US/ICAP ETF/US/ICF ETF/US/ICLN ETF/US/ICLO +ETF/US/ICOI +ETF/US/ICOL ETF/US/ICOP ETF/US/ICOW +ETF/US/ICPI +ETF/US/ICPY +ETF/US/ICRC ETF/US/ICSH ETF/US/ICVT ETF/US/IDAT ETF/US/IDE ETF/US/IDEC +ETF/US/IDEF +ETF/US/IDEQ ETF/US/IDEV ETF/US/IDGT +ETF/US/IDHD ETF/US/IDHQ +ETF/US/IDIV +ETF/US/IDJN +ETF/US/IDLB ETF/US/IDLV ETF/US/IDMO +ETF/US/IDMY ETF/US/IDNA ETF/US/IDOG ETF/US/IDRV @@ -1978,22 +3180,40 @@ ETF/US/IDU ETF/US/IDUB ETF/US/IDV ETF/US/IDVO +ETF/US/IDVY ETF/US/IDVZ ETF/US/IDX +ETF/US/IDY +ETF/US/IDYN +ETF/US/IECS ETF/US/IEDI ETF/US/IEF ETF/US/IEFA +ETF/US/IEFN +ETF/US/IEHS ETF/US/IEI +ETF/US/IEIH +ETF/US/IEMD +ETF/US/IEME ETF/US/IEMG +ETF/US/IEMV ETF/US/IEO +ETF/US/IEQ ETF/US/IETC +ETF/US/IETH ETF/US/IEUR ETF/US/IEUS ETF/US/IEV ETF/US/IEZ ETF/US/IFEB ETF/US/IFED +ETF/US/IFEU ETF/US/IFGL +ETF/US/IFIX +ETF/US/IFLN +ETF/US/IFLO +ETF/US/IFLR +ETF/US/IFLY ETF/US/IFN ETF/US/IFRA ETF/US/IFV @@ -2005,12 +3225,16 @@ ETF/US/IGD ETF/US/IGE ETF/US/IGEB ETF/US/IGF +ETF/US/IGGY ETF/US/IGHG ETF/US/IGI ETF/US/IGIB +ETF/US/IGIH ETF/US/IGLB ETF/US/IGLD ETF/US/IGM +ETF/US/IGME +ETF/US/IGN ETF/US/IGOV ETF/US/IGPT ETF/US/IGR @@ -2018,16 +3242,23 @@ ETF/US/IGRO ETF/US/IGSB ETF/US/IGTR ETF/US/IGV +ETF/US/IGVT ETF/US/IHAK ETF/US/IHD ETF/US/IHDG ETF/US/IHE ETF/US/IHF ETF/US/IHI +ETF/US/IHIT +ETF/US/IHTA ETF/US/IHY +ETF/US/IHYD ETF/US/IHYF +ETF/US/IHYV +ETF/US/IID ETF/US/IIF ETF/US/IIGD +ETF/US/IIGV ETF/US/IIM ETF/US/IJAN ETF/US/IJH @@ -2054,43 +3285,67 @@ ETF/US/IMCG ETF/US/IMCV ETF/US/IMED ETF/US/IMF +ETF/US/IMFC +ETF/US/IMFD +ETF/US/IMFI ETF/US/IMFL +ETF/US/IMFP +ETF/US/IMLP ETF/US/IMOM +ETF/US/IMRA ETF/US/IMSI +ETF/US/IMST ETF/US/IMTB +ETF/US/IMTG ETF/US/IMTM +ETF/US/IMVP +ETF/US/INAG +ETF/US/INAU +ETF/US/INAV +ETF/US/INC ETF/US/INCE ETF/US/INCM ETF/US/INCO +ETF/US/IND ETF/US/INDA ETF/US/INDE ETF/US/INDF ETF/US/INDH ETF/US/INDL +ETF/US/INDQ ETF/US/INDS ETF/US/INDY +ETF/US/INDZ ETF/US/INEQ ETF/US/INFL ETF/US/INFR ETF/US/INKM ETF/US/INMU +ETF/US/INNO ETF/US/INQQ +ETF/US/INR ETF/US/INRO ETF/US/INSI ETF/US/INTF ETF/US/INTL ETF/US/INTW +ETF/US/INVG ETF/US/INVN +ETF/US/INYY ETF/US/IOCT ETF/US/ION ETF/US/IONL ETF/US/IONX +ETF/US/IONZ ETF/US/IOO ETF/US/IOPP +ETF/US/IOYY ETF/US/IPAC ETF/US/IPAV ETF/US/IPAY ETF/US/IPDP +ETF/US/IPE +ETF/US/IPFF ETF/US/IPKW ETF/US/IPO ETF/US/IPOS @@ -2101,23 +3356,39 @@ ETF/US/IQDG ETF/US/IQDY ETF/US/IQHI ETF/US/IQI +ETF/US/IQIN ETF/US/IQLT ETF/US/IQM +ETF/US/IQMM ETF/US/IQQQ ETF/US/IQRA ETF/US/IQSI ETF/US/IQSM ETF/US/IQSU +ETF/US/IQSZ +ETF/US/IRBA +ETF/US/IRBO +ETF/US/IRE +ETF/US/IREG ETF/US/IRET +ETF/US/IREX +ETF/US/IREZ +ETF/US/IRHG +ETF/US/IRL ETF/US/IROC +ETF/US/IRR ETF/US/IRTR ETF/US/IRVH +ETF/US/ISBG ETF/US/ISCB ETF/US/ISCF ETF/US/ISCG ETF/US/ISCV ETF/US/ISD ETF/US/ISDB +ETF/US/ISDS +ETF/US/ISDX +ETF/US/ISEM ETF/US/ISEP ETF/US/ISHBF ETF/US/ISHG @@ -2127,15 +3398,20 @@ ETF/US/ISMD ETF/US/ISMF ETF/US/ISPY ETF/US/ISRA +ETF/US/ISSB ETF/US/ISTB +ETF/US/ISTM +ETF/US/ISUL ETF/US/ISVAF ETF/US/ISVL ETF/US/ISVUF ETF/US/ISVVF ETF/US/ISWN +ETF/US/ISZE ETF/US/ITA ETF/US/ITAN ETF/US/ITB +ETF/US/ITDA ETF/US/ITDB ETF/US/ITDC ETF/US/ITDD @@ -2145,17 +3421,25 @@ ETF/US/ITDG ETF/US/ITDH ETF/US/ITDI ETF/US/ITDJ +ETF/US/ITE ETF/US/ITEQ ETF/US/ITM +ETF/US/ITOL ETF/US/ITOT ETF/US/ITWO ETF/US/IUS ETF/US/IUSB ETF/US/IUSG +ETF/US/IUSS ETF/US/IUSV ETF/US/IVAL +ETF/US/IVDG ETF/US/IVE ETF/US/IVEG +ETF/US/IVEP +ETF/US/IVES +ETF/US/IVH +ETF/US/IVLC ETF/US/IVLU ETF/US/IVOG ETF/US/IVOL @@ -2163,6 +3447,10 @@ ETF/US/IVOO ETF/US/IVOV ETF/US/IVRA ETF/US/IVRS +ETF/US/IVSG +ETF/US/IVSI +ETF/US/IVSS +ETF/US/IVSX ETF/US/IVV ETF/US/IVVB ETF/US/IVVM @@ -2174,7 +3462,9 @@ ETF/US/IWD ETF/US/IWDL ETF/US/IWF ETF/US/IWFG +ETF/US/IWFH ETF/US/IWFL +ETF/US/IWIN ETF/US/IWL ETF/US/IWLG ETF/US/IWM @@ -2196,6 +3486,7 @@ ETF/US/IXG ETF/US/IXJ ETF/US/IXN ETF/US/IXP +ETF/US/IXSE ETF/US/IXUS ETF/US/IYC ETF/US/IYE @@ -2213,11 +3504,17 @@ ETF/US/IYW ETF/US/IYY ETF/US/IYZ ETF/US/IZRL +ETF/US/JA ETF/US/JAAA +ETF/US/JABS +ETF/US/JADB ETF/US/JADE +ETF/US/JAGG ETF/US/JAJL +ETF/US/JANB ETF/US/JAND ETF/US/JANH +ETF/US/JANI ETF/US/JANJ ETF/US/JANM ETF/US/JANP @@ -2226,20 +3523,29 @@ ETF/US/JANT ETF/US/JANU ETF/US/JANW ETF/US/JANZ +ETF/US/JAPN ETF/US/JAVA ETF/US/JBBB ETF/US/JBND +ETF/US/JCC ETF/US/JCE ETF/US/JCHI +ETF/US/JCO ETF/US/JCPB ETF/US/JCPI ETF/US/JCTR +ETF/US/JDD ETF/US/JDIV ETF/US/JDOC ETF/US/JDST ETF/US/JDVI +ETF/US/JDVL +ETF/US/JEDI +ETF/US/JELH +ETF/US/JELM ETF/US/JEMA ETF/US/JEMB +ETF/US/JEMD ETF/US/JEPI ETF/US/JEPQ ETF/US/JEPY @@ -2248,79 +3554,150 @@ ETF/US/JETD ETF/US/JETS ETF/US/JETU ETF/US/JFLI +ETF/US/JFLX ETF/US/JFR ETF/US/JFWD ETF/US/JGH +ETF/US/JGLD ETF/US/JGLO ETF/US/JGRO ETF/US/JGRW +ETF/US/JHAA ETF/US/JHAC +ETF/US/JHAI +ETF/US/JHB ETF/US/JHCB ETF/US/JHCP ETF/US/JHCR +ETF/US/JHCS +ETF/US/JHDG ETF/US/JHDV ETF/US/JHEM ETF/US/JHHY ETF/US/JHI ETF/US/JHID +ETF/US/JHLN +ETF/US/JHMA ETF/US/JHMB +ETF/US/JHMC ETF/US/JHMD +ETF/US/JHME +ETF/US/JHMF +ETF/US/JHMH +ETF/US/JHMI ETF/US/JHML ETF/US/JHMM +ETF/US/JHMS +ETF/US/JHMT ETF/US/JHMU ETF/US/JHPI ETF/US/JHS ETF/US/JHSC +ETF/US/JIB +ETF/US/JIDA +ETF/US/JIDE ETF/US/JIG ETF/US/JIII ETF/US/JIRE +ETF/US/JJA +ETF/US/JJC +ETF/US/JJE +ETF/US/JJG +ETF/US/JJM +ETF/US/JJN +ETF/US/JJP +ETF/US/JJS +ETF/US/JJT +ETF/US/JJU +ETF/US/JKD +ETF/US/JKE +ETF/US/JKF +ETF/US/JKG +ETF/US/JKH +ETF/US/JKI +ETF/US/JKJ +ETF/US/JKK +ETF/US/JKL ETF/US/JLQD ETF/US/JLS ETF/US/JMBS ETF/US/JMEE ETF/US/JMHI ETF/US/JMID +ETF/US/JMIN ETF/US/JMM +ETF/US/JMMF ETF/US/JMOM ETF/US/JMSI ETF/US/JMST +ETF/US/JMTG ETF/US/JMUB ETF/US/JNEU ETF/US/JNK +ETF/US/JNMF ETF/US/JNUG +ETF/US/JO +ETF/US/JOBX ETF/US/JOET ETF/US/JOF ETF/US/JOJO +ETF/US/JOUL +ETF/US/JOYT +ETF/US/JOYY ETF/US/JPAN ETF/US/JPC +ETF/US/JPED ETF/US/JPEF ETF/US/JPEM +ETF/US/JPEU +ETF/US/JPFP +ETF/US/JPGB +ETF/US/JPGE +ETF/US/JPHF +ETF/US/JPHY ETF/US/JPI ETF/US/JPIB ETF/US/JPIE ETF/US/JPIN ETF/US/JPLD +ETF/US/JPLS ETF/US/JPMB ETF/US/JPME +ETF/US/JPMF ETF/US/JPMO +ETF/US/JPMV +ETF/US/JPN +ETF/US/JPNL ETF/US/JPRE +ETF/US/JPS ETF/US/JPSE ETF/US/JPST ETF/US/JPSV +ETF/US/JPT ETF/US/JPUS +ETF/US/JPX ETF/US/JPXN +ETF/US/JPY ETF/US/JQC ETF/US/JQUA ETF/US/JRE ETF/US/JRI +ETF/US/JRNY +ETF/US/JRO ETF/US/JRS ETF/US/JSCP +ETF/US/JSD ETF/US/JSI ETF/US/JSMD ETF/US/JSML ETF/US/JSTC +ETF/US/JTA +ETF/US/JTD ETF/US/JTEK ETF/US/JUCY +ETF/US/JUDB +ETF/US/JUDO +ETF/US/JULB ETF/US/JULD ETF/US/JULH ETF/US/JULJ @@ -2331,6 +3708,7 @@ ETF/US/JULT ETF/US/JULU ETF/US/JULW ETF/US/JULZ +ETF/US/JUNC ETF/US/JUNM ETF/US/JUNP ETF/US/JUNT @@ -2341,57 +3719,98 @@ ETF/US/JUST ETF/US/JVAL ETF/US/JXI ETF/US/JXX +ETF/US/JZRO ETF/US/KALL +ETF/US/KAMO ETF/US/KAPR +ETF/US/KARB ETF/US/KARS +ETF/US/KAT ETF/US/KAUG ETF/US/KBA ETF/US/KBAB ETF/US/KBDC +ETF/US/KBDU ETF/US/KBE +ETF/US/KBFR +ETF/US/KBND ETF/US/KBUF +ETF/US/KBUY ETF/US/KBWB ETF/US/KBWD ETF/US/KBWP ETF/US/KBWR ETF/US/KBWY ETF/US/KCAI +ETF/US/KCAL ETF/US/KCCA +ETF/US/KCCB ETF/US/KCE +ETF/US/KCNY +ETF/US/KCOP ETF/US/KCSH ETF/US/KDEC ETF/US/KDEF +ETF/US/KDFI +ETF/US/KDIV ETF/US/KDRN +ETF/US/KDVD ETF/US/KEAT +ETF/US/KEEX +ETF/US/KEJI ETF/US/KEMQ ETF/US/KEMX +ETF/US/KESG ETF/US/KEUA ETF/US/KF ETF/US/KFEB +ETF/US/KFVG +ETF/US/KFYP +ETF/US/KGHG +ETF/US/KGLD ETF/US/KGRN +ETF/US/KGRO ETF/US/KHPI ETF/US/KHYB ETF/US/KIE ETF/US/KIO +ETF/US/KIQQ ETF/US/KJAN +ETF/US/KJD ETF/US/KJUL ETF/US/KJUN +ETF/US/KLAG +ETF/US/KLCD +ETF/US/KLDW ETF/US/KLIP ETF/US/KLMN ETF/US/KLMT +ETF/US/KLNE ETF/US/KLXY ETF/US/KMAR +ETF/US/KMAY +ETF/US/KMCA +ETF/US/KMED +ETF/US/KMET +ETF/US/KMF ETF/US/KMID +ETF/US/KMLI ETF/US/KMLM +ETF/US/KNAB ETF/US/KNCT ETF/US/KNG +ETF/US/KNGS ETF/US/KNGZ ETF/US/KNO ETF/US/KNOV ETF/US/KNOW +ETF/US/KNRG ETF/US/KOCG ETF/US/KOCT +ETF/US/KOID +ETF/US/KOIN ETF/US/KOKU +ETF/US/KOL ETF/US/KOLD ETF/US/KOMP ETF/US/KONG @@ -2399,6 +3818,7 @@ ETF/US/KOOL ETF/US/KORP ETF/US/KORU ETF/US/KPDD +ETF/US/KPHO ETF/US/KPOP ETF/US/KPRO ETF/US/KQQQ @@ -2408,34 +3828,55 @@ ETF/US/KRMA ETF/US/KRNIF ETF/US/KROP ETF/US/KRUZ +ETF/US/KRWX +ETF/US/KRYP ETF/US/KSA +ETF/US/KSCD ETF/US/KSEA ETF/US/KSEP +ETF/US/KSET +ETF/US/KSLV +ETF/US/KSM ETF/US/KSPY ETF/US/KSTR ETF/US/KTEC ETF/US/KTF +ETF/US/KTUP ETF/US/KURE ETF/US/KVLE ETF/US/KWEB +ETF/US/KWIN ETF/US/KWT ETF/US/KXI +ETF/US/KYC +ETF/US/KYLD ETF/US/KYN ETF/US/LABD ETF/US/LABU +ETF/US/LABX +ETF/US/LACG +ETF/US/LACK ETF/US/LALT ETF/US/LAPR +ETF/US/LATR ETF/US/LAYS ETF/US/LBAY +ETF/US/LBDC +ETF/US/LBJ ETF/US/LBO ETF/US/LCAP +ETF/US/LCDL ETF/US/LCDS ETF/US/LCF ETF/US/LCG +ETF/US/LCIZ ETF/US/LCLG +ETF/US/LCO +ETF/US/LCOW ETF/US/LCR ETF/US/LCTD ETF/US/LCTU +ETF/US/LD ETF/US/LDDR ETF/US/LDEM ETF/US/LDER @@ -2444,14 +3885,19 @@ ETF/US/LDRC ETF/US/LDRH ETF/US/LDRI ETF/US/LDRR +ETF/US/LDRS ETF/US/LDRT +ETF/US/LDRX ETF/US/LDSF ETF/US/LDUR ETF/US/LEAD ETF/US/LEGR ETF/US/LEMB +ETF/US/LEND ETF/US/LENS ETF/US/LEO +ETF/US/LETB +ETF/US/LEUX ETF/US/LEXI ETF/US/LFAE ETF/US/LFAF @@ -2475,12 +3921,14 @@ ETF/US/LFDR ETF/US/LFEQ ETF/US/LFGY ETF/US/LFSC +ETF/US/LGBT ETF/US/LGCF ETF/US/LGDX ETF/US/LGH ETF/US/LGHT ETF/US/LGI ETF/US/LGLV +ETF/US/LGLZ ETF/US/LGOV ETF/US/LGRO ETF/US/LIAB @@ -2501,35 +3949,65 @@ ETF/US/LIAW ETF/US/LIAX ETF/US/LIAY ETF/US/LIBD +ETF/US/LIFT ETF/US/LIMI +ETF/US/LINT ETF/US/LIT +ETF/US/LITL ETF/US/LITP +ETF/US/LITU +ETF/US/LITX +ETF/US/LITZ +ETF/US/LIV ETF/US/LIVR ETF/US/LJAN +ETF/US/LJIM ETF/US/LJUL ETF/US/LKOR ETF/US/LLDR +ETF/US/LLII +ETF/US/LLQD ETF/US/LLYX +ETF/US/LLYZ ETF/US/LMBO ETF/US/LMBS +ETF/US/LMLB +ETF/US/LMLP +ETF/US/LMNX +ETF/US/LMTL +ETF/US/LMTS ETF/US/LMUB +ETF/US/LNGG +ETF/US/LNGR +ETF/US/LNGX ETF/US/LNGZ +ETF/US/LNOK ETF/US/LOCT ETF/US/LODI +ETF/US/LOGO +ETF/US/LOHA ETF/US/LONZ ETF/US/LOPP +ETF/US/LOPX +ETF/US/LOTI ETF/US/LOUP +ETF/US/LOWC ETF/US/LOWV +ETF/US/LPRE +ETF/US/LQ ETF/US/LQAI ETF/US/LQD ETF/US/LQDB ETF/US/LQDH ETF/US/LQDI +ETF/US/LQDM ETF/US/LQDW +ETF/US/LQID ETF/US/LQIG ETF/US/LQPE ETF/US/LQTI -ETF/US/LRFC +ETF/US/LRCU +ETF/US/LRET ETF/US/LRGC ETF/US/LRGE ETF/US/LRGF @@ -2540,56 +4018,96 @@ ETF/US/LSAF ETF/US/LSAT ETF/US/LSEQ ETF/US/LSGR +ETF/US/LSLT +ETF/US/LSST ETF/US/LST ETF/US/LSVD +ETF/US/LTAX +ETF/US/LTCC ETF/US/LTL ETF/US/LTPZ ETF/US/LTTI +ETF/US/LULG +ETF/US/LUNL ETF/US/LUX +ETF/US/LUXE +ETF/US/LUXX +ETF/US/LVDS +ETF/US/LVHB ETF/US/LVHD +ETF/US/LVHE ETF/US/LVHI +ETF/US/LVIG +ETF/US/LVL +ETF/US/LVLN ETF/US/LVOL +ETF/US/LVUS +ETF/US/LYFE +ETF/US/LYFX ETF/US/LYLD +ETF/US/LZRD +ETF/US/MAAX +ETF/US/MAAY ETF/US/MADE ETF/US/MAGA +ETF/US/MAGC ETF/US/MAGG +ETF/US/MAGO +ETF/US/MAGQ ETF/US/MAGS ETF/US/MAGX +ETF/US/MAGY ETF/US/MAKX ETF/US/MAMB +ETF/US/MANI ETF/US/MAPP ETF/US/MARB ETF/US/MARM ETF/US/MARO +ETF/US/MARS ETF/US/MART ETF/US/MARU ETF/US/MARW ETF/US/MARZ -ETF/US/MATH +ETF/US/MATE +ETF/US/MAUG ETF/US/MAV ETF/US/MAVF ETF/US/MAXI ETF/US/MAXJ +ETF/US/MAYC +ETF/US/MAYM ETF/US/MAYP ETF/US/MAYT ETF/US/MAYU ETF/US/MAYW ETF/US/MAYZ ETF/US/MBB +ETF/US/MBBA ETF/US/MBBB ETF/US/MBCC +ETF/US/MBCE +ETF/US/MBG ETF/US/MBND ETF/US/MBNE ETF/US/MBOX ETF/US/MBSD ETF/US/MBSF +ETF/US/MBSX +ETF/US/MCA ETF/US/MCDS +ETF/US/MCEF ETF/US/MCHI ETF/US/MCHS +ETF/US/MCHU ETF/US/MCI ETF/US/MCN +ETF/US/MCOW ETF/US/MCR +ETF/US/MCRO ETF/US/MCSE +ETF/US/MDAA +ETF/US/MDBX ETF/US/MDCP ETF/US/MDEV ETF/US/MDIV @@ -2602,80 +4120,136 @@ ETF/US/MDYV ETF/US/MEAR ETF/US/MEGI ETF/US/MEM +ETF/US/MEMA +ETF/US/MEME ETF/US/MEMX +ETF/US/MEMY +ETF/US/MEN +ETF/US/MENV ETF/US/METD +ETF/US/METL ETF/US/METU ETF/US/METV +ETF/US/METW ETF/US/MEXX +ETF/US/MFD ETF/US/MFDX +ETF/US/MFEB ETF/US/MFEM -ETF/US/MFIC +ETF/US/MFIG +ETF/US/MFL ETF/US/MFLX ETF/US/MFM +ETF/US/MFMO +ETF/US/MFMS ETF/US/MFSB ETF/US/MFSG ETF/US/MFSI ETF/US/MFSM ETF/US/MFSV +ETF/US/MFT ETF/US/MFUL ETF/US/MFUS ETF/US/MFUT +ETF/US/MFV +ETF/US/MFVL ETF/US/MGC ETF/US/MGF ETF/US/MGK +ETF/US/MGKX ETF/US/MGMT ETF/US/MGNR ETF/US/MGOV ETF/US/MGRO +ETF/US/MGU ETF/US/MGV ETF/US/MHD +ETF/US/MHE ETF/US/MHF ETF/US/MHI +ETF/US/MHIG +ETF/US/MHIP ETF/US/MHN +ETF/US/MHY ETF/US/MID ETF/US/MIDE +ETF/US/MIDF ETF/US/MIDU +ETF/US/MIDZ +ETF/US/MIE ETF/US/MIG +ETF/US/MIGO ETF/US/MILK ETF/US/MILN ETF/US/MIN +ETF/US/MINC ETF/US/MINN ETF/US/MINO ETF/US/MINT ETF/US/MINV +ETF/US/MINY ETF/US/MIO ETF/US/MISL ETF/US/MIY ETF/US/MJ +ETF/US/MJIN +ETF/US/MJJ +ETF/US/MJO +ETF/US/MJSC ETF/US/MJUS +ETF/US/MJXL ETF/US/MKAM ETF/US/MKOR +ETF/US/MKTN ETF/US/MLDR ETF/US/MLN ETF/US/MLPA ETF/US/MLPB +ETF/US/MLPC ETF/US/MLPD +ETF/US/MLPE +ETF/US/MLPG +ETF/US/MLPI +ETF/US/MLPO +ETF/US/MLPQ ETF/US/MLPR ETF/US/MLPX +ETF/US/MLPY +ETF/US/MLPZ +ETF/US/MLQD +ETF/US/MLTI ETF/US/MMAX +ETF/US/MMAY ETF/US/MMCA ETF/US/MMD +ETF/US/MMID ETF/US/MMIN ETF/US/MMIT +ETF/US/MMK ETF/US/MMKT ETF/US/MMLG +ETF/US/MMMA +ETF/US/MMSB ETF/US/MMSC +ETF/US/MMSD ETF/US/MMT ETF/US/MMTM ETF/US/MMU -ETF/US/MMV ETF/US/MNA ETF/US/MNBD +ETF/US/MNP ETF/US/MNRS ETF/US/MNTL +ETF/US/MNVR +ETF/US/MNVT +ETF/US/MNZL ETF/US/MOAT +ETF/US/MOHR +ETF/US/MOM ETF/US/MOO ETF/US/MOOD +ETF/US/MOON +ETF/US/MORL ETF/US/MORT ETF/US/MOTE ETF/US/MOTG @@ -2683,68 +4257,113 @@ ETF/US/MOTI ETF/US/MOTO ETF/US/MPA ETF/US/MPAY +ETF/US/MPG +ETF/US/MPL +ETF/US/MPLY ETF/US/MPRO ETF/US/MPV +ETF/US/MPWX ETF/US/MQQQ ETF/US/MQT ETF/US/MQY +ETF/US/MRA +ETF/US/MRAD ETF/US/MRAL ETF/US/MRCP ETF/US/MRGR +ETF/US/MRND +ETF/US/MRNX ETF/US/MRNY +ETF/US/MRRL ETF/US/MRSK +ETF/US/MRVU +ETF/US/MSBT ETF/US/MSD +ETF/US/MSDD ETF/US/MSFD ETF/US/MSFL ETF/US/MSFO ETF/US/MSFU +ETF/US/MSFW ETF/US/MSFX ETF/US/MSFY +ETF/US/MSGR +ETF/US/MSII ETF/US/MSLC ETF/US/MSMR +ETF/US/MSOO ETF/US/MSOS ETF/US/MSOX +ETF/US/MSR ETF/US/MSSM ETF/US/MSSS +ETF/US/MSST +ETF/US/MST ETF/US/MSTB ETF/US/MSTI +ETF/US/MSTK +ETF/US/MSTP ETF/US/MSTQ ETF/US/MSTU +ETF/US/MSTW ETF/US/MSTX ETF/US/MSTY ETF/US/MSTZ +ETF/US/MSUS +ETF/US/MSVX +ETF/US/MSXX ETF/US/MTBA ETF/US/MTGP +ETF/US/MTRA +ETF/US/MTT ETF/US/MTUL ETF/US/MTUM +ETF/US/MTVR +ETF/US/MTYY ETF/US/MUA ETF/US/MUB ETF/US/MUC ETF/US/MUD ETF/US/MUE +ETF/US/MUH ETF/US/MUI ETF/US/MUJ ETF/US/MULL +ETF/US/MULT +ETF/US/MUNA +ETF/US/MUNB +ETF/US/MUNC +ETF/US/MUND ETF/US/MUNI +ETF/US/MUNX +ETF/US/MUNY +ETF/US/MUS ETF/US/MUSE ETF/US/MUSI ETF/US/MUSQ ETF/US/MUST +ETF/US/MUTE ETF/US/MUU +ETF/US/MUYY ETF/US/MVAL ETF/US/MVF ETF/US/MVFD ETF/US/MVFG +ETF/US/MVIN ETF/US/MVLL +ETF/US/MVP ETF/US/MVPA ETF/US/MVPL ETF/US/MVPS ETF/US/MVRL ETF/US/MVT ETF/US/MVV +ETF/US/MXDE +ETF/US/MXDU ETF/US/MXE ETF/US/MXF ETF/US/MXI +ETF/US/MYC ETF/US/MYCF ETF/US/MYCG ETF/US/MYCH @@ -2754,16 +4373,26 @@ ETF/US/MYCK ETF/US/MYCL ETF/US/MYCM ETF/US/MYCN +ETF/US/MYCO ETF/US/MYD +ETF/US/MYF +ETF/US/MYHA +ETF/US/MYHB +ETF/US/MYHC +ETF/US/MYHD +ETF/US/MYHE ETF/US/MYI +ETF/US/MYJ ETF/US/MYLD ETF/US/MYMF ETF/US/MYMG ETF/US/MYMH ETF/US/MYMI ETF/US/MYMJ +ETF/US/MYMK ETF/US/MYN ETF/US/MYY +ETF/US/MZA ETF/US/MZZ ETF/US/NAC ETF/US/NACP @@ -2773,6 +4402,7 @@ ETF/US/NAN ETF/US/NANC ETF/US/NANR ETF/US/NAPR +ETF/US/NASA ETF/US/NATO ETF/US/NAUG ETF/US/NAZ @@ -2780,19 +4410,28 @@ ETF/US/NBB ETF/US/NBCE ETF/US/NBCM ETF/US/NBCR +ETF/US/NBCT ETF/US/NBDS ETF/US/NBET ETF/US/NBFC +ETF/US/NBFR ETF/US/NBGR ETF/US/NBGX ETF/US/NBH +ETF/US/NBIE +ETF/US/NBIG +ETF/US/NBIL +ETF/US/NBIZ ETF/US/NBJP +ETF/US/NBO ETF/US/NBOS ETF/US/NBSD ETF/US/NBSM ETF/US/NBTR +ETF/US/NBW ETF/US/NBXG ETF/US/NCA +ETF/US/NCB ETF/US/NCIQ ETF/US/NCLO ETF/US/NCPB @@ -2802,91 +4441,153 @@ ETF/US/NDAA ETF/US/NDEC ETF/US/NDIA ETF/US/NDIV +ETF/US/NDJI ETF/US/NDMO ETF/US/NDOW ETF/US/NDP ETF/US/NDVG ETF/US/NEA ETF/US/NEAR +ETF/US/NEBX +ETF/US/NEED +ETF/US/NEHI +ETF/US/NELS +ETF/US/NEMD +ETF/US/NEMG ETF/US/NERD +ETF/US/NETG ETF/US/NETL +ETF/US/NETX ETF/US/NETZ +ETF/US/NEV ETF/US/NEWZ ETF/US/NFEB ETF/US/NFJ ETF/US/NFLP ETF/US/NFLT ETF/US/NFLU +ETF/US/NFLW ETF/US/NFLY +ETF/US/NFO ETF/US/NFRA +ETF/US/NFRX ETF/US/NFTY +ETF/US/NFTZ ETF/US/NFXL ETF/US/NFXS +ETF/US/NGE +ETF/US/NGHT +ETF/US/NGIF +ETF/US/NHA +ETF/US/NHF ETF/US/NHS +ETF/US/NHYB ETF/US/NHYM +ETF/US/NIB +ETF/US/NICO +ETF/US/NID ETF/US/NIE +ETF/US/NIFE +ETF/US/NIHI ETF/US/NIKL ETF/US/NIM +ETF/US/NIOG +ETF/US/NIQ +ETF/US/NISM ETF/US/NITE +ETF/US/NIWM ETF/US/NIXT ETF/US/NJAN ETF/US/NJNK ETF/US/NJUL ETF/US/NJUN +ETF/US/NJV +ETF/US/NKEL +ETF/US/NKEQ +ETF/US/NKG ETF/US/NKX ETF/US/NLR +ETF/US/NLSI ETF/US/NMAI ETF/US/NMAR +ETF/US/NMAY ETF/US/NMB +ETF/US/NMBL ETF/US/NMCO ETF/US/NMI ETF/US/NML ETF/US/NMS ETF/US/NMT +ETF/US/NMY ETF/US/NMZ +ETF/US/NNEX ETF/US/NNOV ETF/US/NNY ETF/US/NOBL ETF/US/NOCT +ETF/US/NODE +ETF/US/NOEQ ETF/US/NOM +ETF/US/NOPE ETF/US/NORW ETF/US/NOVM ETF/US/NOVP ETF/US/NOVZ +ETF/US/NOWL ETF/US/NPCT ETF/US/NPFD +ETF/US/NPFE ETF/US/NPFI +ETF/US/NPN ETF/US/NPV ETF/US/NQP ETF/US/NRES ETF/US/NRGD +ETF/US/NRGO ETF/US/NRGU +ETF/US/NRGZ ETF/US/NRK ETF/US/NRO ETF/US/NRSH +ETF/US/NSCI ETF/US/NSCR ETF/US/NSCS ETF/US/NSEP ETF/US/NSI +ETF/US/NSL +ETF/US/NSPI +ETF/US/NSPL +ETF/US/NSPY ETF/US/NTG +ETF/US/NTKI +ETF/US/NTRL +ETF/US/NTSD ETF/US/NTSE ETF/US/NTSI ETF/US/NTSX +ETF/US/NTZG +ETF/US/NTZO ETF/US/NUAG ETF/US/NUBD +ETF/US/NUDG ETF/US/NUDM ETF/US/NUDV ETF/US/NUEM +ETF/US/NUG ETF/US/NUGO ETF/US/NUGT +ETF/US/NUGY ETF/US/NUHY +ETF/US/NUKX ETF/US/NUKZ ETF/US/NULC ETF/US/NULG ETF/US/NULV +ETF/US/NUM ETF/US/NUMG ETF/US/NUMI ETF/US/NUMV +ETF/US/NUO ETF/US/NURE ETF/US/NUSA ETF/US/NUSB @@ -2898,9 +4599,11 @@ ETF/US/NVBT ETF/US/NVBU ETF/US/NVBW ETF/US/NVD +ETF/US/NVDB ETF/US/NVDD ETF/US/NVDG ETF/US/NVDL +ETF/US/NVDO ETF/US/NVDQ ETF/US/NVDS ETF/US/NVDU @@ -2908,28 +4611,50 @@ ETF/US/NVDW ETF/US/NVDX ETF/US/NVDY ETF/US/NVG +ETF/US/NVII ETF/US/NVIR +ETF/US/NVIT +ETF/US/NVMZ ETF/US/NVOH ETF/US/NVOX +ETF/US/NVQ +ETF/US/NVTX ETF/US/NVW +ETF/US/NVYY ETF/US/NWLG +ETF/US/NWMX ETF/US/NXC -ETF/US/NXDT ETF/US/NXG ETF/US/NXJ ETF/US/NXN ETF/US/NXP +ETF/US/NXPG +ETF/US/NXPX +ETF/US/NXQ +ETF/US/NXR ETF/US/NXTE ETF/US/NXTG ETF/US/NXTI ETF/US/NXTV +ETF/US/NXUS ETF/US/NYF +ETF/US/NYM +ETF/US/NYNY +ETF/US/NYSX +ETF/US/NYV +ETF/US/NYYY ETF/US/NZAC ETF/US/NZF +ETF/US/NZRO ETF/US/NZUS ETF/US/OACP ETF/US/OAEM +ETF/US/OAIA +ETF/US/OAIB +ETF/US/OAIE ETF/US/OAIM +ETF/US/OAKG +ETF/US/OAKI ETF/US/OAKM ETF/US/OALC ETF/US/OARK @@ -2938,10 +4663,13 @@ ETF/US/OBIL ETF/US/OBND ETF/US/OBOR ETF/US/OBTC +ETF/US/OCDB ETF/US/OCEN ETF/US/OCFS ETF/US/OCIO +ETF/US/OCSI ETF/US/OCTA +ETF/US/OCTB ETF/US/OCTD ETF/US/OCTH ETF/US/OCTJ @@ -2953,38 +4681,77 @@ ETF/US/OCTU ETF/US/OCTW ETF/US/OCTZ ETF/US/ODDS +ETF/US/ODDZ +ETF/US/ODHY +ETF/US/ODTE ETF/US/OEF +ETF/US/OEFA +ETF/US/OEI ETF/US/OEUR ETF/US/OFOS ETF/US/OGIG ETF/US/OGSP ETF/US/OIA ETF/US/OIH +ETF/US/OIL ETF/US/OILD ETF/US/OILK ETF/US/OILU +ETF/US/OILX +ETF/US/OKLL +ETF/US/OKLS +ETF/US/OKTG +ETF/US/OKTX +ETF/US/OLD +ETF/US/OLEM ETF/US/OMAH ETF/US/OMFL ETF/US/OMFS +ETF/US/OMOM ETF/US/OND +ETF/US/ONDG +ETF/US/ONDL +ETF/US/ONDU +ETF/US/ONEH ETF/US/ONEO ETF/US/ONEQ ETF/US/ONEV ETF/US/ONEY ETF/US/ONEZ +ETF/US/ONG ETF/US/ONLN ETF/US/ONOF +ETF/US/ONX +ETF/US/OOK ETF/US/OOQB ETF/US/OOSB ETF/US/OOSP ETF/US/OOTO +ETF/US/OPEG ETF/US/OPER +ETF/US/OPEX ETF/US/OPP +ETF/US/OPPE +ETF/US/OPPJ +ETF/US/OPPX ETF/US/OPTZ +ETF/US/OQAL +ETF/US/ORBX +ETF/US/ORCS +ETF/US/ORCU ETF/US/ORCX +ETF/US/ORFN +ETF/US/ORG +ETF/US/ORLG +ETF/US/ORO ETF/US/ORR +ETF/US/OSCG ETF/US/OSCV +ETF/US/OSCX ETF/US/OSEA +ETF/US/OSIZ +ETF/US/OSSL +ETF/US/OTGL ETF/US/OUNZ ETF/US/OUSA ETF/US/OUSM @@ -2992,19 +4759,25 @@ ETF/US/OVB ETF/US/OVF ETF/US/OVL ETF/US/OVLH +ETF/US/OVLU ETF/US/OVM +ETF/US/OVOL ETF/US/OVS ETF/US/OVT +ETF/US/OWN ETF/US/OWNB ETF/US/OWNS ETF/US/OXLC -ETF/US/OZ +ETF/US/OYLD ETF/US/OZEM ETF/US/PAAA +ETF/US/PAAU ETF/US/PAB ETF/US/PABD ETF/US/PABU +ETF/US/PACA ETF/US/PAI +ETF/US/PAK ETF/US/PALC ETF/US/PALD ETF/US/PALL @@ -3013,17 +4786,25 @@ ETF/US/PAMC ETF/US/PANG ETF/US/PAPI ETF/US/PAPR +ETF/US/PASS ETF/US/PATN +ETF/US/PATX ETF/US/PAUG ETF/US/PAVE ETF/US/PAWZ ETF/US/PAXS +ETF/US/PAYH +ETF/US/PAYM +ETF/US/PAYR ETF/US/PBAP ETF/US/PBAU ETF/US/PBD ETF/US/PBDC ETF/US/PBDE +ETF/US/PBDM ETF/US/PBE +ETF/US/PBEE +ETF/US/PBEU ETF/US/PBFB ETF/US/PBFR ETF/US/PBJ @@ -3033,39 +4814,59 @@ ETF/US/PBJN ETF/US/PBL ETF/US/PBMR ETF/US/PBMY +ETF/US/PBND ETF/US/PBNV ETF/US/PBOC +ETF/US/PBOG +ETF/US/PBOT ETF/US/PBP +ETF/US/PBPH ETF/US/PBQQ +ETF/US/PBRG ETF/US/PBSE +ETF/US/PBSM ETF/US/PBTP +ETF/US/PBUG ETF/US/PBUS ETF/US/PBW ETF/US/PCCE +ETF/US/PCEB ETF/US/PCEF ETF/US/PCEM ETF/US/PCF ETF/US/PCFI ETF/US/PCGG ETF/US/PCHI +ETF/US/PCI ETF/US/PCIG ETF/US/PCK +ETF/US/PCL +ETF/US/PCLC +ETF/US/PCLG +ETF/US/PCLN ETF/US/PCLO ETF/US/PCM ETF/US/PCMM ETF/US/PCN +ETF/US/PCPI ETF/US/PCQ +ETF/US/PCR ETF/US/PCRB +ETF/US/PCS +ETF/US/PCSG ETF/US/PCY ETF/US/PDBA ETF/US/PDBC +ETF/US/PDDL ETF/US/PDEC +ETF/US/PDEV ETF/US/PDI ETF/US/PDN ETF/US/PDP ETF/US/PDT ETF/US/PDX ETF/US/PEJ +ETF/US/PEK ETF/US/PEMX ETF/US/PEO ETF/US/PEPS @@ -3075,7 +4876,10 @@ ETF/US/PEXL ETF/US/PEY ETF/US/PEZ ETF/US/PFD +ETF/US/PFDE ETF/US/PFEB +ETF/US/PFEL +ETF/US/PFES ETF/US/PFF ETF/US/PFFA ETF/US/PFFD @@ -3090,13 +4894,17 @@ ETF/US/PFLD ETF/US/PFM ETF/US/PFN ETF/US/PFO +ETF/US/PFOE ETF/US/PFRL ETF/US/PFUT ETF/US/PFXF +ETF/US/PGAL ETF/US/PGF ETF/US/PGHY ETF/US/PGJ +ETF/US/PGM ETF/US/PGP +ETF/US/PGRI ETF/US/PGRO ETF/US/PGX ETF/US/PGZ @@ -3114,6 +4922,7 @@ ETF/US/PICB ETF/US/PICK ETF/US/PID ETF/US/PIE +ETF/US/PIEL ETF/US/PIEQ ETF/US/PIFI ETF/US/PILL @@ -3131,50 +4940,96 @@ ETF/US/PJFM ETF/US/PJFV ETF/US/PJIO ETF/US/PJP +ETF/US/PJU ETF/US/PJUL ETF/US/PJUN +ETF/US/PJUS ETF/US/PKB +ETF/US/PKO ETF/US/PKW +ETF/US/PLA +ETF/US/PLAT +ETF/US/PLC +ETF/US/PLCY ETF/US/PLDR +ETF/US/PLGI +ETF/US/PLOO +ETF/US/PLRG +ETF/US/PLT +ETF/US/PLTA ETF/US/PLTD +ETF/US/PLTG +ETF/US/PLTI +ETF/US/PLTL ETF/US/PLTM ETF/US/PLTU ETF/US/PLTW ETF/US/PLTY +ETF/US/PLTZ +ETF/US/PLU +ETF/US/PLUL +ETF/US/PLYY ETF/US/PMAP ETF/US/PMAR +ETF/US/PMAU ETF/US/PMAY ETF/US/PMBS +ETF/US/PMDE ETF/US/PMF ETF/US/PMFB ETF/US/PMIO ETF/US/PMJA +ETF/US/PMJL +ETF/US/PMJN ETF/US/PML ETF/US/PMM ETF/US/PMMF ETF/US/PMMR -ETF/US/PMN +ETF/US/PMMY +ETF/US/PMNV ETF/US/PMO +ETF/US/PMOC +ETF/US/PMOM +ETF/US/PMR +ETF/US/PMSE ETF/US/PMX ETF/US/PNF ETF/US/PNI ETF/US/PNOV ETF/US/PNQI ETF/US/POCT +ETF/US/POEL +ETF/US/PONX +ETF/US/POTX +ETF/US/POW ETF/US/POWA +ETF/US/POWR ETF/US/PP ETF/US/PPA +ETF/US/PPDM ETF/US/PPEM ETF/US/PPH ETF/US/PPIE +ETF/US/PPLC +ETF/US/PPLN ETF/US/PPLT +ETF/US/PPMC +ETF/US/PPR +ETF/US/PPSC ETF/US/PPT ETF/US/PPTY ETF/US/PQAP ETF/US/PQDI +ETF/US/PQIN ETF/US/PQJA ETF/US/PQJL +ETF/US/PQLC +ETF/US/PQNT ETF/US/PQOC +ETF/US/PQSG +ETF/US/PQSV +ETF/US/PQUS +ETF/US/PRAB ETF/US/PRAE ETF/US/PRAY ETF/US/PRCS @@ -3182,11 +5037,21 @@ ETF/US/PREF ETF/US/PRF ETF/US/PRFD ETF/US/PRFZ +ETF/US/PRID ETF/US/PRIV +ETF/US/PRIZ +ETF/US/PRME ETF/US/PRMN +ETF/US/PRMR ETF/US/PRN ETF/US/PRNT +ETF/US/PRSD +ETF/US/PRTO ETF/US/PRVS +ETF/US/PRVT +ETF/US/PRXG +ETF/US/PRXV +ETF/US/PSAI ETF/US/PSC ETF/US/PSCC ETF/US/PSCD @@ -3202,6 +5067,7 @@ ETF/US/PSCU ETF/US/PSCW ETF/US/PSCX ETF/US/PSDM +ETF/US/PSDN ETF/US/PSEP ETF/US/PSET ETF/US/PSF @@ -3211,14 +5077,18 @@ ETF/US/PSFJ ETF/US/PSFM ETF/US/PSFO ETF/US/PSH -ETF/US/PSHZF ETF/US/PSI ETF/US/PSIL ETF/US/PSK ETF/US/PSL ETF/US/PSLV +ETF/US/PSM +ETF/US/PSMB +ETF/US/PSMC ETF/US/PSMD +ETF/US/PSMG ETF/US/PSMJ +ETF/US/PSMM ETF/US/PSMO ETF/US/PSMR ETF/US/PSP @@ -3229,7 +5099,10 @@ ETF/US/PSR ETF/US/PST ETF/US/PSTP ETF/US/PSTR +ETF/US/PSUS ETF/US/PSWD +ETF/US/PSY +ETF/US/PSYK ETF/US/PTA ETF/US/PTBD ETF/US/PTEC @@ -3247,10 +5120,12 @@ ETF/US/PTY ETF/US/PUI ETF/US/PULS ETF/US/PULT +ETF/US/PUNK ETF/US/PUSH ETF/US/PUTD ETF/US/PUTW ETF/US/PVAL +ETF/US/PVEX ETF/US/PVI ETF/US/PWB ETF/US/PWRD @@ -3261,30 +5136,55 @@ ETF/US/PXE ETF/US/PXF ETF/US/PXH ETF/US/PXI +ETF/US/PXIU ETF/US/PXJ +ETF/US/PXUS ETF/US/PY ETF/US/PYLD ETF/US/PYN +ETF/US/PYPE +ETF/US/PYPG +ETF/US/PYPS +ETF/US/PYPT +ETF/US/PYPU ETF/US/PYPY ETF/US/PYZ ETF/US/PZA ETF/US/PZC +ETF/US/PZD +ETF/US/PZIV +ETF/US/PZLV ETF/US/PZT ETF/US/QABA ETF/US/QAI +ETF/US/QALT ETF/US/QARP ETF/US/QAT +ETF/US/QB ETF/US/QBER ETF/US/QBF +ETF/US/QBIF ETF/US/QBIG +ETF/US/QBIV +ETF/US/QBKF +ETF/US/QBKV +ETF/US/QBQF +ETF/US/QBQV +ETF/US/QBSF +ETF/US/QBSV +ETF/US/QBTX +ETF/US/QBTZ ETF/US/QBUF ETF/US/QBUL +ETF/US/QBY ETF/US/QCAP ETF/US/QCJA ETF/US/QCJL ETF/US/QCLN ETF/US/QCLR +ETF/US/QCMD ETF/US/QCML +ETF/US/QCMU ETF/US/QCOC ETF/US/QCON ETF/US/QDCC @@ -3296,12 +5196,20 @@ ETF/US/QDTE ETF/US/QDTY ETF/US/QDVO ETF/US/QDWN +ETF/US/QDXU +ETF/US/QDYN +ETF/US/QED ETF/US/QEFA ETF/US/QEMM ETF/US/QETH +ETF/US/QEW +ETF/US/QFHD ETF/US/QFLR +ETF/US/QFRD +ETF/US/QGRD ETF/US/QGRO ETF/US/QGRW +ETF/US/QGTA ETF/US/QHDG ETF/US/QHY ETF/US/QID @@ -3309,9 +5217,12 @@ ETF/US/QIDX ETF/US/QIG ETF/US/QINT ETF/US/QIS +ETF/US/QJN ETF/US/QJUN ETF/US/QLC ETF/US/QLD +ETF/US/QLDY +ETF/US/QLS ETF/US/QLTA ETF/US/QLTI ETF/US/QLV @@ -3321,19 +5232,30 @@ ETF/US/QMAG ETF/US/QMAR ETF/US/QMFE ETF/US/QMID +ETF/US/QMJ ETF/US/QMMY +ETF/US/QMN ETF/US/QMNV ETF/US/QMOM +ETF/US/QMY ETF/US/QNXT ETF/US/QOWZ ETF/US/QPFF +ETF/US/QPT +ETF/US/QPUX ETF/US/QPX ETF/US/QQA +ETF/US/QQC +ETF/US/QQD +ETF/US/QQDN ETF/US/QQEW ETF/US/QQH +ETF/US/QQHG ETF/US/QQJG +ETF/US/QQJN ETF/US/QQLV ETF/US/QQMG +ETF/US/QQMY ETF/US/QQQ ETF/US/QQQA ETF/US/QQQD @@ -3343,20 +5265,29 @@ ETF/US/QQQH ETF/US/QQQI ETF/US/QQQJ ETF/US/QQQM +ETF/US/QQQN ETF/US/QQQP ETF/US/QQQS ETF/US/QQQT ETF/US/QQQU ETF/US/QQQW ETF/US/QQQY +ETF/US/QQUP +ETF/US/QQWZ +ETF/US/QQXL ETF/US/QQXT ETF/US/QRFT ETF/US/QRMI ETF/US/QSIG ETF/US/QSIX ETF/US/QSML +ETF/US/QSOL ETF/US/QSPT +ETF/US/QSU ETF/US/QSWN +ETF/US/QSX +ETF/US/QSY +ETF/US/QTAC ETF/US/QTAP ETF/US/QTEC ETF/US/QTJA @@ -3367,59 +5298,102 @@ ETF/US/QTPI ETF/US/QTR ETF/US/QTUM ETF/US/QUAL +ETF/US/QUBX +ETF/US/QUIZ ETF/US/QULL ETF/US/QUP ETF/US/QUS +ETF/US/QUSA ETF/US/QUVU ETF/US/QVAL +ETF/US/QVM ETF/US/QVML ETF/US/QVMM ETF/US/QVMS +ETF/US/QVMT +ETF/US/QVOL ETF/US/QVOY ETF/US/QWLD +ETF/US/QWST +ETF/US/QXAS ETF/US/QXQ ETF/US/QYLD ETF/US/QYLE ETF/US/QYLG ETF/US/RA ETF/US/RAA +ETF/US/RAAA +ETF/US/RAAR ETF/US/RAAX +ETF/US/RAAY +ETF/US/RACK ETF/US/RAFE +ETF/US/RALS ETF/US/RATE +ETF/US/RAUS ETF/US/RAVI ETF/US/RAYC ETF/US/RAYD ETF/US/RAYE ETF/US/RAYJ ETF/US/RAYS +ETF/US/RB ETF/US/RBIL +ETF/US/RBIN ETF/US/RBLD ETF/US/RBLU +ETF/US/RBLY +ETF/US/RBND ETF/US/RBUF +ETF/US/RBUS +ETF/US/RCAX ETF/US/RCG ETF/US/RCGE +ETF/US/RCLO +ETF/US/RCLR +ETF/US/RCLY ETF/US/RCS +ETF/US/RCTR ETF/US/RDFI ETF/US/RDIV +ETF/US/RDMX ETF/US/RDOG ETF/US/RDTE ETF/US/RDTL ETF/US/RDTY ETF/US/RDVI ETF/US/RDVY +ETF/US/RDWU +ETF/US/RDYY ETF/US/REAI +ETF/US/REC ETF/US/RECS +ETF/US/REDV +ETF/US/REEM ETF/US/REET +ETF/US/REFA ETF/US/REGL +ETF/US/REGS ETF/US/REIT ETF/US/REK ETF/US/REKT ETF/US/REM +ETF/US/REMC +ETF/US/REMG +ETF/US/REML ETF/US/REMX +ETF/US/RENW +ETF/US/RESD +ETF/US/RESE +ETF/US/RESI +ETF/US/RESM +ETF/US/RESP ETF/US/RETL ETF/US/REVS ETF/US/REW +ETF/US/REXC ETF/US/REZ +ETF/US/RFAP ETF/US/RFCI ETF/US/RFDA ETF/US/RFDI @@ -3431,66 +5405,111 @@ ETF/US/RFI ETF/US/RFIX ETF/US/RFLR ETF/US/RFMZ +ETF/US/RFU +ETF/US/RFUN ETF/US/RFV ETF/US/RGEF +ETF/US/RGLB +ETF/US/RGLO ETF/US/RGT +ETF/US/RGTU ETF/US/RGTX +ETF/US/RGTZ +ETF/US/RGYY +ETF/US/RHCB ETF/US/RHRX ETF/US/RHTX +ETF/US/RIDV ETF/US/RIET +ETF/US/RIFR ETF/US/RIGS +ETF/US/RIGZ ETF/US/RILA ETF/US/RINC ETF/US/RINF ETF/US/RING +ETF/US/RINT ETF/US/RIOX +ETF/US/RISE ETF/US/RISN ETF/US/RISR ETF/US/RIV +ETF/US/RIZE +ETF/US/RJA +ETF/US/RJDI +ETF/US/RJI ETF/US/RJMG +ETF/US/RJMI +ETF/US/RJN +ETF/US/RJVI +ETF/US/RJZ ETF/US/RKLX +ETF/US/RKLZ +ETF/US/RKNG +ETF/US/RKSG +ETF/US/RKTL ETF/US/RLTY ETF/US/RLY ETF/US/RMCA ETF/US/RMI ETF/US/RMIF ETF/US/RMM +ETF/US/RMME ETF/US/RMMZ ETF/US/RMNY ETF/US/RMOP +ETF/US/RMRC +ETF/US/RMRM ETF/US/RMT ETF/US/RND +ETF/US/RNDM ETF/US/RNEM ETF/US/RNEW +ETF/US/RNIN +ETF/US/RNMC ETF/US/RNP ETF/US/RNRG +ETF/US/RNSC +ETF/US/RNTY ETF/US/RNWZ ETF/US/ROAM ETF/US/ROBN ETF/US/ROBO ETF/US/ROBT +ETF/US/ROCI +ETF/US/ROCQ +ETF/US/ROCY ETF/US/RODE +ETF/US/RODI ETF/US/RODM ETF/US/ROE +ETF/US/ROGS ETF/US/ROIS ETF/US/ROKT ETF/US/ROM ETF/US/ROMO +ETF/US/RONB +ETF/US/ROOF ETF/US/ROPE +ETF/US/RORE ETF/US/RORO ETF/US/ROSC ETF/US/ROUS +ETF/US/ROYA ETF/US/RPAR ETF/US/RPG ETF/US/RPHS +ETF/US/RPUT ETF/US/RPV ETF/US/RQI +ETF/US/RRH ETF/US/RSBA ETF/US/RSBT ETF/US/RSBY ETF/US/RSDE ETF/US/RSEE ETF/US/RSHO +ETF/US/RSIT ETF/US/RSJN ETF/US/RSMC ETF/US/RSMR @@ -3509,54 +5528,95 @@ ETF/US/RSPR ETF/US/RSPS ETF/US/RSPT ETF/US/RSPU +ETF/US/RSPY ETF/US/RSSB ETF/US/RSSE ETF/US/RSSL ETF/US/RSST +ETF/US/RSSX ETF/US/RSSY ETF/US/RSX ETF/US/RSXJ ETF/US/RTAI ETF/US/RTH +ETF/US/RTL ETF/US/RTRE +ETF/US/RTXG +ETF/US/RTYD +ETF/US/RTYY +ETF/US/RUFF ETF/US/RULE ETF/US/RUNN +ETF/US/RUSC +ETF/US/RUSL +ETF/US/RUSS ETF/US/RVER +ETF/US/RVNL ETF/US/RVNU ETF/US/RVRB +ETF/US/RVRS ETF/US/RVT +ETF/US/RW +ETF/US/RWCD +ETF/US/RWDC +ETF/US/RWDE +ETF/US/RWED +ETF/US/RWEM +ETF/US/RWGV +ETF/US/RWIN +ETF/US/RWIU ETF/US/RWJ ETF/US/RWK ETF/US/RWL +ETF/US/RWLC +ETF/US/RWLS ETF/US/RWM ETF/US/RWO ETF/US/RWR +ETF/US/RWSL +ETF/US/RWUI +ETF/US/RWVG +ETF/US/RWW ETF/US/RWX ETF/US/RXD ETF/US/RXI ETF/US/RXL +ETF/US/RYJ ETF/US/RYLD ETF/US/RYLG ETF/US/RYSE +ETF/US/RYZZ ETF/US/RZG ETF/US/RZV ETF/US/SAA ETF/US/SABA ETF/US/SAEF +ETF/US/SAGG ETF/US/SAGP ETF/US/SAMM ETF/US/SAMT +ETF/US/SANE ETF/US/SAPH ETF/US/SARK +ETF/US/SASS +ETF/US/SATG ETF/US/SATO ETF/US/SAUG +ETF/US/SAVN ETF/US/SAWG ETF/US/SAWS +ETF/US/SBAR ETF/US/SBB ETF/US/SBI +ETF/US/SBIL ETF/US/SBIO ETF/US/SBIT +ETF/US/SBM ETF/US/SBND +ETF/US/SBTU +ETF/US/SBU +ETF/US/SBUG +ETF/US/SCA ETF/US/SCAP ETF/US/SCC ETF/US/SCCR @@ -3565,6 +5625,7 @@ ETF/US/SCDL ETF/US/SCDS ETF/US/SCDV ETF/US/SCEC +ETF/US/SCEP ETF/US/SCHA ETF/US/SCHB ETF/US/SCHC @@ -3585,23 +5646,42 @@ ETF/US/SCHV ETF/US/SCHX ETF/US/SCHY ETF/US/SCHZ +ETF/US/SCID +ETF/US/SCIF +ETF/US/SCIJ ETF/US/SCIO +ETF/US/SCIU +ETF/US/SCIX ETF/US/SCJ +ETF/US/SCJN +ETF/US/SCLS ETF/US/SCLZ ETF/US/SCMB +ETF/US/SCMC +ETF/US/SCMY +ETF/US/SCNM ETF/US/SCO +ETF/US/SCOM +ETF/US/SCOW +ETF/US/SCRD +ETF/US/SCSB +ETF/US/SCUB ETF/US/SCUS ETF/US/SCY ETF/US/SCYB ETF/US/SCZ +ETF/US/SDAG ETF/US/SDCI ETF/US/SDCP ETF/US/SDD ETF/US/SDEM ETF/US/SDFI ETF/US/SDG +ETF/US/SDGA +ETF/US/SDGS ETF/US/SDHY ETF/US/SDIV +ETF/US/SDMF ETF/US/SDOG ETF/US/SDOW ETF/US/SDP @@ -3611,9 +5691,12 @@ ETF/US/SDTY ETF/US/SDVD ETF/US/SDVY ETF/US/SDY +ETF/US/SDYL ETF/US/SEA +ETF/US/SECD ETF/US/SECR ETF/US/SECT +ETF/US/SECU ETF/US/SEEM ETF/US/SEF ETF/US/SEIE @@ -3623,6 +5706,10 @@ ETF/US/SEIS ETF/US/SEIV ETF/US/SEIX ETF/US/SELV +ETF/US/SEMG +ETF/US/SEMY +ETF/US/SENT +ETF/US/SEPI ETF/US/SEPM ETF/US/SEPP ETF/US/SEPT @@ -3632,26 +5719,38 @@ ETF/US/SEPZ ETF/US/SETH ETF/US/SETM ETF/US/SFEB +ETF/US/SFGV +ETF/US/SFHY +ETF/US/SFIG ETF/US/SFLO ETF/US/SFLR +ETF/US/SFTX +ETF/US/SFTY ETF/US/SFY ETF/US/SFYF ETF/US/SFYX ETF/US/SGDJ ETF/US/SGDM +ETF/US/SGG ETF/US/SGLC ETF/US/SGOL ETF/US/SGOV +ETF/US/SGRT +ETF/US/SGRW +ETF/US/SGVT ETF/US/SH ETF/US/SHAG ETF/US/SHDG ETF/US/SHE ETF/US/SHEH +ETF/US/SHFT ETF/US/SHLD ETF/US/SHM ETF/US/SHNY ETF/US/SHOC +ETF/US/SHPD ETF/US/SHPP +ETF/US/SHPU ETF/US/SHRT ETF/US/SHRY ETF/US/SHUS @@ -3666,8 +5765,11 @@ ETF/US/SIHY ETF/US/SIJ ETF/US/SIL ETF/US/SILJ +ETF/US/SILX ETF/US/SIMS +ETF/US/SINV ETF/US/SIO +ETF/US/SIOO ETF/US/SIVR ETF/US/SIXA ETF/US/SIXD @@ -3680,9 +5782,11 @@ ETF/US/SIXO ETF/US/SIXP ETF/US/SIXS ETF/US/SIXZ +ETF/US/SIZ ETF/US/SIZE ETF/US/SJB ETF/US/SJCP +ETF/US/SJIM ETF/US/SJLD ETF/US/SJNK ETF/US/SKF @@ -3691,13 +5795,21 @@ ETF/US/SKRE ETF/US/SKYU ETF/US/SKYY ETF/US/SLDR +ETF/US/SLIM +ETF/US/SLJY ETF/US/SLNZ +ETF/US/SLON ETF/US/SLQD +ETF/US/SLT +ETF/US/SLTY ETF/US/SLV ETF/US/SLVO ETF/US/SLVP ETF/US/SLVR +ETF/US/SLVX +ETF/US/SLWS ETF/US/SLX +ETF/US/SLY ETF/US/SLYG ETF/US/SLYV ETF/US/SMAP @@ -3705,34 +5817,54 @@ ETF/US/SMAX ETF/US/SMAY ETF/US/SMB ETF/US/SMBS +ETF/US/SMCC ETF/US/SMCF ETF/US/SMCL ETF/US/SMCO +ETF/US/SMCP ETF/US/SMCX ETF/US/SMCY ETF/US/SMCZ ETF/US/SMDD ETF/US/SMDV ETF/US/SMDX +ETF/US/SMDY +ETF/US/SMEZ ETF/US/SMH ETF/US/SMHB +ETF/US/SMHD ETF/US/SMHX ETF/US/SMI ETF/US/SMIG ETF/US/SMIN ETF/US/SMIZ +ETF/US/SMLE ETF/US/SMLF ETF/US/SMLL ETF/US/SMLV +ETF/US/SMM ETF/US/SMMD ETF/US/SMMU ETF/US/SMMV ETF/US/SMN ETF/US/SMOG +ETF/US/SMOM ETF/US/SMOT +ETF/US/SMOX +ETF/US/SMQ +ETF/US/SMRF ETF/US/SMRI ETF/US/SMST +ETF/US/SMU +ETF/US/SMUP +ETF/US/SMYY +ETF/US/SMZ +ETF/US/SNAG ETF/US/SNAV +ETF/US/SNDG +ETF/US/SNDQ +ETF/US/SNDU +ETF/US/SNOU ETF/US/SNOV ETF/US/SNOY ETF/US/SNPD @@ -3741,13 +5873,25 @@ ETF/US/SNPG ETF/US/SNPV ETF/US/SNSR ETF/US/SNTH +ETF/US/SNUG +ETF/US/SNXX ETF/US/SOCL +ETF/US/SOEZ +ETF/US/SOF +ETF/US/SOFA +ETF/US/SOFL ETF/US/SOFR ETF/US/SOFX +ETF/US/SOGU +ETF/US/SOIL +ETF/US/SOLC +ETF/US/SOLM ETF/US/SOLR ETF/US/SOLT +ETF/US/SOLX ETF/US/SOLZ -ETF/US/SOR +ETF/US/SOUX +ETF/US/SOVB ETF/US/SOVF ETF/US/SOXL ETF/US/SOXM @@ -3758,6 +5902,7 @@ ETF/US/SOXX ETF/US/SOXY ETF/US/SOYB ETF/US/SPAB +ETF/US/SPAK ETF/US/SPAM ETF/US/SPAQ ETF/US/SPAX @@ -3767,10 +5912,15 @@ ETF/US/SPBU ETF/US/SPBW ETF/US/SPBX ETF/US/SPC +ETF/US/SPCI +ETF/US/SPCK +ETF/US/SPCL +ETF/US/SPCT ETF/US/SPCX ETF/US/SPCY ETF/US/SPCZ ETF/US/SPD +ETF/US/SPDF ETF/US/SPDG ETF/US/SPDN ETF/US/SPDV @@ -3787,15 +5937,21 @@ ETF/US/SPHQ ETF/US/SPHY ETF/US/SPIB ETF/US/SPIP +ETF/US/SPIT +ETF/US/SPKX +ETF/US/SPKY ETF/US/SPLB ETF/US/SPLG +ETF/US/SPLS ETF/US/SPLV ETF/US/SPMB ETF/US/SPMD ETF/US/SPMO ETF/US/SPMV +ETF/US/SPOG ETF/US/SPPP ETF/US/SPQ +ETF/US/SPQQ ETF/US/SPRE ETF/US/SPRX ETF/US/SPSB @@ -3807,6 +5963,7 @@ ETF/US/SPTI ETF/US/SPTL ETF/US/SPTM ETF/US/SPTS +ETF/US/SPTU ETF/US/SPUC ETF/US/SPUS ETF/US/SPUT @@ -3814,19 +5971,25 @@ ETF/US/SPUU ETF/US/SPVM ETF/US/SPVU ETF/US/SPWO +ETF/US/SPXB +ETF/US/SPXD ETF/US/SPXE ETF/US/SPXL +ETF/US/SPXM ETF/US/SPXN ETF/US/SPXS ETF/US/SPXT ETF/US/SPXU ETF/US/SPXV ETF/US/SPXX +ETF/US/SPXZ ETF/US/SPY +ETF/US/SPYA ETF/US/SPYB ETF/US/SPYC ETF/US/SPYD ETF/US/SPYG +ETF/US/SPYH ETF/US/SPYI ETF/US/SPYM ETF/US/SPYQ @@ -3835,48 +5998,82 @@ ETF/US/SPYU ETF/US/SPYV ETF/US/SPYX ETF/US/SQEW +ETF/US/SQLT ETF/US/SQLV ETF/US/SQMX ETF/US/SQQQ +ETF/US/SQS ETF/US/SQY +ETF/US/SQZZ ETF/US/SRET ETF/US/SRHQ ETF/US/SRHR ETF/US/SRLN ETF/US/SROI +ETF/US/SRPU ETF/US/SRS ETF/US/SRTY ETF/US/SRV ETF/US/SRVR +ETF/US/SSCP ETF/US/SSEHF ETF/US/SSFI ETF/US/SSG +ETF/US/SSK +ETF/US/SSLY +ETF/US/SSMG ETF/US/SSO ETF/US/SSPX ETF/US/SSPY +ETF/US/SSS ETF/US/SSUS ETF/US/SSXU ETF/US/STAX ETF/US/STBF +ETF/US/STBL +ETF/US/STBQ ETF/US/STCE +ETF/US/STEN ETF/US/STEW +ETF/US/STGF ETF/US/STHH ETF/US/STIP ETF/US/STK +ETF/US/STLC +ETF/US/STLG +ETF/US/STLR +ETF/US/STLU +ETF/US/STLV +ETF/US/STMB ETF/US/STNC ETF/US/STOT +ETF/US/STOX +ETF/US/STPP ETF/US/STPZ +ETF/US/STRN ETF/US/STRV ETF/US/STSB +ETF/US/STSM ETF/US/STXD ETF/US/STXE +ETF/US/STXF ETF/US/STXG ETF/US/STXI ETF/US/STXK +ETF/US/STXL ETF/US/STXM ETF/US/STXT +ETF/US/STXU ETF/US/STXV +ETF/US/STXX +ETF/US/STYL ETF/US/SUB +ETF/US/SUBS +ETF/US/SUBZ +ETF/US/SUIL +ETF/US/SUIS +ETF/US/SULR +ETF/US/SUNY ETF/US/SUPL ETF/US/SUPP ETF/US/SURE @@ -3890,28 +6087,54 @@ ETF/US/SVIX ETF/US/SVOL ETF/US/SVXY ETF/US/SWAN +ETF/US/SWAR +ETF/US/SWEB ETF/US/SWP ETF/US/SWZ ETF/US/SXQG +ETF/US/SXUS +ETF/US/SYE ETF/US/SYFI +ETF/US/SYG +ETF/US/SYII ETF/US/SYLD ETF/US/SYNB +ETF/US/SYSB +ETF/US/SYUS +ETF/US/SYV +ETF/US/SYZ +ETF/US/SZC ETF/US/SZK ETF/US/SZNE +ETF/US/TAAG +ETF/US/TABD +ETF/US/TACE ETF/US/TACK +ETF/US/TACN +ETF/US/TACU +ETF/US/TADS +ETF/US/TAEQ ETF/US/TAFI ETF/US/TAFL ETF/US/TAFM ETF/US/TAGG ETF/US/TAGS ETF/US/TAIL +ETF/US/TAJX +ETF/US/TALV ETF/US/TAN +ETF/US/TAO +ETF/US/TAOZ ETF/US/TAPR ETF/US/TARK +ETF/US/TAWK ETF/US/TAX ETF/US/TAXE ETF/US/TAXF +ETF/US/TAXI ETF/US/TAXM +ETF/US/TAXS +ETF/US/TAXT ETF/US/TAXX ETF/US/TBF ETF/US/TBFG @@ -3920,66 +6143,132 @@ ETF/US/TBIL ETF/US/TBJL ETF/US/TBLL ETF/US/TBLU +ETF/US/TBND ETF/US/TBT ETF/US/TBUX ETF/US/TBX +ETF/US/TBXU ETF/US/TCAF +ETF/US/TCAI ETF/US/TCAL +ETF/US/TCAN ETF/US/TCHI ETF/US/TCHP +ETF/US/TCLD ETF/US/TCPB +ETF/US/TCTL +ETF/US/TCV +ETF/US/TDAQ +ETF/US/TDAX +ETF/US/TDD ETF/US/TDEC ETF/US/TDF +ETF/US/TDH ETF/US/TDIV +ETF/US/TDN +ETF/US/TDOG +ETF/US/TDOT +ETF/US/TDSA ETF/US/TDSB ETF/US/TDSC +ETF/US/TDSD +ETF/US/TDSE ETF/US/TDTF ETF/US/TDTT ETF/US/TDV ETF/US/TDVG ETF/US/TDVI +ETF/US/TDX ETF/US/TEAF +ETF/US/TEC ETF/US/TECB ETF/US/TECL ETF/US/TECS +ETF/US/TECY +ETF/US/TEGS ETF/US/TEI ETF/US/TEK ETF/US/TEKX +ETF/US/TEKY +ETF/US/TEMD ETF/US/TEMP +ETF/US/TEMR +ETF/US/TEMT ETF/US/TEMX +ETF/US/TEND +ETF/US/TENG +ETF/US/TENJ +ETF/US/TENM ETF/US/TEQI +ETF/US/TERG +ETF/US/TERM ETF/US/TESL +ETF/US/TEST +ETF/US/TETH +ETF/US/TEUP +ETF/US/TEXN +ETF/US/TEXU +ETF/US/TEXX +ETF/US/TFFI +ETF/US/TFGZ ETF/US/TFI +ETF/US/TFIV ETF/US/TFJL ETF/US/TFLO ETF/US/TFLR +ETF/US/TFLT +ETF/US/TFNS ETF/US/TFPN +ETF/US/TGIF +ETF/US/TGLB ETF/US/TGLR ETF/US/TGRT ETF/US/TGRW +ETF/US/THCX ETF/US/THD ETF/US/THEQ ETF/US/THIR ETF/US/THLV +ETF/US/THMR +ETF/US/THMZ ETF/US/THNQ ETF/US/THNR ETF/US/THQ ETF/US/THRO +ETF/US/THRV ETF/US/THTA ETF/US/THW ETF/US/THY ETF/US/THYF +ETF/US/THYM +ETF/US/THYP +ETF/US/TIER +ETF/US/TIIV ETF/US/TILL ETF/US/TILT ETF/US/TIME +ETF/US/TINS ETF/US/TINT ETF/US/TINY ETF/US/TIP +ETF/US/TIPA +ETF/US/TIPB +ETF/US/TIPC +ETF/US/TIPD +ETF/US/TIPL ETF/US/TIPX ETF/US/TIPZ ETF/US/TJAN ETF/US/TJUL +ETF/US/TJUN +ETF/US/TKNQ +ETF/US/TKNS +ETF/US/TLA ETF/US/TLCI +ETF/US/TLDH +ETF/US/TLDR +ETF/US/TLEH +ETF/US/TLG ETF/US/TLH ETF/US/TLT ETF/US/TLTD @@ -3989,10 +6278,12 @@ ETF/US/TLTM ETF/US/TLTP ETF/US/TLTQ ETF/US/TLTW +ETF/US/TLTX ETF/US/TMAR ETF/US/TMAT ETF/US/TMB ETF/US/TMDV +ETF/US/TMED ETF/US/TMET ETF/US/TMF ETF/US/TMFC @@ -4002,20 +6293,39 @@ ETF/US/TMFM ETF/US/TMFS ETF/US/TMFX ETF/US/TMH +ETF/US/TMLP +ETF/US/TMNL +ETF/US/TMNS +ETF/US/TMSF ETF/US/TMSL ETF/US/TMV +ETF/US/TMVE +ETF/US/TMYY ETF/US/TNA +ETF/US/TNGY +ETF/US/TNUK +ETF/US/TNXT ETF/US/TOAK +ETF/US/TOAO +ETF/US/TOCT ETF/US/TOGA ETF/US/TOK ETF/US/TOKE ETF/US/TOLL ETF/US/TOLZ +ETF/US/TOPC ETF/US/TOPT +ETF/US/TOS +ETF/US/TOT ETF/US/TOTL ETF/US/TOTR ETF/US/TOUS ETF/US/TOV +ETF/US/TOXR +ETF/US/TPAY +ETF/US/TPFC +ETF/US/TPFG +ETF/US/TPFI ETF/US/TPHD ETF/US/TPHE ETF/US/TPIF @@ -4024,30 +6334,55 @@ ETF/US/TPLE ETF/US/TPLS ETF/US/TPMN ETF/US/TPOR +ETF/US/TPRY ETF/US/TPSC ETF/US/TPYP ETF/US/TPZ ETF/US/TQQQ ETF/US/TQQY +ETF/US/TRBF +ETF/US/TRDF +ETF/US/TRES ETF/US/TRFK ETF/US/TRFM +ETF/US/TRIL ETF/US/TRIO ETF/US/TRND +ETF/US/TROT ETF/US/TRPA ETF/US/TRSY ETF/US/TRTY +ETF/US/TRUC +ETF/US/TRUD +ETF/US/TRUF +ETF/US/TRUH +ETF/US/TRUI +ETF/US/TRUO +ETF/US/TRUT +ETF/US/TRYP +ETF/US/TSCM +ETF/US/TSCV ETF/US/TSDD ETF/US/TSEC ETF/US/TSEL ETF/US/TSEP +ETF/US/TSES ETF/US/TSI +ETF/US/TSIC +ETF/US/TSII +ETF/US/TSJA +ETF/US/TSLF ETF/US/TSLG +ETF/US/TSLH +ETF/US/TSLI ETF/US/TSLL +ETF/US/TSLO ETF/US/TSLP ETF/US/TSLQ ETF/US/TSLR ETF/US/TSLS ETF/US/TSLT +ETF/US/TSLV ETF/US/TSLW ETF/US/TSLY ETF/US/TSLZ @@ -4057,71 +6392,128 @@ ETF/US/TSMU ETF/US/TSMX ETF/US/TSMY ETF/US/TSMZ +ETF/US/TSNF +ETF/US/TSOC +ETF/US/TSOL ETF/US/TSPA ETF/US/TSPX ETF/US/TSPY +ETF/US/TSRS +ETF/US/TSSD +ETF/US/TSUI ETF/US/TSW +ETF/US/TSXD +ETF/US/TSXU +ETF/US/TSYW +ETF/US/TSYX ETF/US/TSYY +ETF/US/TTAC +ETF/US/TTAI +ETF/US/TTDU ETF/US/TTEQ +ETF/US/TTOP ETF/US/TTP ETF/US/TTT +ETF/US/TTTN +ETF/US/TTXD +ETF/US/TTXU ETF/US/TUA ETF/US/TUG ETF/US/TUGN +ETF/US/TUNE ETF/US/TUR +ETF/US/TURF +ETF/US/TUSA ETF/US/TUSB ETF/US/TUSI +ETF/US/TUZ ETF/US/TVAL +ETF/US/TVIX +ETF/US/TWAR +ETF/US/TWEB ETF/US/TWIO ETF/US/TWM ETF/US/TWN ETF/US/TWOX +ETF/US/TXBC +ETF/US/TXNU ETF/US/TXS ETF/US/TXSS ETF/US/TXUE ETF/US/TXUG +ETF/US/TXXD +ETF/US/TXXH ETF/US/TXXI +ETF/US/TXXS ETF/US/TY ETF/US/TYA +ETF/US/TYBS ETF/US/TYD ETF/US/TYG ETF/US/TYLD ETF/US/TYLG +ETF/US/TYNE +ETF/US/TYNS ETF/US/TYO +ETF/US/TYYY ETF/US/TZA ETF/US/UAE +ETF/US/UAG ETF/US/UAPR +ETF/US/UAUD ETF/US/UAUG +ETF/US/UAV +ETF/US/UBCB +ETF/US/UBEW +ETF/US/UBG +ETF/US/UBIO ETF/US/UBND ETF/US/UBOT ETF/US/UBR ETF/US/UBRL ETF/US/UBT ETF/US/UCC +ETF/US/UCHF +ETF/US/UCI ETF/US/UCIB ETF/US/UCO +ETF/US/UCOM ETF/US/UCON +ETF/US/UCOP ETF/US/UCRD ETF/US/UCYB ETF/US/UDEC ETF/US/UDIV ETF/US/UDN ETF/US/UDOW +ETF/US/UECG +ETF/US/UEUR ETF/US/UEVM ETF/US/UFEB ETF/US/UFIV ETF/US/UFO +ETF/US/UFOD +ETF/US/UFOX ETF/US/UGA +ETF/US/UGBP +ETF/US/UGCE ETF/US/UGE ETF/US/UGL +ETF/US/UGLD ETF/US/UITB ETF/US/UIVM ETF/US/UJAN ETF/US/UJB +ETF/US/UJPY +ETF/US/UJU ETF/US/UJUL ETF/US/UJUN +ETF/US/UKW +ETF/US/ULBR ETF/US/ULE ETF/US/ULST +ETF/US/ULTI +ETF/US/ULTR ETF/US/ULTY ETF/US/ULVM ETF/US/UMAR @@ -4130,17 +6522,26 @@ ETF/US/UMDD ETF/US/UMI ETF/US/UMMA ETF/US/UNG +ETF/US/UNHG +ETF/US/UNHU +ETF/US/UNHW ETF/US/UNIY ETF/US/UNL ETF/US/UNOV +ETF/US/UNX ETF/US/UOCT +ETF/US/UPAL ETF/US/UPAR ETF/US/UPGD ETF/US/UPGR +ETF/US/UPLT ETF/US/UPRO ETF/US/UPSD +ETF/US/UPSG +ETF/US/UPSX ETF/US/UPV ETF/US/UPW +ETF/US/UPWD ETF/US/URA ETF/US/URAA ETF/US/URAN @@ -4148,11 +6549,15 @@ ETF/US/URAX ETF/US/URE ETF/US/URNJ ETF/US/URNM +ETF/US/URR +ETF/US/URSP ETF/US/URTH ETF/US/URTY ETF/US/USA ETF/US/USAF ETF/US/USAI +ETF/US/USAX +ETF/US/USBF ETF/US/USCA ETF/US/USCF ETF/US/USCI @@ -4160,22 +6565,36 @@ ETF/US/USCL ETF/US/USD ETF/US/USDU ETF/US/USDX +ETF/US/USDY ETF/US/USE ETF/US/USEP +ETF/US/USEQ +ETF/US/USEW +ETF/US/USFE ETF/US/USFI ETF/US/USFR ETF/US/USG +ETF/US/USGG +ETF/US/USHG ETF/US/USHY +ETF/US/USI ETF/US/USIG ETF/US/USIN ETF/US/USL +ETF/US/USLB +ETF/US/USLN +ETF/US/USLV ETF/US/USMC +ETF/US/USMD ETF/US/USMF ETF/US/USML ETF/US/USMV +ETF/US/USNG ETF/US/USNZ ETF/US/USO +ETF/US/USOD ETF/US/USOI +ETF/US/USOU ETF/US/USOY ETF/US/USPX ETF/US/USRD @@ -4185,8 +6604,11 @@ ETF/US/USSG ETF/US/USSH ETF/US/UST ETF/US/USTB +ETF/US/USV ETF/US/USVM ETF/US/USVN +ETF/US/USVT +ETF/US/USX ETF/US/USXF ETF/US/UTEN ETF/US/UTES @@ -4199,31 +6621,59 @@ ETF/US/UTSL ETF/US/UTWO ETF/US/UTWY ETF/US/UUP +ETF/US/UUPP +ETF/US/UUUG +ETF/US/UVDV ETF/US/UVIX ETF/US/UVXY ETF/US/UWM +ETF/US/UWT ETF/US/UX +ETF/US/UXAP ETF/US/UXI ETF/US/UXJA +ETF/US/UXJL ETF/US/UXOC +ETF/US/UXRP ETF/US/UYG ETF/US/UYLD ETF/US/UYM ETF/US/VABS +ETF/US/VAIE +ETF/US/VALG ETF/US/VALQ +ETF/US/VALT +ETF/US/VALX ETF/US/VAMO +ETF/US/VAVX ETF/US/VAW ETF/US/VB +ETF/US/VBB +ETF/US/VBCA +ETF/US/VBCB +ETF/US/VBCC +ETF/US/VBCD +ETF/US/VBCE +ETF/US/VBCF +ETF/US/VBCG +ETF/US/VBCH +ETF/US/VBCI +ETF/US/VBCJ ETF/US/VBF ETF/US/VBIL ETF/US/VBK +ETF/US/VBNB ETF/US/VBND ETF/US/VBR +ETF/US/VBX ETF/US/VCAR ETF/US/VCEB +ETF/US/VCF ETF/US/VCIT ETF/US/VCLN +ETF/US/VCLO ETF/US/VCLT +ETF/US/VCOB ETF/US/VCR ETF/US/VCRB ETF/US/VCRM @@ -4231,40 +6681,60 @@ ETF/US/VCSH ETF/US/VCV ETF/US/VDC ETF/US/VDE +ETF/US/VDG +ETF/US/VDI +ETF/US/VDIG +ETF/US/VDNI +ETF/US/VDV ETF/US/VEA +ETF/US/VEFA ETF/US/VEGA ETF/US/VEGI ETF/US/VEGN +ETF/US/VEM ETF/US/VEMY ETF/US/VERS +ETF/US/VETS ETF/US/VETZ ETF/US/VEU +ETF/US/VEXC ETF/US/VFH +ETF/US/VFIN ETF/US/VFL ETF/US/VFLO +ETF/US/VFLQ ETF/US/VFMF ETF/US/VFMO ETF/US/VFMV ETF/US/VFQY ETF/US/VFVA +ETF/US/VGFO +ETF/US/VGHY ETF/US/VGI ETF/US/VGIT ETF/US/VGK ETF/US/VGLT ETF/US/VGM +ETF/US/VGMS +ETF/US/VGRO ETF/US/VGSH ETF/US/VGSR ETF/US/VGT ETF/US/VGUS +ETF/US/VGVT ETF/US/VHT ETF/US/VICE +ETF/US/VIDG ETF/US/VIDI ETF/US/VIG ETF/US/VIGI +ETF/US/VIIX ETF/US/VIOG ETF/US/VIOO ETF/US/VIOV +ETF/US/VIRS ETF/US/VIS +ETF/US/VIXI ETF/US/VIXM ETF/US/VIXY ETF/US/VKI @@ -4273,13 +6743,18 @@ ETF/US/VLLU ETF/US/VLT ETF/US/VLU ETF/US/VLUE +ETF/US/VMAT ETF/US/VMAX ETF/US/VMBS +ETF/US/VMM ETF/US/VMO ETF/US/VMOT +ETF/US/VMSB ETF/US/VNAM +ETF/US/VNIE ETF/US/VNLA ETF/US/VNM +ETF/US/VNMC ETF/US/VNQ ETF/US/VNQI ETF/US/VNSE @@ -4292,44 +6767,66 @@ ETF/US/VONV ETF/US/VOO ETF/US/VOOG ETF/US/VOOV +ETF/US/VOOX ETF/US/VOT ETF/US/VOTE ETF/US/VOX +ETF/US/VOXP +ETF/US/VOYX ETF/US/VPC ETF/US/VPL ETF/US/VPLS +ETF/US/VPN +ETF/US/VPOP ETF/US/VPU ETF/US/VPV +ETF/US/VPX +ETF/US/VQT ETF/US/VRAI ETF/US/VRIG ETF/US/VRP ETF/US/VRTL ETF/US/VSDA +ETF/US/VSDB ETF/US/VSDM ETF/US/VSGX ETF/US/VSHY +ETF/US/VSL ETF/US/VSLU ETF/US/VSMV +ETF/US/VSOL +ETF/US/VSPY ETF/US/VSS +ETF/US/VSTL ETF/US/VT +ETF/US/VTA ETF/US/VTC ETF/US/VTEB ETF/US/VTEC ETF/US/VTEI +ETF/US/VTEL ETF/US/VTES +ETF/US/VTG ETF/US/VTHR ETF/US/VTI ETF/US/VTIP ETF/US/VTN +ETF/US/VTP +ETF/US/VTRN ETF/US/VTV ETF/US/VTWG ETF/US/VTWO ETF/US/VTWV ETF/US/VUG +ETF/US/VUS ETF/US/VUSB ETF/US/VUSE +ETF/US/VUSG +ETF/US/VUSI +ETF/US/VUSV ETF/US/VV ETF/US/VVR +ETF/US/VWI ETF/US/VWID ETF/US/VWO ETF/US/VWOB @@ -4341,59 +6838,125 @@ ETF/US/VYLD ETF/US/VYM ETF/US/VYMI ETF/US/WABF +ETF/US/WAGN +ETF/US/WAMA ETF/US/WANT ETF/US/WAR +ETF/US/WARP +ETF/US/WATS +ETF/US/WBAL ETF/US/WBAT +ETF/US/WBIA +ETF/US/WBIB +ETF/US/WBIC +ETF/US/WBID +ETF/US/WBIE ETF/US/WBIF ETF/US/WBIG +ETF/US/WBII ETF/US/WBIL +ETF/US/WBIN +ETF/US/WBIT ETF/US/WBIY ETF/US/WBND +ETF/US/WCAP ETF/US/WCBR ETF/US/WCEO +ETF/US/WCHN ETF/US/WCLD ETF/US/WCME +ETF/US/WCMG ETF/US/WCMI +ETF/US/WCPB +ETF/US/WDAF +ETF/US/WDAI +ETF/US/WDCX +ETF/US/WDE +ETF/US/WDEF +ETF/US/WDGF ETF/US/WDI +ETF/US/WDIG ETF/US/WDIV ETF/US/WDNA +ETF/US/WDRN +ETF/US/WDRW ETF/US/WDTE ETF/US/WEA ETF/US/WEAT ETF/US/WEBL ETF/US/WEBS +ETF/US/WEBX ETF/US/WEED ETF/US/WEEI ETF/US/WEEK ETF/US/WEEL ETF/US/WEIX +ETF/US/WEPN ETF/US/WFH +ETF/US/WFHY +ETF/US/WFIG +ETF/US/WGLD ETF/US/WGMI +ETF/US/WGRO ETF/US/WHTX ETF/US/WIA +ETF/US/WIL +ETF/US/WILD +ETF/US/WIMA ETF/US/WINC ETF/US/WIP +ETF/US/WISD ETF/US/WISE ETF/US/WIW +ETF/US/WIZ +ETF/US/WKLY ETF/US/WLDR +ETF/US/WLDU ETF/US/WLTG +ETF/US/WLTH +ETF/US/WMH +ETF/US/WMSB +ETF/US/WMTI +ETF/US/WNDR ETF/US/WNDY ETF/US/WNTR ETF/US/WOMN ETF/US/WOOD +ETF/US/WPAY +ETF/US/WPS +ETF/US/WQTM +ETF/US/WR ETF/US/WRND +ETF/US/WRTH +ETF/US/WSDB +ETF/US/WSGE +ETF/US/WSML ETF/US/WTAI ETF/US/WTBN +ETF/US/WTIB ETF/US/WTID +ETF/US/WTIP ETF/US/WTIU +ETF/US/WTLS ETF/US/WTMF +ETF/US/WTMU +ETF/US/WTMY ETF/US/WTPI ETF/US/WTRE ETF/US/WTV +ETF/US/WUCT ETF/US/WUGI +ETF/US/WULX ETF/US/WUSA ETF/US/WWJD +ETF/US/WWOW +ETF/US/WX ETF/US/WXET +ETF/US/WZRD +ETF/US/XA +ETF/US/XAGG +ETF/US/XAGI +ETF/US/XAIL ETF/US/XAIX ETF/US/XAPR ETF/US/XAR @@ -4401,28 +6964,44 @@ ETF/US/XAUG ETF/US/XB ETF/US/XBAP ETF/US/XBB +ETF/US/XBCI +ETF/US/XBFR ETF/US/XBI ETF/US/XBIL +ETF/US/XBIX ETF/US/XBJA ETF/US/XBJL +ETF/US/XBNB ETF/US/XBOC +ETF/US/XBOX +ETF/US/XBTF +ETF/US/XBTY +ETF/US/XBUY ETF/US/XC ETF/US/XCCC ETF/US/XCEM +ETF/US/XCHG ETF/US/XCLR ETF/US/XCNY +ETF/US/XCOM ETF/US/XCOR ETF/US/XDAP ETF/US/XDAT ETF/US/XDEC +ETF/US/XDEF +ETF/US/XDIV ETF/US/XDJA ETF/US/XDJL +ETF/US/XDNA ETF/US/XDOC ETF/US/XDQQ ETF/US/XDSQ ETF/US/XDTE ETF/US/XEMD +ETF/US/XEML ETF/US/XES +ETF/US/XEUR +ETF/US/XEY ETF/US/XFEB ETF/US/XFIV ETF/US/XFIX @@ -4431,6 +7010,7 @@ ETF/US/XFLX ETF/US/XHB ETF/US/XHE ETF/US/XHLF +ETF/US/XHOA ETF/US/XHS ETF/US/XHYC ETF/US/XHYD @@ -4445,24 +7025,50 @@ ETF/US/XIJN ETF/US/XIMR ETF/US/XISE ETF/US/XITK +ETF/US/XIWC ETF/US/XJAN ETF/US/XJH ETF/US/XJR ETF/US/XJUL ETF/US/XJUN +ETF/US/XKRE ETF/US/XLB +ETF/US/XLBI +ETF/US/XLBX ETF/US/XLC +ETF/US/XLCI ETF/US/XLE +ETF/US/XLEI +ETF/US/XLEX +ETF/US/XLEY ETF/US/XLF +ETF/US/XLFI +ETF/US/XLFX ETF/US/XLG ETF/US/XLI +ETF/US/XLII +ETF/US/XLIX ETF/US/XLK +ETF/US/XLKI +ETF/US/XLKX ETF/US/XLP +ETF/US/XLPX ETF/US/XLRE +ETF/US/XLRI +ETF/US/XLSI ETF/US/XLSR +ETF/US/XLSY +ETF/US/XLTY ETF/US/XLU +ETF/US/XLUI +ETF/US/XLUX +ETF/US/XLUY ETF/US/XLV +ETF/US/XLVI +ETF/US/XLVX ETF/US/XLY +ETF/US/XLYI +ETF/US/XLYX ETF/US/XMAG ETF/US/XMAR ETF/US/XMAY @@ -4472,34 +7078,57 @@ ETF/US/XMLV ETF/US/XMMO ETF/US/XMPT ETF/US/XMVM +ETF/US/XMX ETF/US/XNAV +ETF/US/XNDX ETF/US/XNOV ETF/US/XNTK ETF/US/XOCT +ETF/US/XOEF +ETF/US/XOEX ETF/US/XOMO +ETF/US/XOMX +ETF/US/XOMZ ETF/US/XOP +ETF/US/XOVL ETF/US/XOVR +ETF/US/XPAV ETF/US/XPAY +ETF/US/XPEG ETF/US/XPH +ETF/US/XPM ETF/US/XPND ETF/US/XPP +ETF/US/XQQI ETF/US/XRLV ETF/US/XRLX ETF/US/XRMI +ETF/US/XRP +ETF/US/XRPC +ETF/US/XRPI +ETF/US/XRPK +ETF/US/XRPM +ETF/US/XRPR +ETF/US/XRPT +ETF/US/XRPZ ETF/US/XRT ETF/US/XSD +ETF/US/XSEM ETF/US/XSEP ETF/US/XSHD ETF/US/XSHQ ETF/US/XSLV ETF/US/XSMO ETF/US/XSOE +ETF/US/XSPI ETF/US/XSVM ETF/US/XSVN ETF/US/XSW ETF/US/XT +ETF/US/XTAI ETF/US/XTAP ETF/US/XTEN +ETF/US/XTH ETF/US/XTJA ETF/US/XTJL ETF/US/XTL @@ -4511,18 +7140,33 @@ ETF/US/XTWO ETF/US/XTWY ETF/US/XUDV ETF/US/XUSP +ETF/US/XV +ETF/US/XVO ETF/US/XVOL +ETF/US/XVUG ETF/US/XVV +ETF/US/XVZ +ETF/US/XW +ETF/US/XWEB ETF/US/XXCH +ETF/US/XXRP +ETF/US/XXV +ETF/US/XXX +ETF/US/XXXX ETF/US/XYLD ETF/US/XYLE ETF/US/XYLG +ETF/US/XYZG ETF/US/XYZY ETF/US/YALL ETF/US/YANG ETF/US/YBIT +ETF/US/YBMN +ETF/US/YBST ETF/US/YBTC +ETF/US/YBTY ETF/US/YCL +ETF/US/YCOM ETF/US/YCS ETF/US/YDEC ETF/US/YEAR @@ -4530,34 +7174,64 @@ ETF/US/YETH ETF/US/YFFI ETF/US/YFYA ETF/US/YGLD +ETF/US/YGRN ETF/US/YINN ETF/US/YJUN +ETF/US/YLCO ETF/US/YLD ETF/US/YLDE +ETF/US/YLDW ETF/US/YMAG ETF/US/YMAR ETF/US/YMAX +ETF/US/YMLI +ETF/US/YMLP +ETF/US/YNOT ETF/US/YOKE ETF/US/YOLO +ETF/US/YPS ETF/US/YQQQ ETF/US/YSEP ETF/US/YSPY +ETF/US/YUMY +ETF/US/YUNG ETF/US/YXI ETF/US/YYY +ETF/US/YYYM ETF/US/ZALT ETF/US/ZAP ETF/US/ZAPR ETF/US/ZAUG +ETF/US/ZBIO +ETF/US/ZCAN +ETF/US/ZCBA +ETF/US/ZCBB +ETF/US/ZCBC +ETF/US/ZCBE +ETF/US/ZCBF +ETF/US/ZCBG ETF/US/ZDEK +ETF/US/ZDEU ETF/US/ZECP +ETF/US/ZETX ETF/US/ZFEB +ETF/US/ZGBR ETF/US/ZHDG +ETF/US/ZHOG +ETF/US/ZHOK ETF/US/ZIG +ETF/US/ZINC ETF/US/ZIPP +ETF/US/ZIV ETF/US/ZIVB ETF/US/ZJAN +ETF/US/ZJPN ETF/US/ZJUL +ETF/US/ZJUN ETF/US/ZMAR +ETF/US/ZMAY +ETF/US/ZMLP +ETF/US/ZMUN ETF/US/ZNOV ETF/US/ZOCT ETF/US/ZROZ @@ -4565,10 +7239,12 @@ ETF/US/ZSB ETF/US/ZSC ETF/US/ZSEP ETF/US/ZSL +ETF/US/ZSPY ETF/US/ZTAX ETF/US/ZTEN ETF/US/ZTR ETF/US/ZTRE ETF/US/ZTWO ETF/US/ZVOL +ETF/US/ZYN ETF/US/ZZZ diff --git a/rust/src/utils/US-IX.csv b/rust/src/utils/US-IX.csv new file mode 100644 index 000000000..54e4cd985 --- /dev/null +++ b/rust/src/utils/US-IX.csv @@ -0,0 +1,648 @@ +IX/US/.VIX +IX/SZ/399267 +IX/SZ/399268 +IX/SH/000680 +IX/SH/000681 +IX/SH/000510 +IX/SH/000699 +IX/SH/000888 +IX/US/.NDXTMC +IX/US/.SPX +IX/SH/000691 +IX/SZ/399019 +IX/SZ/399020 +IX/SZ/399750 +IX/SZ/399850 +IX/SZ/399852 +IX/SZ/399260 +IX/SZ/399261 +IX/SZ/399258 +IX/SZ/399259 +IX/SH/000698 +IX/HK/HSLI +IX/SH/000841 +IX/SH/000948 +IX/SH/000824 +IX/SH/000944 +IX/SH/000925 +IX/SH/000805 +IX/SH/000828 +IX/SH/000904 +IX/SH/000821 +IX/SH/000911 +IX/SH/000811 +IX/SH/000919 +IX/SH/000942 +IX/SH/000994 +IX/SH/000832 +IX/SZ/399060 +IX/SH/000937 +IX/SH/000902 +IX/SH/000909 +IX/SH/000952 +IX/SZ/399030 +IX/SH/000922 +IX/SZ/399274 +IX/SH/000969 +IX/SH/000820 +IX/SH/000910 +IX/SH/000825 +IX/SH/000970 +IX/SH/000964 +IX/SH/000959 +IX/SH/000812 +IX/SZ/399266 +IX/SH/000977 +IX/SH/000936 +IX/SH/000815 +IX/SH/000988 +IX/SH/000912 +IX/SH/000985 +IX/SH/000927 +IX/SH/000917 +IX/SH/000980 +IX/SH/000806 +IX/SH/000961 +IX/SZ/399265 +IX/SH/000995 +IX/SH/000967 +IX/SZ/399262 +IX/SZ/399263 +IX/SH/000907 +IX/SH/000978 +IX/SH/000945 +IX/SH/000930 +IX/SH/000931 +IX/SH/000926 +IX/SH/000963 +IX/SH/000861 +IX/SH/000916 +IX/SH/000859 +IX/SH/000808 +IX/SH/000813 +IX/SH/000984 +IX/SZ/399289 +IX/SZ/399264 +IX/SH/000915 +IX/SH/000979 +IX/SH/000990 +IX/SH/000971 +IX/SH/000908 +IX/SH/000807 +IX/SH/000846 +IX/SH/000171 +IX/SH/000966 +IX/SH/000965 +IX/SH/000949 +IX/SH/000998 +IX/SH/000929 +IX/SH/000941 +IX/SH/000918 +IX/HK/HSCI +IX/SH/000693 +IX/SH/000692 +IX/SH/000695 +IX/SH/000697 +IX/US/.DJUS +IX/US/.DJT +IX/US/.NDX +IX/US/.HXC +IX/SH/000690 +IX/US/.DJU +IX/SH/000687 +IX/SH/000689 +IX/SH/000685 +IX/SH/000683 +IX/SH/000682 +IX/SG/FSTRE +IX/US/.DJI +IX/US/.IXIC +IX/SZ/399269 +IX/SZ/399974 +IX/SZ/399802 +IX/SZ/399695 +IX/SZ/399661 +IX/SZ/399383 +IX/SZ/399318 +IX/SZ/399008 +IX/SH/000076 +IX/SH/000010 +IX/SH/000032 +IX/SH/000012 +IX/SH/000059 +IX/SZ/399934 +IX/SZ/399809 +IX/SZ/399407 +IX/SZ/399804 +IX/SZ/399698 +IX/SZ/399637 +IX/SZ/399555 +IX/SZ/399554 +IX/SZ/399434 +IX/SZ/399374 +IX/SZ/399315 +IX/SZ/399241 +IX/SH/000122 +IX/SH/000138 +IX/SZ/399694 +IX/SZ/399691 +IX/SZ/399673 +IX/SZ/399441 +IX/SZ/399440 +IX/SZ/399387 +IX/SZ/399310 +IX/SZ/399276 +IX/SZ/399010 +IX/SH/000129 +IX/SH/000073 +IX/SH/000091 +IX/SZ/399959 +IX/SZ/399811 +IX/SZ/399810 +IX/SZ/399692 +IX/SZ/399675 +IX/SZ/399553 +IX/SZ/399418 +IX/SZ/399408 +IX/SZ/399367 +IX/SZ/399312 +IX/SZ/399994 +IX/SZ/399989 +IX/SZ/399933 +IX/SZ/399913 +IX/SZ/399668 +IX/SZ/399667 +IX/SZ/399635 +IX/SZ/399633 +IX/SZ/399556 +IX/SZ/399360 +IX/SZ/399333 +IX/SZ/399307 +IX/SZ/399300 +IX/SZ/399243 +IX/SH/000094 +IX/SH/000037 +IX/SH/000128 +IX/SH/000858 +IX/SH/000061 +IX/SH/000159 +IX/SH/000100 +IX/SZ/399640 +IX/SZ/399436 +IX/SZ/399403 +IX/SZ/399394 +IX/SZ/399390 +IX/SZ/399389 +IX/SZ/399382 +IX/SZ/399357 +IX/SZ/399313 +IX/SZ/399311 +IX/SZ/399291 +IX/SZ/399248 +IX/SZ/399102 +IX/SZ/399972 +IX/SZ/399998 +IX/SZ/399986 +IX/SZ/399697 +IX/SZ/399627 +IX/SZ/399625 +IX/SZ/399427 +IX/SZ/399324 +IX/SZ/399005 +IX/SH/000052 +IX/SH/000108 +IX/SH/000891 +IX/SH/000132 +IX/SH/000819 +IX/SZ/399683 +IX/SZ/399671 +IX/SZ/399655 +IX/SZ/399630 +IX/SZ/399316 +IX/SZ/399103 +IX/SH/000116 +IX/SH/000115 +IX/SH/000048 +IX/SZ/399970 +IX/SZ/399696 +IX/SZ/399651 +IX/SZ/399639 +IX/SZ/399339 +IX/SZ/399299 +IX/SZ/399280 +IX/SZ/399233 +IX/SH/000123 +IX/SH/000110 +IX/SH/000867 +IX/SZ/399812 +IX/SH/000120 +IX/SH/000090 +IX/SH/000160 +IX/SH/000148 +IX/SH/000033 +IX/SH/000118 +IX/SH/000112 +IX/SH/000170 +IX/SH/000067 +IX/SH/000047 +IX/SH/000008 +IX/SH/000136 +IX/SH/000827 +IX/SZ/399682 +IX/SZ/399647 +IX/SZ/399438 +IX/SZ/399384 +IX/SZ/399348 +IX/SZ/399319 +IX/SZ/399282 +IX/SZ/399244 +IX/SZ/399242 +IX/SZ/399050 +IX/SH/000130 +IX/SH/000119 +IX/SH/000005 +IX/SH/000860 +IX/SH/000991 +IX/SH/000038 +IX/SH/000162 +IX/SZ/399966 +IX/SZ/399905 +IX/SZ/399706 +IX/SZ/399664 +IX/SZ/399663 +IX/SZ/399616 +IX/SZ/399395 +IX/SZ/399377 +IX/SZ/399353 +IX/SZ/399001 +IX/SH/000042 +IX/SH/000155 +IX/SH/000055 +IX/SH/000025 +IX/SH/000852 +IX/SH/000121 +IX/SZ/399346 +IX/SZ/399341 +IX/SZ/399232 +IX/SZ/399017 +IX/SZ/399013 +IX/SH/000054 +IX/SH/000022 +IX/SH/000126 +IX/SH/000147 +IX/SH/000158 +IX/SH/000125 +IX/SH/000051 +IX/SH/000131 +IX/SZ/399928 +IX/SZ/399652 +IX/SZ/399645 +IX/SZ/399618 +IX/SZ/399975 +IX/SZ/399903 +IX/SZ/399674 +IX/SZ/399659 +IX/SZ/399481 +IX/SZ/399437 +IX/SZ/399428 +IX/SZ/399406 +IX/SZ/399405 +IX/SZ/399361 +IX/SZ/399344 +IX/SZ/399707 +IX/SZ/399704 +IX/SZ/399644 +IX/SZ/399624 +IX/SZ/399409 +IX/SZ/399358 +IX/SZ/399317 +IX/SZ/399321 +IX/SZ/399236 +IX/SH/000006 +IX/SH/000153 +IX/SH/000026 +IX/SH/000019 +IX/SH/000105 +IX/SZ/399007 +IX/SH/000071 +IX/SH/000934 +IX/SH/000107 +IX/SZ/399615 +IX/SZ/399420 +IX/SZ/399385 +IX/SZ/399378 +IX/SZ/399303 +IX/SH/000099 +IX/SH/000847 +IX/SH/000039 +IX/SH/000043 +IX/SH/000001 +IX/SH/000109 +IX/SH/000077 +IX/SH/000068 +IX/SH/000056 +IX/SZ/399814 +IX/SZ/399808 +IX/SZ/399642 +IX/SZ/399611 +IX/SZ/399435 +IX/SZ/399432 +IX/SZ/399935 +IX/SZ/399662 +IX/SZ/399400 +IX/SZ/399386 +IX/SZ/399370 +IX/SZ/399364 +IX/SZ/399231 +IX/SH/000905 +IX/SZ/399971 +IX/SZ/399701 +IX/SZ/399693 +IX/SZ/399681 +IX/SZ/399677 +IX/SZ/399684 +IX/SZ/399672 +IX/SZ/399653 +IX/SZ/399629 +IX/SZ/399628 +IX/SZ/399623 +IX/SZ/399417 +IX/SZ/399380 +IX/SZ/399290 +IX/SZ/399016 +IX/SH/000855 +IX/SH/000095 +IX/SH/000857 +IX/SZ/399658 +IX/SZ/399654 +IX/SH/000040 +IX/SH/000035 +IX/SH/000018 +IX/SH/000139 +IX/SH/000113 +IX/SH/000097 +IX/SH/000989 +IX/SH/000066 +IX/SZ/399371 +IX/SZ/399362 +IX/SZ/399914 +IX/SZ/399689 +IX/SZ/399612 +IX/SZ/399284 +IX/SZ/399277 +IX/SH/000072 +IX/SH/000102 +IX/SH/000865 +IX/SH/000986 +IX/SH/000932 +IX/SZ/399997 +IX/SZ/399996 +IX/SZ/399803 +IX/SZ/399703 +IX/SZ/399636 +IX/SZ/399634 +IX/SZ/399604 +IX/SZ/399412 +IX/SZ/399373 +IX/SZ/399314 +IX/SZ/399306 +IX/SZ/399237 +IX/SZ/399011 +IX/SH/000029 +IX/SH/000869 +IX/SH/000823 +IX/SH/000935 +IX/SH/000117 +IX/SH/000161 +IX/SH/000046 +IX/SH/000152 +IX/SH/000079 +IX/SH/000009 +IX/SZ/399813 +IX/SZ/399429 +IX/SZ/399413 +IX/SZ/399411 +IX/SZ/399365 +IX/SZ/399286 +IX/SZ/399275 +IX/SH/000060 +IX/SH/000030 +IX/SH/000078 +IX/SH/000015 +IX/SH/000028 +IX/SH/000004 +IX/SH/000854 +IX/SZ/399626 +IX/SZ/399401 +IX/SZ/399302 +IX/SZ/399003 +IX/SH/000137 +IX/SH/000031 +IX/SH/000101 +IX/SH/000114 +IX/SZ/399991 +IX/SZ/399976 +IX/SZ/399356 +IX/SZ/399107 +IX/SZ/399012 +IX/SH/000853 +IX/SH/000688 +IX/SH/000856 +IX/SH/000906 +IX/SZ/399805 +IX/SZ/399676 +IX/SZ/399608 +IX/SZ/399423 +IX/SZ/399393 +IX/SZ/399391 +IX/SZ/399328 +IX/SZ/399326 +IX/SZ/399295 +IX/SZ/399240 +IX/SZ/399235 +IX/SH/000098 +IX/SH/000021 +IX/SH/000111 +IX/SH/000913 +IX/SH/000300 +IX/SH/000974 +IX/SZ/399987 +IX/SZ/399965 +IX/SZ/399702 +IX/SZ/399641 +IX/SZ/399638 +IX/SZ/399322 +IX/SZ/399009 +IX/SH/000851 +IX/SZ/399690 +IX/SZ/399687 +IX/SZ/399665 +IX/SZ/399620 +IX/SZ/399404 +IX/SZ/399381 +IX/SZ/399376 +IX/SZ/399355 +IX/SZ/399337 +IX/SZ/399335 +IX/SZ/399108 +IX/SZ/399015 +IX/SH/000062 +IX/SZ/399088 +IX/SZ/399004 +IX/SH/000933 +IX/SH/000145 +IX/SH/000092 +IX/SZ/399657 +IX/SZ/399557 +IX/SZ/399551 +IX/SZ/399431 +IX/SZ/399375 +IX/SZ/399298 +IX/SZ/399234 +IX/SH/000069 +IX/SH/000058 +IX/SH/000142 +IX/SH/000903 +IX/SH/000096 +IX/SZ/399990 +IX/SZ/399932 +IX/SZ/399666 +IX/SZ/399646 +IX/SZ/399369 +IX/SZ/399283 +IX/SZ/399281 +IX/SH/000041 +IX/SH/000106 +IX/SH/000053 +IX/SH/000149 +IX/SH/000017 +IX/SH/000045 +IX/SH/000057 +IX/SH/000134 +IX/SH/000814 +IX/SH/000993 +IX/SZ/399807 +IX/SZ/399688 +IX/SZ/399614 +IX/SH/000075 +IX/SH/000064 +IX/SH/000135 +IX/SH/000020 +IX/SH/000049 +IX/SZ/399993 +IX/SZ/399967 +IX/SZ/399901 +IX/SZ/399806 +IX/SZ/399685 +IX/SZ/399656 +IX/SZ/399621 +IX/SZ/399602 +IX/SZ/399419 +IX/SZ/399397 +IX/SZ/399379 +IX/SZ/399992 +IX/SZ/399973 +IX/SZ/399699 +IX/SZ/399649 +IX/SZ/399622 +IX/SZ/399433 +IX/SZ/399422 +IX/SZ/399416 +IX/SZ/399297 +IX/SZ/399292 +IX/SZ/399249 +IX/SH/000150 +IX/SH/000027 +IX/SH/000146 +IX/SH/000103 +IX/SZ/399686 +IX/SZ/399552 +IX/SZ/399410 +IX/SZ/399402 +IX/SZ/399320 +IX/SZ/399301 +IX/SZ/399296 +IX/SZ/399101 +IX/SZ/399100 +IX/SH/000044 +IX/SH/000016 +IX/SH/000104 +IX/SH/000863 +IX/SH/000070 +IX/SH/000065 +IX/SZ/399679 +IX/SZ/399650 +IX/SZ/399648 +IX/SZ/399396 +IX/SZ/399350 +IX/SZ/399106 +IX/SZ/399002 +IX/SH/000074 +IX/SH/000007 +IX/SH/000849 +IX/SH/000987 +IX/SH/000982 +IX/SZ/399705 +IX/SZ/399619 +IX/SZ/399613 +IX/SZ/399606 +IX/SZ/399550 +IX/SZ/399439 +IX/SZ/399415 +IX/SZ/399398 +IX/SZ/399372 +IX/SZ/399363 +IX/SZ/399352 +IX/SZ/399279 +IX/SZ/399238 +IX/SH/000133 +IX/SH/000093 +IX/SH/000802 +IX/SH/000928 +IX/SH/000050 +IX/SZ/399983 +IX/SZ/399982 +IX/SZ/399680 +IX/SZ/399669 +IX/SZ/399660 +IX/SZ/399643 +IX/SZ/399632 +IX/SZ/399617 +IX/SZ/399610 +IX/SZ/399388 +IX/SZ/399366 +IX/SZ/399359 +IX/SZ/399293 +IX/SZ/399239 +IX/SZ/399018 +IX/SZ/399354 +IX/SZ/399351 +IX/SZ/399285 +IX/SZ/399278 +IX/SH/000036 +IX/SH/000011 +IX/SH/000141 +IX/SH/000002 +IX/SH/000901 +IX/SH/000151 +IX/SH/000034 +IX/SH/000063 +IX/SZ/399995 +IX/SZ/399678 +IX/SZ/399670 +IX/SZ/399631 +IX/SZ/399399 +IX/SZ/399392 +IX/SZ/399368 +IX/SZ/399330 +IX/SZ/399294 +IX/SZ/399006 +IX/SH/000992 +IX/SH/000914 +IX/SH/000003 +IX/SG/STI +IX/SG/FSTC +IX/HK/HSCEI +IX/HK/HSCCI +IX/HK/HSTECH +IX/HK/HSI diff --git a/rust/src/utils/US-WT.csv b/rust/src/utils/US-WT.csv new file mode 100644 index 000000000..ec481c427 --- /dev/null +++ b/rust/src/utils/US-WT.csv @@ -0,0 +1,17693 @@ +WT/HK/10005 +WT/HK/10006 +WT/HK/10012 +WT/HK/10032 +WT/HK/10033 +WT/HK/10034 +WT/HK/10035 +WT/HK/10042 +WT/HK/10043 +WT/HK/10044 +WT/HK/10045 +WT/HK/10046 +WT/HK/10050 +WT/HK/10054 +WT/HK/10058 +WT/HK/10059 +WT/HK/10060 +WT/HK/10062 +WT/HK/10063 +WT/HK/10064 +WT/HK/10065 +WT/HK/10068 +WT/HK/10076 +WT/HK/10078 +WT/HK/10079 +WT/HK/10080 +WT/HK/10081 +WT/HK/10082 +WT/HK/10083 +WT/HK/10084 +WT/HK/10085 +WT/HK/10086 +WT/HK/10087 +WT/HK/10088 +WT/HK/10089 +WT/HK/10090 +WT/HK/10091 +WT/HK/10094 +WT/HK/10095 +WT/HK/10096 +WT/HK/10098 +WT/HK/10099 +WT/HK/10100 +WT/HK/10101 +WT/HK/10102 +WT/HK/10103 +WT/HK/10104 +WT/HK/10105 +WT/HK/10106 +WT/HK/10760 +WT/HK/10777 +WT/HK/10778 +WT/HK/10779 +WT/HK/10796 +WT/HK/10797 +WT/HK/10798 +WT/HK/10799 +WT/HK/10900 +WT/HK/10901 +WT/HK/10902 +WT/HK/10903 +WT/HK/11000 +WT/HK/11001 +WT/HK/11002 +WT/HK/11003 +WT/HK/11004 +WT/HK/11005 +WT/HK/11006 +WT/HK/11007 +WT/HK/11008 +WT/HK/11009 +WT/HK/11010 +WT/HK/11011 +WT/HK/11012 +WT/HK/11013 +WT/HK/11014 +WT/HK/11015 +WT/HK/11016 +WT/HK/11017 +WT/HK/11018 +WT/HK/11019 +WT/HK/11020 +WT/HK/11021 +WT/HK/11022 +WT/HK/11023 +WT/HK/11024 +WT/HK/11025 +WT/HK/11026 +WT/HK/11027 +WT/HK/11028 +WT/HK/11029 +WT/HK/11030 +WT/HK/11031 +WT/HK/11032 +WT/HK/11033 +WT/HK/11034 +WT/HK/11035 +WT/HK/11036 +WT/HK/11037 +WT/HK/11038 +WT/HK/11039 +WT/HK/11040 +WT/HK/11041 +WT/HK/11042 +WT/HK/11043 +WT/HK/11044 +WT/HK/11046 +WT/HK/11047 +WT/HK/11048 +WT/HK/11049 +WT/HK/11050 +WT/HK/11051 +WT/HK/11052 +WT/HK/11053 +WT/HK/11054 +WT/HK/11055 +WT/HK/11056 +WT/HK/11057 +WT/HK/11058 +WT/HK/11059 +WT/HK/11060 +WT/HK/11061 +WT/HK/11062 +WT/HK/11063 +WT/HK/11064 +WT/HK/11065 +WT/HK/11066 +WT/HK/11067 +WT/HK/11068 +WT/HK/11069 +WT/HK/11070 +WT/HK/11071 +WT/HK/11072 +WT/HK/11073 +WT/HK/11074 +WT/HK/11075 +WT/HK/11076 +WT/HK/11077 +WT/HK/11078 +WT/HK/11079 +WT/HK/11080 +WT/HK/11081 +WT/HK/11082 +WT/HK/11083 +WT/HK/11084 +WT/HK/11085 +WT/HK/11086 +WT/HK/11087 +WT/HK/11088 +WT/HK/11089 +WT/HK/11090 +WT/HK/11091 +WT/HK/11092 +WT/HK/11093 +WT/HK/11094 +WT/HK/11095 +WT/HK/11096 +WT/HK/11097 +WT/HK/11098 +WT/HK/11099 +WT/HK/11100 +WT/HK/11101 +WT/HK/11102 +WT/HK/11103 +WT/HK/11104 +WT/HK/11105 +WT/HK/11106 +WT/HK/11107 +WT/HK/11108 +WT/HK/11109 +WT/HK/11110 +WT/HK/11111 +WT/HK/11112 +WT/HK/11113 +WT/HK/11114 +WT/HK/11115 +WT/HK/11116 +WT/HK/11117 +WT/HK/11118 +WT/HK/11119 +WT/HK/11120 +WT/HK/11121 +WT/HK/11122 +WT/HK/11123 +WT/HK/11124 +WT/HK/11125 +WT/HK/11126 +WT/HK/11127 +WT/HK/11128 +WT/HK/11129 +WT/HK/11130 +WT/HK/11131 +WT/HK/11132 +WT/HK/11133 +WT/HK/11134 +WT/HK/11135 +WT/HK/11136 +WT/HK/11137 +WT/HK/11138 +WT/HK/11139 +WT/HK/11140 +WT/HK/11141 +WT/HK/11142 +WT/HK/11143 +WT/HK/11144 +WT/HK/11145 +WT/HK/11146 +WT/HK/11147 +WT/HK/11148 +WT/HK/11149 +WT/HK/11151 +WT/HK/11152 +WT/HK/11153 +WT/HK/11154 +WT/HK/11155 +WT/HK/11156 +WT/HK/11157 +WT/HK/11158 +WT/HK/11772 +WT/HK/12421 +WT/HK/12427 +WT/HK/13005 +WT/HK/13022 +WT/HK/13036 +WT/HK/13039 +WT/HK/13043 +WT/HK/13050 +WT/HK/13051 +WT/HK/13056 +WT/HK/13073 +WT/HK/13094 +WT/HK/13095 +WT/HK/13097 +WT/HK/13106 +WT/HK/13108 +WT/HK/13109 +WT/HK/13111 +WT/HK/13113 +WT/HK/13123 +WT/HK/13126 +WT/HK/13135 +WT/HK/13138 +WT/HK/13140 +WT/HK/13142 +WT/HK/13147 +WT/HK/13149 +WT/HK/13156 +WT/HK/13172 +WT/HK/13178 +WT/HK/13186 +WT/HK/13188 +WT/HK/13194 +WT/HK/13196 +WT/HK/13200 +WT/HK/13204 +WT/HK/13208 +WT/HK/13210 +WT/HK/13212 +WT/HK/13220 +WT/HK/13222 +WT/HK/13229 +WT/HK/13235 +WT/HK/13236 +WT/HK/13245 +WT/HK/13250 +WT/HK/13257 +WT/HK/13266 +WT/HK/13288 +WT/HK/13289 +WT/HK/13297 +WT/HK/13307 +WT/HK/13317 +WT/HK/13326 +WT/HK/13327 +WT/HK/13333 +WT/HK/13337 +WT/HK/13339 +WT/HK/13346 +WT/HK/13348 +WT/HK/13351 +WT/HK/13354 +WT/HK/13356 +WT/HK/13377 +WT/HK/13390 +WT/HK/13396 +WT/HK/13402 +WT/HK/13407 +WT/HK/13411 +WT/HK/13423 +WT/HK/13433 +WT/HK/13434 +WT/HK/13439 +WT/HK/13454 +WT/HK/13456 +WT/HK/13460 +WT/HK/13463 +WT/HK/13476 +WT/HK/13483 +WT/HK/13493 +WT/HK/13522 +WT/HK/13541 +WT/HK/13551 +WT/HK/13554 +WT/HK/13569 +WT/HK/13591 +WT/HK/13598 +WT/HK/13604 +WT/HK/13612 +WT/HK/13622 +WT/HK/13629 +WT/HK/13630 +WT/HK/13633 +WT/HK/13641 +WT/HK/13643 +WT/HK/13650 +WT/HK/13662 +WT/HK/13663 +WT/HK/13689 +WT/HK/13705 +WT/HK/13712 +WT/HK/13718 +WT/HK/13735 +WT/HK/13746 +WT/HK/13778 +WT/HK/13807 +WT/HK/13832 +WT/HK/13889 +WT/HK/13911 +WT/HK/13923 +WT/HK/13932 +WT/HK/13968 +WT/HK/13979 +WT/HK/13987 +WT/HK/13991 +WT/HK/14001 +WT/HK/14022 +WT/HK/14026 +WT/HK/14027 +WT/HK/14056 +WT/HK/14103 +WT/HK/14112 +WT/HK/14136 +WT/HK/14148 +WT/HK/14149 +WT/HK/14151 +WT/HK/14162 +WT/HK/14178 +WT/HK/14186 +WT/HK/14200 +WT/HK/14201 +WT/HK/14208 +WT/HK/14210 +WT/HK/14219 +WT/HK/14278 +WT/HK/14297 +WT/HK/14305 +WT/HK/14313 +WT/HK/14320 +WT/HK/14321 +WT/HK/14322 +WT/HK/14328 +WT/HK/14333 +WT/HK/14335 +WT/HK/14383 +WT/HK/14384 +WT/HK/14387 +WT/HK/14394 +WT/HK/14401 +WT/HK/14414 +WT/HK/14425 +WT/HK/14438 +WT/HK/14447 +WT/HK/14454 +WT/HK/14490 +WT/HK/14530 +WT/HK/14533 +WT/HK/14551 +WT/HK/14590 +WT/HK/14609 +WT/HK/14611 +WT/HK/14612 +WT/HK/14616 +WT/HK/14620 +WT/HK/14635 +WT/HK/14638 +WT/HK/14647 +WT/HK/14652 +WT/HK/14653 +WT/HK/14655 +WT/HK/14657 +WT/HK/14658 +WT/HK/14660 +WT/HK/14662 +WT/HK/14666 +WT/HK/14681 +WT/HK/14683 +WT/HK/14687 +WT/HK/14688 +WT/HK/14700 +WT/HK/14707 +WT/HK/14711 +WT/HK/14724 +WT/HK/14725 +WT/HK/14731 +WT/HK/14733 +WT/HK/14757 +WT/HK/14792 +WT/HK/14798 +WT/HK/14799 +WT/HK/14802 +WT/HK/14806 +WT/HK/14820 +WT/HK/14826 +WT/HK/14833 +WT/HK/14849 +WT/HK/14856 +WT/HK/14862 +WT/HK/14873 +WT/HK/14892 +WT/HK/14920 +WT/HK/14924 +WT/HK/14937 +WT/HK/14958 +WT/HK/14967 +WT/HK/14976 +WT/HK/14980 +WT/HK/15002 +WT/HK/15005 +WT/HK/15013 +WT/HK/15044 +WT/HK/15055 +WT/HK/15072 +WT/HK/15079 +WT/HK/15080 +WT/HK/15092 +WT/HK/15097 +WT/HK/15110 +WT/HK/15116 +WT/HK/15123 +WT/HK/15163 +WT/HK/15168 +WT/HK/15174 +WT/HK/15176 +WT/HK/15198 +WT/HK/15212 +WT/HK/15213 +WT/HK/15223 +WT/HK/15239 +WT/HK/15263 +WT/HK/15264 +WT/HK/15275 +WT/HK/15286 +WT/HK/15304 +WT/HK/15306 +WT/HK/15310 +WT/HK/15312 +WT/HK/15326 +WT/HK/15333 +WT/HK/15338 +WT/HK/15343 +WT/HK/15350 +WT/HK/15366 +WT/HK/15373 +WT/HK/15374 +WT/HK/15403 +WT/HK/15409 +WT/HK/15417 +WT/HK/15433 +WT/HK/15436 +WT/HK/15438 +WT/HK/15441 +WT/HK/15457 +WT/HK/15458 +WT/HK/15463 +WT/HK/15468 +WT/HK/15478 +WT/HK/15480 +WT/HK/15493 +WT/HK/15505 +WT/HK/15509 +WT/HK/15516 +WT/HK/15519 +WT/HK/15532 +WT/HK/15533 +WT/HK/15534 +WT/HK/15553 +WT/HK/15560 +WT/HK/15586 +WT/HK/15589 +WT/HK/15606 +WT/HK/15614 +WT/HK/15644 +WT/HK/15648 +WT/HK/15652 +WT/HK/15654 +WT/HK/15660 +WT/HK/15673 +WT/HK/15685 +WT/HK/15691 +WT/HK/15692 +WT/HK/15699 +WT/HK/15728 +WT/HK/15732 +WT/HK/15751 +WT/HK/15755 +WT/HK/15759 +WT/HK/15772 +WT/HK/15792 +WT/HK/15842 +WT/HK/15849 +WT/HK/15865 +WT/HK/15867 +WT/HK/15872 +WT/HK/15878 +WT/HK/15892 +WT/HK/15904 +WT/HK/15905 +WT/HK/15911 +WT/HK/15920 +WT/HK/15921 +WT/HK/15927 +WT/HK/15953 +WT/HK/15954 +WT/HK/15967 +WT/HK/16004 +WT/HK/16022 +WT/HK/16036 +WT/HK/16040 +WT/HK/16067 +WT/HK/16080 +WT/HK/16090 +WT/HK/16117 +WT/HK/16130 +WT/HK/16136 +WT/HK/16140 +WT/HK/16167 +WT/HK/16185 +WT/HK/16190 +WT/HK/16196 +WT/HK/16198 +WT/HK/16206 +WT/HK/16209 +WT/HK/16221 +WT/HK/16225 +WT/HK/16235 +WT/HK/16242 +WT/HK/16244 +WT/HK/16247 +WT/HK/16253 +WT/HK/16263 +WT/HK/16266 +WT/HK/16278 +WT/HK/16281 +WT/HK/16286 +WT/HK/16300 +WT/HK/16350 +WT/HK/16369 +WT/HK/16370 +WT/HK/16395 +WT/HK/16396 +WT/HK/16398 +WT/HK/16435 +WT/HK/16437 +WT/HK/16456 +WT/HK/16463 +WT/HK/16465 +WT/HK/16472 +WT/HK/16478 +WT/HK/16480 +WT/HK/16497 +WT/HK/16511 +WT/HK/16532 +WT/HK/16534 +WT/HK/16536 +WT/HK/16540 +WT/HK/16543 +WT/HK/16544 +WT/HK/16549 +WT/HK/16564 +WT/HK/16592 +WT/HK/16601 +WT/HK/16602 +WT/HK/16612 +WT/HK/16620 +WT/HK/16621 +WT/HK/16628 +WT/HK/16632 +WT/HK/16665 +WT/HK/16667 +WT/HK/16676 +WT/HK/16677 +WT/HK/16697 +WT/HK/16699 +WT/HK/16709 +WT/HK/16710 +WT/HK/16725 +WT/HK/16737 +WT/HK/16760 +WT/HK/16765 +WT/HK/16771 +WT/HK/16772 +WT/HK/16774 +WT/HK/16783 +WT/HK/16823 +WT/HK/16831 +WT/HK/16833 +WT/HK/16844 +WT/HK/16853 +WT/HK/16855 +WT/HK/16858 +WT/HK/16859 +WT/HK/16864 +WT/HK/16883 +WT/HK/16885 +WT/HK/16901 +WT/HK/16904 +WT/HK/16906 +WT/HK/16908 +WT/HK/16915 +WT/HK/16922 +WT/HK/16931 +WT/HK/16942 +WT/HK/16953 +WT/HK/16956 +WT/HK/16957 +WT/HK/16962 +WT/HK/16973 +WT/HK/16994 +WT/HK/16997 +WT/HK/17006 +WT/HK/17010 +WT/HK/17011 +WT/HK/17012 +WT/HK/17017 +WT/HK/17019 +WT/HK/17027 +WT/HK/17028 +WT/HK/17036 +WT/HK/17038 +WT/HK/17046 +WT/HK/17050 +WT/HK/17059 +WT/HK/17060 +WT/HK/17084 +WT/HK/17089 +WT/HK/17090 +WT/HK/17098 +WT/HK/17102 +WT/HK/17105 +WT/HK/17108 +WT/HK/17109 +WT/HK/17121 +WT/HK/17123 +WT/HK/17124 +WT/HK/17132 +WT/HK/17138 +WT/HK/17139 +WT/HK/17141 +WT/HK/17142 +WT/HK/17146 +WT/HK/17151 +WT/HK/17153 +WT/HK/17154 +WT/HK/17170 +WT/HK/17171 +WT/HK/17176 +WT/HK/17177 +WT/HK/17183 +WT/HK/17190 +WT/HK/17199 +WT/HK/17207 +WT/HK/17208 +WT/HK/17212 +WT/HK/17213 +WT/HK/17216 +WT/HK/17220 +WT/HK/17226 +WT/HK/17227 +WT/HK/17234 +WT/HK/17244 +WT/HK/17248 +WT/HK/17254 +WT/HK/17255 +WT/HK/17259 +WT/HK/17269 +WT/HK/17270 +WT/HK/17284 +WT/HK/17291 +WT/HK/17301 +WT/HK/17308 +WT/HK/17313 +WT/HK/17317 +WT/HK/17327 +WT/HK/17329 +WT/HK/17331 +WT/HK/17334 +WT/HK/17341 +WT/HK/17353 +WT/HK/17356 +WT/HK/17362 +WT/HK/17363 +WT/HK/17366 +WT/HK/17368 +WT/HK/17378 +WT/HK/17380 +WT/HK/17381 +WT/HK/17395 +WT/HK/17397 +WT/HK/17415 +WT/HK/17417 +WT/HK/17419 +WT/HK/17430 +WT/HK/17431 +WT/HK/17440 +WT/HK/17442 +WT/HK/17444 +WT/HK/17449 +WT/HK/17450 +WT/HK/17453 +WT/HK/17457 +WT/HK/17472 +WT/HK/17473 +WT/HK/17474 +WT/HK/17479 +WT/HK/17484 +WT/HK/17485 +WT/HK/17490 +WT/HK/17493 +WT/HK/17497 +WT/HK/17498 +WT/HK/17500 +WT/HK/17507 +WT/HK/17508 +WT/HK/17515 +WT/HK/17544 +WT/HK/17545 +WT/HK/17551 +WT/HK/17553 +WT/HK/17555 +WT/HK/17566 +WT/HK/17575 +WT/HK/17576 +WT/HK/17577 +WT/HK/17579 +WT/HK/17584 +WT/HK/17588 +WT/HK/17589 +WT/HK/17591 +WT/HK/17592 +WT/HK/17593 +WT/HK/17594 +WT/HK/17606 +WT/HK/17609 +WT/HK/17612 +WT/HK/17615 +WT/HK/17617 +WT/HK/17622 +WT/HK/17624 +WT/HK/17633 +WT/HK/17637 +WT/HK/17638 +WT/HK/17640 +WT/HK/17641 +WT/HK/17643 +WT/HK/17646 +WT/HK/17659 +WT/HK/17672 +WT/HK/17673 +WT/HK/17682 +WT/HK/17690 +WT/HK/17693 +WT/HK/17695 +WT/HK/17699 +WT/HK/17700 +WT/HK/17701 +WT/HK/17712 +WT/HK/17714 +WT/HK/17717 +WT/HK/17723 +WT/HK/17724 +WT/HK/17728 +WT/HK/17729 +WT/HK/17739 +WT/HK/17749 +WT/HK/17752 +WT/HK/17753 +WT/HK/17757 +WT/HK/17759 +WT/HK/17770 +WT/HK/17771 +WT/HK/17773 +WT/HK/17777 +WT/HK/17781 +WT/HK/17791 +WT/HK/17801 +WT/HK/17802 +WT/HK/17804 +WT/HK/17807 +WT/HK/17809 +WT/HK/17814 +WT/HK/17815 +WT/HK/17824 +WT/HK/17828 +WT/HK/17835 +WT/HK/17838 +WT/HK/17839 +WT/HK/17842 +WT/HK/17863 +WT/HK/17879 +WT/HK/17888 +WT/HK/17894 +WT/HK/17896 +WT/HK/17918 +WT/HK/17919 +WT/HK/17923 +WT/HK/17934 +WT/HK/17937 +WT/HK/17957 +WT/HK/17961 +WT/HK/17964 +WT/HK/17968 +WT/HK/17970 +WT/HK/17972 +WT/HK/17992 +WT/HK/17995 +WT/HK/17996 +WT/HK/17997 +WT/HK/18020 +WT/HK/18031 +WT/HK/18064 +WT/HK/18066 +WT/HK/18068 +WT/HK/18080 +WT/HK/18106 +WT/HK/18116 +WT/HK/18124 +WT/HK/18128 +WT/HK/18130 +WT/HK/18134 +WT/HK/18139 +WT/HK/18140 +WT/HK/18143 +WT/HK/18152 +WT/HK/18158 +WT/HK/18161 +WT/HK/18162 +WT/HK/18163 +WT/HK/18167 +WT/HK/18178 +WT/HK/18182 +WT/HK/18187 +WT/HK/18194 +WT/HK/18196 +WT/HK/18198 +WT/HK/18201 +WT/HK/18202 +WT/HK/18204 +WT/HK/18205 +WT/HK/18207 +WT/HK/18212 +WT/HK/18213 +WT/HK/18218 +WT/HK/18220 +WT/HK/18224 +WT/HK/18226 +WT/HK/18228 +WT/HK/18232 +WT/HK/18237 +WT/HK/18253 +WT/HK/18258 +WT/HK/18262 +WT/HK/18263 +WT/HK/18278 +WT/HK/18281 +WT/HK/18288 +WT/HK/18290 +WT/HK/18291 +WT/HK/18292 +WT/HK/18293 +WT/HK/18297 +WT/HK/18300 +WT/HK/18305 +WT/HK/18310 +WT/HK/18311 +WT/HK/18324 +WT/HK/18333 +WT/HK/18347 +WT/HK/18352 +WT/HK/18353 +WT/HK/18362 +WT/HK/18367 +WT/HK/18368 +WT/HK/18369 +WT/HK/18370 +WT/HK/18379 +WT/HK/18386 +WT/HK/18387 +WT/HK/18389 +WT/HK/18397 +WT/HK/18402 +WT/HK/18404 +WT/HK/18411 +WT/HK/18418 +WT/HK/18419 +WT/HK/18442 +WT/HK/18451 +WT/HK/18456 +WT/HK/18457 +WT/HK/18463 +WT/HK/18474 +WT/HK/18487 +WT/HK/18495 +WT/HK/18497 +WT/HK/18504 +WT/HK/18507 +WT/HK/18509 +WT/HK/18510 +WT/HK/18511 +WT/HK/18512 +WT/HK/18513 +WT/HK/18515 +WT/HK/18521 +WT/HK/18522 +WT/HK/18526 +WT/HK/18527 +WT/HK/18530 +WT/HK/18535 +WT/HK/18537 +WT/HK/18540 +WT/HK/18555 +WT/HK/18558 +WT/HK/18567 +WT/HK/18577 +WT/HK/18579 +WT/HK/18585 +WT/HK/18591 +WT/HK/18594 +WT/HK/18596 +WT/HK/18600 +WT/HK/18610 +WT/HK/18612 +WT/HK/18613 +WT/HK/18614 +WT/HK/18616 +WT/HK/18625 +WT/HK/18629 +WT/HK/18636 +WT/HK/18640 +WT/HK/18644 +WT/HK/18649 +WT/HK/18650 +WT/HK/18655 +WT/HK/18664 +WT/HK/18671 +WT/HK/18673 +WT/HK/18677 +WT/HK/18682 +WT/HK/18683 +WT/HK/18686 +WT/HK/18689 +WT/HK/18690 +WT/HK/18692 +WT/HK/18693 +WT/HK/18707 +WT/HK/18713 +WT/HK/18718 +WT/HK/18719 +WT/HK/18720 +WT/HK/18723 +WT/HK/18730 +WT/HK/18733 +WT/HK/18734 +WT/HK/18735 +WT/HK/18743 +WT/HK/18750 +WT/HK/18754 +WT/HK/18756 +WT/HK/18760 +WT/HK/18766 +WT/HK/18771 +WT/HK/18772 +WT/HK/18773 +WT/HK/18775 +WT/HK/18780 +WT/HK/18786 +WT/HK/18793 +WT/HK/18807 +WT/HK/18811 +WT/HK/18812 +WT/HK/18813 +WT/HK/18814 +WT/HK/18816 +WT/HK/18818 +WT/HK/18822 +WT/HK/18825 +WT/HK/18828 +WT/HK/18829 +WT/HK/18833 +WT/HK/18835 +WT/HK/18836 +WT/HK/18837 +WT/HK/18840 +WT/HK/18849 +WT/HK/18855 +WT/HK/18858 +WT/HK/18870 +WT/HK/18873 +WT/HK/18874 +WT/HK/18878 +WT/HK/18884 +WT/HK/18887 +WT/HK/18888 +WT/HK/18903 +WT/HK/18905 +WT/HK/18911 +WT/HK/18916 +WT/HK/18917 +WT/HK/18919 +WT/HK/18920 +WT/HK/18924 +WT/HK/18931 +WT/HK/18932 +WT/HK/18934 +WT/HK/18935 +WT/HK/18936 +WT/HK/18941 +WT/HK/18944 +WT/HK/18954 +WT/HK/18956 +WT/HK/18960 +WT/HK/18961 +WT/HK/18964 +WT/HK/18969 +WT/HK/18970 +WT/HK/18974 +WT/HK/18975 +WT/HK/18978 +WT/HK/18982 +WT/HK/18984 +WT/HK/18987 +WT/HK/18995 +WT/HK/18996 +WT/HK/18999 +WT/HK/19002 +WT/HK/19004 +WT/HK/19012 +WT/HK/19015 +WT/HK/19019 +WT/HK/19032 +WT/HK/19033 +WT/HK/19034 +WT/HK/19043 +WT/HK/19052 +WT/HK/19054 +WT/HK/19055 +WT/HK/19057 +WT/HK/19058 +WT/HK/19059 +WT/HK/19064 +WT/HK/19072 +WT/HK/19073 +WT/HK/19074 +WT/HK/19079 +WT/HK/19086 +WT/HK/19087 +WT/HK/19090 +WT/HK/19093 +WT/HK/19094 +WT/HK/19097 +WT/HK/19101 +WT/HK/19104 +WT/HK/19111 +WT/HK/19114 +WT/HK/19115 +WT/HK/19120 +WT/HK/19128 +WT/HK/19133 +WT/HK/19136 +WT/HK/19138 +WT/HK/19144 +WT/HK/19148 +WT/HK/19149 +WT/HK/19151 +WT/HK/19158 +WT/HK/19160 +WT/HK/19161 +WT/HK/19164 +WT/HK/19167 +WT/HK/19168 +WT/HK/19169 +WT/HK/19170 +WT/HK/19175 +WT/HK/19176 +WT/HK/19184 +WT/HK/19189 +WT/HK/19195 +WT/HK/19197 +WT/HK/19198 +WT/HK/19201 +WT/HK/19203 +WT/HK/19207 +WT/HK/19209 +WT/HK/19210 +WT/HK/19213 +WT/HK/19214 +WT/HK/19217 +WT/HK/19218 +WT/HK/19225 +WT/HK/19227 +WT/HK/19228 +WT/HK/19229 +WT/HK/19230 +WT/HK/19232 +WT/HK/19233 +WT/HK/19235 +WT/HK/19236 +WT/HK/19243 +WT/HK/19246 +WT/HK/19249 +WT/HK/19254 +WT/HK/19258 +WT/HK/19260 +WT/HK/19264 +WT/HK/19268 +WT/HK/19269 +WT/HK/19271 +WT/HK/19273 +WT/HK/19275 +WT/HK/19289 +WT/HK/19292 +WT/HK/19296 +WT/HK/19302 +WT/HK/19307 +WT/HK/19310 +WT/HK/19311 +WT/HK/19312 +WT/HK/19314 +WT/HK/19317 +WT/HK/19325 +WT/HK/19339 +WT/HK/19340 +WT/HK/19343 +WT/HK/19344 +WT/HK/19345 +WT/HK/19350 +WT/HK/19351 +WT/HK/19352 +WT/HK/19360 +WT/HK/19364 +WT/HK/19365 +WT/HK/19369 +WT/HK/19373 +WT/HK/19376 +WT/HK/19377 +WT/HK/19380 +WT/HK/19389 +WT/HK/19397 +WT/HK/19399 +WT/HK/19403 +WT/HK/19404 +WT/HK/19407 +WT/HK/19411 +WT/HK/19418 +WT/HK/19423 +WT/HK/19435 +WT/HK/19441 +WT/HK/19450 +WT/HK/19453 +WT/HK/19455 +WT/HK/19459 +WT/HK/19462 +WT/HK/19464 +WT/HK/19466 +WT/HK/19467 +WT/HK/19469 +WT/HK/19473 +WT/HK/19479 +WT/HK/19481 +WT/HK/19491 +WT/HK/19499 +WT/HK/19516 +WT/HK/19517 +WT/HK/19518 +WT/HK/19521 +WT/HK/19522 +WT/HK/19534 +WT/HK/19535 +WT/HK/19543 +WT/HK/19552 +WT/HK/19556 +WT/HK/19558 +WT/HK/19562 +WT/HK/19565 +WT/HK/19570 +WT/HK/19572 +WT/HK/19573 +WT/HK/19574 +WT/HK/19576 +WT/HK/19581 +WT/HK/19584 +WT/HK/19596 +WT/HK/19611 +WT/HK/19613 +WT/HK/19620 +WT/HK/19621 +WT/HK/19622 +WT/HK/19629 +WT/HK/19630 +WT/HK/19631 +WT/HK/19635 +WT/HK/19639 +WT/HK/19640 +WT/HK/19651 +WT/HK/19652 +WT/HK/19653 +WT/HK/19654 +WT/HK/19656 +WT/HK/19666 +WT/HK/19669 +WT/HK/19673 +WT/HK/19676 +WT/HK/19679 +WT/HK/19681 +WT/HK/19682 +WT/HK/19683 +WT/HK/19694 +WT/HK/19695 +WT/HK/19698 +WT/HK/19700 +WT/HK/19701 +WT/HK/19702 +WT/HK/19704 +WT/HK/19714 +WT/HK/19719 +WT/HK/19720 +WT/HK/19722 +WT/HK/19731 +WT/HK/19737 +WT/HK/19739 +WT/HK/19740 +WT/HK/19744 +WT/HK/19746 +WT/HK/19749 +WT/HK/19751 +WT/HK/19752 +WT/HK/19753 +WT/HK/19754 +WT/HK/19764 +WT/HK/19770 +WT/HK/19773 +WT/HK/19774 +WT/HK/19776 +WT/HK/19784 +WT/HK/19789 +WT/HK/19794 +WT/HK/19800 +WT/HK/19803 +WT/HK/19804 +WT/HK/19805 +WT/HK/19806 +WT/HK/19812 +WT/HK/19823 +WT/HK/19824 +WT/HK/19835 +WT/HK/19838 +WT/HK/19840 +WT/HK/19846 +WT/HK/19850 +WT/HK/19851 +WT/HK/19857 +WT/HK/19864 +WT/HK/19866 +WT/HK/19867 +WT/HK/19869 +WT/HK/19871 +WT/HK/19872 +WT/HK/19873 +WT/HK/19874 +WT/HK/19875 +WT/HK/19876 +WT/HK/19879 +WT/HK/19884 +WT/HK/19886 +WT/HK/19889 +WT/HK/19891 +WT/HK/19893 +WT/HK/19895 +WT/HK/19899 +WT/HK/19902 +WT/HK/19903 +WT/HK/19905 +WT/HK/19906 +WT/HK/19909 +WT/HK/19910 +WT/HK/19911 +WT/HK/19912 +WT/HK/19918 +WT/HK/19920 +WT/HK/19924 +WT/HK/19929 +WT/HK/19930 +WT/HK/19932 +WT/HK/19935 +WT/HK/19936 +WT/HK/19938 +WT/HK/19943 +WT/HK/19945 +WT/HK/19946 +WT/HK/19947 +WT/HK/19948 +WT/HK/19950 +WT/HK/19954 +WT/HK/19955 +WT/HK/19956 +WT/HK/19959 +WT/HK/19965 +WT/HK/19966 +WT/HK/19967 +WT/HK/19970 +WT/HK/19974 +WT/HK/19975 +WT/HK/19976 +WT/HK/19977 +WT/HK/19979 +WT/HK/19981 +WT/HK/19982 +WT/HK/19983 +WT/HK/19984 +WT/HK/19985 +WT/HK/19987 +WT/HK/19991 +WT/HK/20005 +WT/HK/20007 +WT/HK/20013 +WT/HK/20015 +WT/HK/20016 +WT/HK/20017 +WT/HK/20021 +WT/HK/20023 +WT/HK/20024 +WT/HK/20025 +WT/HK/20026 +WT/HK/20027 +WT/HK/20028 +WT/HK/20029 +WT/HK/20030 +WT/HK/20031 +WT/HK/20032 +WT/HK/20035 +WT/HK/20038 +WT/HK/20041 +WT/HK/20043 +WT/HK/20046 +WT/HK/20047 +WT/HK/20048 +WT/HK/20050 +WT/HK/20056 +WT/HK/20070 +WT/HK/20071 +WT/HK/20072 +WT/HK/20076 +WT/HK/20077 +WT/HK/20078 +WT/HK/20079 +WT/HK/20080 +WT/HK/20083 +WT/HK/20086 +WT/HK/20088 +WT/HK/20089 +WT/HK/20092 +WT/HK/20093 +WT/HK/20094 +WT/HK/20097 +WT/HK/20099 +WT/HK/20104 +WT/HK/20108 +WT/HK/20109 +WT/HK/20112 +WT/HK/20113 +WT/HK/20114 +WT/HK/20119 +WT/HK/20120 +WT/HK/20122 +WT/HK/20123 +WT/HK/20126 +WT/HK/20130 +WT/HK/20131 +WT/HK/20137 +WT/HK/20141 +WT/HK/20146 +WT/HK/20148 +WT/HK/20149 +WT/HK/20151 +WT/HK/20161 +WT/HK/20163 +WT/HK/20165 +WT/HK/20166 +WT/HK/20170 +WT/HK/20171 +WT/HK/20177 +WT/HK/20178 +WT/HK/20181 +WT/HK/20189 +WT/HK/20196 +WT/HK/20197 +WT/HK/20209 +WT/HK/20212 +WT/HK/20220 +WT/HK/20221 +WT/HK/20230 +WT/HK/20237 +WT/HK/20243 +WT/HK/20249 +WT/HK/20252 +WT/HK/20254 +WT/HK/20255 +WT/HK/20259 +WT/HK/20260 +WT/HK/20264 +WT/HK/20265 +WT/HK/20270 +WT/HK/20287 +WT/HK/20290 +WT/HK/20291 +WT/HK/20294 +WT/HK/20303 +WT/HK/20305 +WT/HK/20310 +WT/HK/20311 +WT/HK/20314 +WT/HK/20320 +WT/HK/20322 +WT/HK/20324 +WT/HK/20326 +WT/HK/20335 +WT/HK/20340 +WT/HK/20341 +WT/HK/20342 +WT/HK/20352 +WT/HK/20355 +WT/HK/20356 +WT/HK/20357 +WT/HK/20362 +WT/HK/20367 +WT/HK/20368 +WT/HK/20371 +WT/HK/20375 +WT/HK/20377 +WT/HK/20380 +WT/HK/20384 +WT/HK/20387 +WT/HK/20390 +WT/HK/20391 +WT/HK/20399 +WT/HK/20401 +WT/HK/20405 +WT/HK/20407 +WT/HK/20416 +WT/HK/20418 +WT/HK/20421 +WT/HK/20427 +WT/HK/20430 +WT/HK/20436 +WT/HK/20440 +WT/HK/20441 +WT/HK/20442 +WT/HK/20444 +WT/HK/20446 +WT/HK/20448 +WT/HK/20449 +WT/HK/20451 +WT/HK/20452 +WT/HK/20453 +WT/HK/20454 +WT/HK/20459 +WT/HK/20461 +WT/HK/20462 +WT/HK/20464 +WT/HK/20470 +WT/HK/20471 +WT/HK/20472 +WT/HK/20473 +WT/HK/20475 +WT/HK/20480 +WT/HK/20483 +WT/HK/20486 +WT/HK/20487 +WT/HK/20496 +WT/HK/20501 +WT/HK/20502 +WT/HK/20503 +WT/HK/20508 +WT/HK/20512 +WT/HK/20515 +WT/HK/20524 +WT/HK/20532 +WT/HK/20533 +WT/HK/20534 +WT/HK/20535 +WT/HK/20548 +WT/HK/20554 +WT/HK/20558 +WT/HK/20559 +WT/HK/20561 +WT/HK/20567 +WT/HK/20569 +WT/HK/20573 +WT/HK/20579 +WT/HK/20581 +WT/HK/20584 +WT/HK/20589 +WT/HK/20601 +WT/HK/20604 +WT/HK/20606 +WT/HK/20611 +WT/HK/20612 +WT/HK/20615 +WT/HK/20622 +WT/HK/20628 +WT/HK/20629 +WT/HK/20631 +WT/HK/20632 +WT/HK/20634 +WT/HK/20635 +WT/HK/20640 +WT/HK/20642 +WT/HK/20643 +WT/HK/20648 +WT/HK/20657 +WT/HK/20659 +WT/HK/20660 +WT/HK/20665 +WT/HK/20670 +WT/HK/20672 +WT/HK/20676 +WT/HK/20679 +WT/HK/20683 +WT/HK/20685 +WT/HK/20688 +WT/HK/20694 +WT/HK/20698 +WT/HK/20700 +WT/HK/20701 +WT/HK/20705 +WT/HK/20708 +WT/HK/20715 +WT/HK/20719 +WT/HK/20723 +WT/HK/20725 +WT/HK/20726 +WT/HK/20739 +WT/HK/20744 +WT/HK/20747 +WT/HK/20748 +WT/HK/20757 +WT/HK/20760 +WT/HK/20770 +WT/HK/20773 +WT/HK/20774 +WT/HK/20780 +WT/HK/20782 +WT/HK/20783 +WT/HK/20784 +WT/HK/20785 +WT/HK/20788 +WT/HK/20790 +WT/HK/20792 +WT/HK/20793 +WT/HK/20798 +WT/HK/20802 +WT/HK/20803 +WT/HK/20806 +WT/HK/20812 +WT/HK/20814 +WT/HK/20815 +WT/HK/20819 +WT/HK/20823 +WT/HK/20826 +WT/HK/20827 +WT/HK/20837 +WT/HK/20839 +WT/HK/20848 +WT/HK/20850 +WT/HK/20851 +WT/HK/20853 +WT/HK/20856 +WT/HK/20858 +WT/HK/20859 +WT/HK/20860 +WT/HK/20862 +WT/HK/20872 +WT/HK/20875 +WT/HK/20879 +WT/HK/20881 +WT/HK/20882 +WT/HK/20883 +WT/HK/20896 +WT/HK/20907 +WT/HK/20909 +WT/HK/20910 +WT/HK/20915 +WT/HK/20916 +WT/HK/20917 +WT/HK/20918 +WT/HK/20920 +WT/HK/20922 +WT/HK/20923 +WT/HK/20929 +WT/HK/20933 +WT/HK/20935 +WT/HK/20938 +WT/HK/20943 +WT/HK/20945 +WT/HK/20949 +WT/HK/20952 +WT/HK/20953 +WT/HK/20958 +WT/HK/20960 +WT/HK/20961 +WT/HK/20968 +WT/HK/20969 +WT/HK/20970 +WT/HK/20971 +WT/HK/20972 +WT/HK/20974 +WT/HK/20978 +WT/HK/20982 +WT/HK/20983 +WT/HK/20986 +WT/HK/20992 +WT/HK/20993 +WT/HK/20998 +WT/HK/21001 +WT/HK/21002 +WT/HK/21005 +WT/HK/21008 +WT/HK/21015 +WT/HK/21019 +WT/HK/21023 +WT/HK/21026 +WT/HK/21032 +WT/HK/21033 +WT/HK/21036 +WT/HK/21040 +WT/HK/21041 +WT/HK/21051 +WT/HK/21057 +WT/HK/21058 +WT/HK/21059 +WT/HK/21061 +WT/HK/21063 +WT/HK/21064 +WT/HK/21065 +WT/HK/21073 +WT/HK/21075 +WT/HK/21079 +WT/HK/21088 +WT/HK/21090 +WT/HK/21091 +WT/HK/21092 +WT/HK/21093 +WT/HK/21094 +WT/HK/21095 +WT/HK/21096 +WT/HK/21097 +WT/HK/21098 +WT/HK/21109 +WT/HK/21110 +WT/HK/21112 +WT/HK/21113 +WT/HK/21114 +WT/HK/21116 +WT/HK/21117 +WT/HK/21121 +WT/HK/21123 +WT/HK/21124 +WT/HK/21125 +WT/HK/21126 +WT/HK/21128 +WT/HK/21131 +WT/HK/21132 +WT/HK/21136 +WT/HK/21138 +WT/HK/21142 +WT/HK/21143 +WT/HK/21144 +WT/HK/21145 +WT/HK/21146 +WT/HK/21147 +WT/HK/21148 +WT/HK/21161 +WT/HK/21162 +WT/HK/21169 +WT/HK/21189 +WT/HK/21192 +WT/HK/21194 +WT/HK/21196 +WT/HK/21197 +WT/HK/21198 +WT/HK/21201 +WT/HK/21217 +WT/HK/21218 +WT/HK/21224 +WT/HK/21227 +WT/HK/21228 +WT/HK/21232 +WT/HK/21233 +WT/HK/21235 +WT/HK/21238 +WT/HK/21241 +WT/HK/21242 +WT/HK/21252 +WT/HK/21254 +WT/HK/21255 +WT/HK/21257 +WT/HK/21263 +WT/HK/21274 +WT/HK/21275 +WT/HK/21281 +WT/HK/21283 +WT/HK/21284 +WT/HK/21285 +WT/HK/21287 +WT/HK/21291 +WT/HK/21293 +WT/HK/21294 +WT/HK/21298 +WT/HK/21314 +WT/HK/21315 +WT/HK/21321 +WT/HK/21322 +WT/HK/21323 +WT/HK/21335 +WT/HK/21337 +WT/HK/21352 +WT/HK/21359 +WT/HK/21360 +WT/HK/21366 +WT/HK/21367 +WT/HK/21374 +WT/HK/21375 +WT/HK/21379 +WT/HK/21380 +WT/HK/21381 +WT/HK/21383 +WT/HK/21385 +WT/HK/21386 +WT/HK/21387 +WT/HK/21388 +WT/HK/21389 +WT/HK/21390 +WT/HK/21391 +WT/HK/21392 +WT/HK/21393 +WT/HK/21394 +WT/HK/21395 +WT/HK/21396 +WT/HK/21404 +WT/HK/21412 +WT/HK/21413 +WT/HK/21417 +WT/HK/21424 +WT/HK/21433 +WT/HK/21434 +WT/HK/21435 +WT/HK/21436 +WT/HK/21437 +WT/HK/21439 +WT/HK/21447 +WT/HK/21448 +WT/HK/21449 +WT/HK/21450 +WT/HK/21451 +WT/HK/21452 +WT/HK/21453 +WT/HK/21454 +WT/HK/21455 +WT/HK/21458 +WT/HK/21459 +WT/HK/21460 +WT/HK/21461 +WT/HK/21466 +WT/HK/21469 +WT/HK/21473 +WT/HK/21475 +WT/HK/21476 +WT/HK/21477 +WT/HK/21478 +WT/HK/21484 +WT/HK/21485 +WT/HK/21486 +WT/HK/21487 +WT/HK/21488 +WT/HK/21493 +WT/HK/21494 +WT/HK/21496 +WT/HK/21498 +WT/HK/21502 +WT/HK/21508 +WT/HK/21509 +WT/HK/21510 +WT/HK/21514 +WT/HK/21519 +WT/HK/21524 +WT/HK/21526 +WT/HK/21527 +WT/HK/21528 +WT/HK/21530 +WT/HK/21536 +WT/HK/21538 +WT/HK/21539 +WT/HK/21541 +WT/HK/21542 +WT/HK/21549 +WT/HK/21556 +WT/HK/21557 +WT/HK/21558 +WT/HK/21563 +WT/HK/21569 +WT/HK/21570 +WT/HK/21574 +WT/HK/21581 +WT/HK/21582 +WT/HK/21583 +WT/HK/21584 +WT/HK/21588 +WT/HK/21589 +WT/HK/21598 +WT/HK/21602 +WT/HK/21603 +WT/HK/21606 +WT/HK/21607 +WT/HK/21610 +WT/HK/21615 +WT/HK/21621 +WT/HK/21627 +WT/HK/21628 +WT/HK/21629 +WT/HK/21632 +WT/HK/21634 +WT/HK/21635 +WT/HK/21637 +WT/HK/21640 +WT/HK/21641 +WT/HK/21642 +WT/HK/21643 +WT/HK/21644 +WT/HK/21646 +WT/HK/21647 +WT/HK/21649 +WT/HK/21650 +WT/HK/21652 +WT/HK/21654 +WT/HK/21655 +WT/HK/21656 +WT/HK/21657 +WT/HK/21660 +WT/HK/21665 +WT/HK/21666 +WT/HK/21670 +WT/HK/21673 +WT/HK/21674 +WT/HK/21675 +WT/HK/21676 +WT/HK/21677 +WT/HK/21678 +WT/HK/21680 +WT/HK/21681 +WT/HK/21682 +WT/HK/21683 +WT/HK/21684 +WT/HK/21685 +WT/HK/21688 +WT/HK/21689 +WT/HK/21691 +WT/HK/21692 +WT/HK/21694 +WT/HK/21695 +WT/HK/21696 +WT/HK/21697 +WT/HK/21699 +WT/HK/21700 +WT/HK/21701 +WT/HK/21704 +WT/HK/21705 +WT/HK/21707 +WT/HK/21708 +WT/HK/21709 +WT/HK/21715 +WT/HK/21717 +WT/HK/21718 +WT/HK/21719 +WT/HK/21721 +WT/HK/21723 +WT/HK/21725 +WT/HK/21726 +WT/HK/21727 +WT/HK/21728 +WT/HK/21729 +WT/HK/21730 +WT/HK/21736 +WT/HK/21737 +WT/HK/21738 +WT/HK/21741 +WT/HK/21742 +WT/HK/21745 +WT/HK/21747 +WT/HK/21748 +WT/HK/21749 +WT/HK/21750 +WT/HK/21751 +WT/HK/21753 +WT/HK/21758 +WT/HK/21759 +WT/HK/21760 +WT/HK/21763 +WT/HK/21765 +WT/HK/21767 +WT/HK/21769 +WT/HK/21770 +WT/HK/21771 +WT/HK/21772 +WT/HK/21773 +WT/HK/21775 +WT/HK/21776 +WT/HK/21780 +WT/HK/21783 +WT/HK/21785 +WT/HK/21787 +WT/HK/21789 +WT/HK/21791 +WT/HK/21792 +WT/HK/21796 +WT/HK/21801 +WT/HK/21815 +WT/HK/21821 +WT/HK/21823 +WT/HK/21830 +WT/HK/21834 +WT/HK/21836 +WT/HK/21837 +WT/HK/21839 +WT/HK/21840 +WT/HK/21841 +WT/HK/21843 +WT/HK/21844 +WT/HK/21845 +WT/HK/21846 +WT/HK/21847 +WT/HK/21855 +WT/HK/21856 +WT/HK/21857 +WT/HK/21859 +WT/HK/21862 +WT/HK/21869 +WT/HK/21870 +WT/HK/21871 +WT/HK/21873 +WT/HK/21874 +WT/HK/21875 +WT/HK/21878 +WT/HK/21879 +WT/HK/21880 +WT/HK/21881 +WT/HK/21882 +WT/HK/21887 +WT/HK/21888 +WT/HK/21892 +WT/HK/21893 +WT/HK/21896 +WT/HK/21897 +WT/HK/21898 +WT/HK/21900 +WT/HK/21903 +WT/HK/21904 +WT/HK/21909 +WT/HK/21910 +WT/HK/21911 +WT/HK/21912 +WT/HK/21913 +WT/HK/21915 +WT/HK/21916 +WT/HK/21917 +WT/HK/21918 +WT/HK/21919 +WT/HK/21923 +WT/HK/21924 +WT/HK/21925 +WT/HK/21928 +WT/HK/21929 +WT/HK/21930 +WT/HK/21934 +WT/HK/21935 +WT/HK/21936 +WT/HK/21939 +WT/HK/21940 +WT/HK/21941 +WT/HK/21942 +WT/HK/21943 +WT/HK/21944 +WT/HK/21946 +WT/HK/21949 +WT/HK/21954 +WT/HK/21956 +WT/HK/21959 +WT/HK/21960 +WT/HK/21962 +WT/HK/21964 +WT/HK/21965 +WT/HK/21967 +WT/HK/21971 +WT/HK/21972 +WT/HK/21973 +WT/HK/21974 +WT/HK/21976 +WT/HK/21977 +WT/HK/21978 +WT/HK/21980 +WT/HK/21981 +WT/HK/21984 +WT/HK/21985 +WT/HK/21988 +WT/HK/21990 +WT/HK/21993 +WT/HK/21997 +WT/HK/21998 +WT/HK/22000 +WT/HK/22001 +WT/HK/22002 +WT/HK/22003 +WT/HK/22004 +WT/HK/22005 +WT/HK/22006 +WT/HK/22007 +WT/HK/22008 +WT/HK/22009 +WT/HK/22010 +WT/HK/22011 +WT/HK/22013 +WT/HK/22018 +WT/HK/22020 +WT/HK/22023 +WT/HK/22027 +WT/HK/22034 +WT/HK/22037 +WT/HK/22039 +WT/HK/22043 +WT/HK/22044 +WT/HK/22045 +WT/HK/22046 +WT/HK/22049 +WT/HK/22051 +WT/HK/22053 +WT/HK/22054 +WT/HK/22055 +WT/HK/22056 +WT/HK/22057 +WT/HK/22058 +WT/HK/22059 +WT/HK/22060 +WT/HK/22062 +WT/HK/22063 +WT/HK/22064 +WT/HK/22065 +WT/HK/22066 +WT/HK/22071 +WT/HK/22072 +WT/HK/22073 +WT/HK/22074 +WT/HK/22077 +WT/HK/22084 +WT/HK/22085 +WT/HK/22090 +WT/HK/22091 +WT/HK/22093 +WT/HK/22094 +WT/HK/22095 +WT/HK/22097 +WT/HK/22098 +WT/HK/22105 +WT/HK/22108 +WT/HK/22112 +WT/HK/22113 +WT/HK/22114 +WT/HK/22115 +WT/HK/22116 +WT/HK/22117 +WT/HK/22118 +WT/HK/22119 +WT/HK/22120 +WT/HK/22123 +WT/HK/22124 +WT/HK/22125 +WT/HK/22126 +WT/HK/22130 +WT/HK/22137 +WT/HK/22138 +WT/HK/22146 +WT/HK/22149 +WT/HK/22153 +WT/HK/22157 +WT/HK/22159 +WT/HK/22160 +WT/HK/22162 +WT/HK/22165 +WT/HK/22166 +WT/HK/22168 +WT/HK/22169 +WT/HK/22172 +WT/HK/22173 +WT/HK/22174 +WT/HK/22177 +WT/HK/22178 +WT/HK/22179 +WT/HK/22182 +WT/HK/22184 +WT/HK/22185 +WT/HK/22186 +WT/HK/22192 +WT/HK/22193 +WT/HK/22199 +WT/HK/22200 +WT/HK/22201 +WT/HK/22202 +WT/HK/22204 +WT/HK/22205 +WT/HK/22206 +WT/HK/22207 +WT/HK/22208 +WT/HK/22209 +WT/HK/22211 +WT/HK/22212 +WT/HK/22213 +WT/HK/22216 +WT/HK/22218 +WT/HK/22219 +WT/HK/22221 +WT/HK/22222 +WT/HK/22223 +WT/HK/22224 +WT/HK/22226 +WT/HK/22227 +WT/HK/22228 +WT/HK/22229 +WT/HK/22230 +WT/HK/22231 +WT/HK/22232 +WT/HK/22233 +WT/HK/22235 +WT/HK/22236 +WT/HK/22238 +WT/HK/22239 +WT/HK/22242 +WT/HK/22249 +WT/HK/22250 +WT/HK/22251 +WT/HK/22252 +WT/HK/22253 +WT/HK/22254 +WT/HK/22255 +WT/HK/22256 +WT/HK/22257 +WT/HK/22262 +WT/HK/22268 +WT/HK/22272 +WT/HK/22273 +WT/HK/22274 +WT/HK/22276 +WT/HK/22277 +WT/HK/22280 +WT/HK/22283 +WT/HK/22284 +WT/HK/22287 +WT/HK/22292 +WT/HK/22294 +WT/HK/22296 +WT/HK/22299 +WT/HK/22300 +WT/HK/22302 +WT/HK/22303 +WT/HK/22304 +WT/HK/22305 +WT/HK/22306 +WT/HK/22308 +WT/HK/22309 +WT/HK/22310 +WT/HK/22312 +WT/HK/22313 +WT/HK/22314 +WT/HK/22316 +WT/HK/22317 +WT/HK/22318 +WT/HK/22319 +WT/HK/22322 +WT/HK/22323 +WT/HK/22324 +WT/HK/22325 +WT/HK/22326 +WT/HK/22327 +WT/HK/22330 +WT/HK/22331 +WT/HK/22332 +WT/HK/22333 +WT/HK/22334 +WT/HK/22335 +WT/HK/22336 +WT/HK/22337 +WT/HK/22340 +WT/HK/22341 +WT/HK/22342 +WT/HK/22344 +WT/HK/22345 +WT/HK/22346 +WT/HK/22347 +WT/HK/22348 +WT/HK/22349 +WT/HK/22350 +WT/HK/22352 +WT/HK/22353 +WT/HK/22354 +WT/HK/22356 +WT/HK/22357 +WT/HK/22358 +WT/HK/22359 +WT/HK/22360 +WT/HK/22361 +WT/HK/22362 +WT/HK/22363 +WT/HK/22364 +WT/HK/22365 +WT/HK/22366 +WT/HK/22375 +WT/HK/22377 +WT/HK/22378 +WT/HK/22380 +WT/HK/22381 +WT/HK/22382 +WT/HK/22383 +WT/HK/22385 +WT/HK/22386 +WT/HK/22387 +WT/HK/22388 +WT/HK/22390 +WT/HK/22395 +WT/HK/22396 +WT/HK/22397 +WT/HK/22398 +WT/HK/22399 +WT/HK/22400 +WT/HK/22401 +WT/HK/22402 +WT/HK/22403 +WT/HK/22404 +WT/HK/22405 +WT/HK/22408 +WT/HK/22409 +WT/HK/22410 +WT/HK/22411 +WT/HK/22412 +WT/HK/22413 +WT/HK/22415 +WT/HK/22418 +WT/HK/22419 +WT/HK/22420 +WT/HK/22421 +WT/HK/22422 +WT/HK/22423 +WT/HK/22424 +WT/HK/22425 +WT/HK/22426 +WT/HK/22427 +WT/HK/22429 +WT/HK/22431 +WT/HK/22433 +WT/HK/22436 +WT/HK/22437 +WT/HK/22439 +WT/HK/22440 +WT/HK/22441 +WT/HK/22442 +WT/HK/22443 +WT/HK/22444 +WT/HK/22445 +WT/HK/22446 +WT/HK/22448 +WT/HK/22449 +WT/HK/22450 +WT/HK/22453 +WT/HK/22454 +WT/HK/22455 +WT/HK/22457 +WT/HK/22458 +WT/HK/22459 +WT/HK/22460 +WT/HK/22462 +WT/HK/22463 +WT/HK/22464 +WT/HK/22465 +WT/HK/22466 +WT/HK/22467 +WT/HK/22469 +WT/HK/22470 +WT/HK/22471 +WT/HK/22472 +WT/HK/22473 +WT/HK/22474 +WT/HK/22475 +WT/HK/22476 +WT/HK/22477 +WT/HK/22480 +WT/HK/22481 +WT/HK/22482 +WT/HK/22483 +WT/HK/22484 +WT/HK/22485 +WT/HK/22487 +WT/HK/22488 +WT/HK/22489 +WT/HK/22490 +WT/HK/22493 +WT/HK/22494 +WT/HK/22495 +WT/HK/22496 +WT/HK/22497 +WT/HK/22498 +WT/HK/22499 +WT/HK/22500 +WT/HK/22501 +WT/HK/22502 +WT/HK/22503 +WT/HK/22504 +WT/HK/22505 +WT/HK/22508 +WT/HK/22509 +WT/HK/22510 +WT/HK/22511 +WT/HK/22512 +WT/HK/22515 +WT/HK/22516 +WT/HK/22520 +WT/HK/22521 +WT/HK/22522 +WT/HK/22523 +WT/HK/22524 +WT/HK/22525 +WT/HK/22526 +WT/HK/22527 +WT/HK/22528 +WT/HK/22529 +WT/HK/22531 +WT/HK/22532 +WT/HK/22534 +WT/HK/22535 +WT/HK/22536 +WT/HK/22538 +WT/HK/22539 +WT/HK/22542 +WT/HK/22543 +WT/HK/22544 +WT/HK/22545 +WT/HK/22546 +WT/HK/22549 +WT/HK/22550 +WT/HK/22551 +WT/HK/22552 +WT/HK/22555 +WT/HK/22556 +WT/HK/22557 +WT/HK/22558 +WT/HK/22559 +WT/HK/22560 +WT/HK/22561 +WT/HK/22562 +WT/HK/22564 +WT/HK/22565 +WT/HK/22566 +WT/HK/22567 +WT/HK/22568 +WT/HK/22569 +WT/HK/22571 +WT/HK/22573 +WT/HK/22574 +WT/HK/22575 +WT/HK/22576 +WT/HK/22577 +WT/HK/22578 +WT/HK/22580 +WT/HK/22581 +WT/HK/22582 +WT/HK/22583 +WT/HK/22584 +WT/HK/22587 +WT/HK/22588 +WT/HK/22589 +WT/HK/22590 +WT/HK/22591 +WT/HK/22592 +WT/HK/22593 +WT/HK/22594 +WT/HK/22595 +WT/HK/22598 +WT/HK/22600 +WT/HK/22603 +WT/HK/22605 +WT/HK/22606 +WT/HK/22607 +WT/HK/22608 +WT/HK/22609 +WT/HK/22610 +WT/HK/22611 +WT/HK/22612 +WT/HK/22614 +WT/HK/22615 +WT/HK/22616 +WT/HK/22617 +WT/HK/22618 +WT/HK/22619 +WT/HK/22620 +WT/HK/22621 +WT/HK/22622 +WT/HK/22626 +WT/HK/22627 +WT/HK/22628 +WT/HK/22629 +WT/HK/22630 +WT/HK/22631 +WT/HK/22632 +WT/HK/22633 +WT/HK/22634 +WT/HK/22635 +WT/HK/22636 +WT/HK/22637 +WT/HK/22638 +WT/HK/22639 +WT/HK/22640 +WT/HK/22641 +WT/HK/22643 +WT/HK/22644 +WT/HK/22645 +WT/HK/22646 +WT/HK/22647 +WT/HK/22649 +WT/HK/22650 +WT/HK/22651 +WT/HK/22652 +WT/HK/22654 +WT/HK/22655 +WT/HK/22656 +WT/HK/22657 +WT/HK/22658 +WT/HK/22659 +WT/HK/22660 +WT/HK/22663 +WT/HK/22664 +WT/HK/22667 +WT/HK/22668 +WT/HK/22670 +WT/HK/22671 +WT/HK/22672 +WT/HK/22673 +WT/HK/22674 +WT/HK/22675 +WT/HK/22676 +WT/HK/22677 +WT/HK/22678 +WT/HK/22679 +WT/HK/22680 +WT/HK/22681 +WT/HK/22682 +WT/HK/22683 +WT/HK/22684 +WT/HK/22686 +WT/HK/22687 +WT/HK/22688 +WT/HK/22689 +WT/HK/22691 +WT/HK/22693 +WT/HK/22694 +WT/HK/22695 +WT/HK/22700 +WT/HK/22703 +WT/HK/22704 +WT/HK/22706 +WT/HK/22709 +WT/HK/22710 +WT/HK/22711 +WT/HK/22712 +WT/HK/22713 +WT/HK/22714 +WT/HK/22715 +WT/HK/22716 +WT/HK/22718 +WT/HK/22719 +WT/HK/22720 +WT/HK/22722 +WT/HK/22723 +WT/HK/22724 +WT/HK/22726 +WT/HK/22728 +WT/HK/22729 +WT/HK/22731 +WT/HK/22732 +WT/HK/22733 +WT/HK/22737 +WT/HK/22739 +WT/HK/22740 +WT/HK/22741 +WT/HK/22742 +WT/HK/22743 +WT/HK/22744 +WT/HK/22745 +WT/HK/22746 +WT/HK/22747 +WT/HK/22748 +WT/HK/22749 +WT/HK/22750 +WT/HK/22751 +WT/HK/22752 +WT/HK/22753 +WT/HK/22754 +WT/HK/22755 +WT/HK/22757 +WT/HK/22758 +WT/HK/22760 +WT/HK/22761 +WT/HK/22762 +WT/HK/22764 +WT/HK/22765 +WT/HK/22766 +WT/HK/22767 +WT/HK/22768 +WT/HK/22769 +WT/HK/22771 +WT/HK/22772 +WT/HK/22774 +WT/HK/22775 +WT/HK/22776 +WT/HK/22777 +WT/HK/22778 +WT/HK/22779 +WT/HK/22780 +WT/HK/22781 +WT/HK/22782 +WT/HK/22783 +WT/HK/22785 +WT/HK/22787 +WT/HK/22788 +WT/HK/22789 +WT/HK/22790 +WT/HK/22791 +WT/HK/22792 +WT/HK/22793 +WT/HK/22794 +WT/HK/22795 +WT/HK/22796 +WT/HK/22797 +WT/HK/22798 +WT/HK/22799 +WT/HK/22800 +WT/HK/22801 +WT/HK/22802 +WT/HK/22803 +WT/HK/22804 +WT/HK/22806 +WT/HK/22808 +WT/HK/22809 +WT/HK/22812 +WT/HK/22817 +WT/HK/22818 +WT/HK/22819 +WT/HK/22820 +WT/HK/22822 +WT/HK/22823 +WT/HK/22824 +WT/HK/22825 +WT/HK/22826 +WT/HK/22827 +WT/HK/22828 +WT/HK/22829 +WT/HK/22830 +WT/HK/22831 +WT/HK/22832 +WT/HK/22834 +WT/HK/22835 +WT/HK/22836 +WT/HK/22837 +WT/HK/22838 +WT/HK/22839 +WT/HK/22840 +WT/HK/22841 +WT/HK/22844 +WT/HK/22845 +WT/HK/22847 +WT/HK/22848 +WT/HK/22849 +WT/HK/22850 +WT/HK/22851 +WT/HK/22852 +WT/HK/22853 +WT/HK/22854 +WT/HK/22855 +WT/HK/22856 +WT/HK/22857 +WT/HK/22858 +WT/HK/22859 +WT/HK/22862 +WT/HK/22863 +WT/HK/22864 +WT/HK/22865 +WT/HK/22866 +WT/HK/22867 +WT/HK/22868 +WT/HK/22869 +WT/HK/22870 +WT/HK/22872 +WT/HK/22873 +WT/HK/22874 +WT/HK/22875 +WT/HK/22876 +WT/HK/22878 +WT/HK/22879 +WT/HK/22881 +WT/HK/22884 +WT/HK/22886 +WT/HK/22887 +WT/HK/22888 +WT/HK/22889 +WT/HK/22892 +WT/HK/22894 +WT/HK/22895 +WT/HK/22897 +WT/HK/22898 +WT/HK/22901 +WT/HK/22903 +WT/HK/22904 +WT/HK/22905 +WT/HK/22906 +WT/HK/22907 +WT/HK/22908 +WT/HK/22909 +WT/HK/22910 +WT/HK/22911 +WT/HK/22912 +WT/HK/22913 +WT/HK/22916 +WT/HK/22917 +WT/HK/22919 +WT/HK/22920 +WT/HK/22921 +WT/HK/22922 +WT/HK/22925 +WT/HK/22926 +WT/HK/22927 +WT/HK/22928 +WT/HK/22929 +WT/HK/22930 +WT/HK/22931 +WT/HK/22932 +WT/HK/22934 +WT/HK/22935 +WT/HK/22936 +WT/HK/22937 +WT/HK/22938 +WT/HK/22939 +WT/HK/22942 +WT/HK/22944 +WT/HK/22945 +WT/HK/22946 +WT/HK/22947 +WT/HK/22948 +WT/HK/22949 +WT/HK/22950 +WT/HK/22951 +WT/HK/22955 +WT/HK/22956 +WT/HK/22957 +WT/HK/22958 +WT/HK/22960 +WT/HK/22961 +WT/HK/22963 +WT/HK/22964 +WT/HK/22965 +WT/HK/22966 +WT/HK/22968 +WT/HK/22969 +WT/HK/22970 +WT/HK/22973 +WT/HK/22974 +WT/HK/22975 +WT/HK/22976 +WT/HK/22977 +WT/HK/22978 +WT/HK/22980 +WT/HK/22981 +WT/HK/22982 +WT/HK/22983 +WT/HK/22987 +WT/HK/22988 +WT/HK/22989 +WT/HK/22990 +WT/HK/22991 +WT/HK/22992 +WT/HK/22994 +WT/HK/22995 +WT/HK/22996 +WT/HK/22997 +WT/HK/22998 +WT/HK/22999 +WT/HK/23000 +WT/HK/23001 +WT/HK/23002 +WT/HK/23004 +WT/HK/23006 +WT/HK/23007 +WT/HK/23008 +WT/HK/23009 +WT/HK/23010 +WT/HK/23011 +WT/HK/23013 +WT/HK/23014 +WT/HK/23016 +WT/HK/23019 +WT/HK/23020 +WT/HK/23021 +WT/HK/23023 +WT/HK/23024 +WT/HK/23025 +WT/HK/23026 +WT/HK/23027 +WT/HK/23031 +WT/HK/23032 +WT/HK/23033 +WT/HK/23034 +WT/HK/23035 +WT/HK/23036 +WT/HK/23037 +WT/HK/23038 +WT/HK/23039 +WT/HK/23040 +WT/HK/23041 +WT/HK/23043 +WT/HK/23044 +WT/HK/23045 +WT/HK/23046 +WT/HK/23047 +WT/HK/23048 +WT/HK/23049 +WT/HK/23050 +WT/HK/23051 +WT/HK/23052 +WT/HK/23053 +WT/HK/23054 +WT/HK/23055 +WT/HK/23056 +WT/HK/23058 +WT/HK/23059 +WT/HK/23061 +WT/HK/23062 +WT/HK/23063 +WT/HK/23065 +WT/HK/23066 +WT/HK/23067 +WT/HK/23068 +WT/HK/23069 +WT/HK/23070 +WT/HK/23071 +WT/HK/23072 +WT/HK/23073 +WT/HK/23074 +WT/HK/23075 +WT/HK/23076 +WT/HK/23078 +WT/HK/23079 +WT/HK/23080 +WT/HK/23081 +WT/HK/23082 +WT/HK/23083 +WT/HK/23084 +WT/HK/23087 +WT/HK/23088 +WT/HK/23089 +WT/HK/23090 +WT/HK/23091 +WT/HK/23092 +WT/HK/23093 +WT/HK/23095 +WT/HK/23096 +WT/HK/23098 +WT/HK/23099 +WT/HK/23100 +WT/HK/23101 +WT/HK/23102 +WT/HK/23103 +WT/HK/23104 +WT/HK/23105 +WT/HK/23107 +WT/HK/23108 +WT/HK/23109 +WT/HK/23110 +WT/HK/23111 +WT/HK/23112 +WT/HK/23114 +WT/HK/23115 +WT/HK/23116 +WT/HK/23117 +WT/HK/23121 +WT/HK/23122 +WT/HK/23123 +WT/HK/23124 +WT/HK/23125 +WT/HK/23126 +WT/HK/23127 +WT/HK/23128 +WT/HK/23129 +WT/HK/23130 +WT/HK/23131 +WT/HK/23132 +WT/HK/23133 +WT/HK/23134 +WT/HK/23135 +WT/HK/23136 +WT/HK/23138 +WT/HK/23139 +WT/HK/23140 +WT/HK/23141 +WT/HK/23142 +WT/HK/23144 +WT/HK/23145 +WT/HK/23146 +WT/HK/23148 +WT/HK/23149 +WT/HK/23150 +WT/HK/23151 +WT/HK/23152 +WT/HK/23153 +WT/HK/23154 +WT/HK/23156 +WT/HK/23157 +WT/HK/23158 +WT/HK/23159 +WT/HK/23161 +WT/HK/23162 +WT/HK/23163 +WT/HK/23164 +WT/HK/23165 +WT/HK/23167 +WT/HK/23168 +WT/HK/23170 +WT/HK/23171 +WT/HK/23172 +WT/HK/23173 +WT/HK/23174 +WT/HK/23175 +WT/HK/23176 +WT/HK/23177 +WT/HK/23178 +WT/HK/23179 +WT/HK/23180 +WT/HK/23181 +WT/HK/23182 +WT/HK/23183 +WT/HK/23184 +WT/HK/23185 +WT/HK/23186 +WT/HK/23187 +WT/HK/23188 +WT/HK/23189 +WT/HK/23190 +WT/HK/23191 +WT/HK/23192 +WT/HK/23194 +WT/HK/23195 +WT/HK/23196 +WT/HK/23197 +WT/HK/23198 +WT/HK/23199 +WT/HK/23200 +WT/HK/23201 +WT/HK/23202 +WT/HK/23203 +WT/HK/23204 +WT/HK/23205 +WT/HK/23208 +WT/HK/23209 +WT/HK/23210 +WT/HK/23211 +WT/HK/23212 +WT/HK/23214 +WT/HK/23215 +WT/HK/23216 +WT/HK/23217 +WT/HK/23218 +WT/HK/23219 +WT/HK/23220 +WT/HK/23221 +WT/HK/23222 +WT/HK/23223 +WT/HK/23224 +WT/HK/23225 +WT/HK/23226 +WT/HK/23227 +WT/HK/23228 +WT/HK/23230 +WT/HK/23231 +WT/HK/23232 +WT/HK/23233 +WT/HK/23235 +WT/HK/23236 +WT/HK/23238 +WT/HK/23239 +WT/HK/23240 +WT/HK/23241 +WT/HK/23242 +WT/HK/23243 +WT/HK/23244 +WT/HK/23245 +WT/HK/23246 +WT/HK/23247 +WT/HK/23249 +WT/HK/23250 +WT/HK/23251 +WT/HK/23252 +WT/HK/23253 +WT/HK/23254 +WT/HK/23255 +WT/HK/23256 +WT/HK/23257 +WT/HK/23259 +WT/HK/23260 +WT/HK/23262 +WT/HK/23263 +WT/HK/23264 +WT/HK/23265 +WT/HK/23266 +WT/HK/23267 +WT/HK/23268 +WT/HK/23269 +WT/HK/23270 +WT/HK/23272 +WT/HK/23273 +WT/HK/23275 +WT/HK/23276 +WT/HK/23277 +WT/HK/23278 +WT/HK/23279 +WT/HK/23281 +WT/HK/23282 +WT/HK/23285 +WT/HK/23287 +WT/HK/23288 +WT/HK/23289 +WT/HK/23290 +WT/HK/23291 +WT/HK/23292 +WT/HK/23293 +WT/HK/23294 +WT/HK/23296 +WT/HK/23297 +WT/HK/23298 +WT/HK/23299 +WT/HK/23300 +WT/HK/23302 +WT/HK/23303 +WT/HK/23305 +WT/HK/23306 +WT/HK/23307 +WT/HK/23308 +WT/HK/23309 +WT/HK/23310 +WT/HK/23311 +WT/HK/23312 +WT/HK/23313 +WT/HK/23314 +WT/HK/23315 +WT/HK/23316 +WT/HK/23317 +WT/HK/23318 +WT/HK/23319 +WT/HK/23320 +WT/HK/23321 +WT/HK/23323 +WT/HK/23324 +WT/HK/23325 +WT/HK/23326 +WT/HK/23327 +WT/HK/23328 +WT/HK/23329 +WT/HK/23330 +WT/HK/23331 +WT/HK/23332 +WT/HK/23333 +WT/HK/23334 +WT/HK/23335 +WT/HK/23336 +WT/HK/23338 +WT/HK/23339 +WT/HK/23340 +WT/HK/23341 +WT/HK/23342 +WT/HK/23343 +WT/HK/23344 +WT/HK/23345 +WT/HK/23346 +WT/HK/23347 +WT/HK/23348 +WT/HK/23349 +WT/HK/23350 +WT/HK/23351 +WT/HK/23353 +WT/HK/23354 +WT/HK/23355 +WT/HK/23356 +WT/HK/23357 +WT/HK/23358 +WT/HK/23359 +WT/HK/23360 +WT/HK/23361 +WT/HK/23362 +WT/HK/23363 +WT/HK/23365 +WT/HK/23366 +WT/HK/23367 +WT/HK/23368 +WT/HK/23371 +WT/HK/23375 +WT/HK/23376 +WT/HK/23377 +WT/HK/23383 +WT/HK/23387 +WT/HK/23389 +WT/HK/23391 +WT/HK/23395 +WT/HK/23396 +WT/HK/23397 +WT/HK/23398 +WT/HK/23400 +WT/HK/23401 +WT/HK/23402 +WT/HK/23403 +WT/HK/23404 +WT/HK/23405 +WT/HK/23406 +WT/HK/23407 +WT/HK/23411 +WT/HK/23412 +WT/HK/23413 +WT/HK/23414 +WT/HK/23415 +WT/HK/23416 +WT/HK/23418 +WT/HK/23419 +WT/HK/23420 +WT/HK/23421 +WT/HK/23422 +WT/HK/23423 +WT/HK/23424 +WT/HK/23425 +WT/HK/23426 +WT/HK/23427 +WT/HK/23428 +WT/HK/23429 +WT/HK/23430 +WT/HK/23431 +WT/HK/23432 +WT/HK/23433 +WT/HK/23434 +WT/HK/23437 +WT/HK/23438 +WT/HK/23439 +WT/HK/23441 +WT/HK/23442 +WT/HK/23443 +WT/HK/23445 +WT/HK/23446 +WT/HK/23447 +WT/HK/23448 +WT/HK/23449 +WT/HK/23450 +WT/HK/23451 +WT/HK/23452 +WT/HK/23453 +WT/HK/23454 +WT/HK/23455 +WT/HK/23457 +WT/HK/23458 +WT/HK/23459 +WT/HK/23461 +WT/HK/23463 +WT/HK/23464 +WT/HK/23465 +WT/HK/23466 +WT/HK/23467 +WT/HK/23468 +WT/HK/23469 +WT/HK/23470 +WT/HK/23471 +WT/HK/23472 +WT/HK/23473 +WT/HK/23474 +WT/HK/23475 +WT/HK/23476 +WT/HK/23478 +WT/HK/23479 +WT/HK/23480 +WT/HK/23482 +WT/HK/23483 +WT/HK/23484 +WT/HK/23487 +WT/HK/23488 +WT/HK/23489 +WT/HK/23490 +WT/HK/23491 +WT/HK/23492 +WT/HK/23493 +WT/HK/23494 +WT/HK/23496 +WT/HK/23497 +WT/HK/23498 +WT/HK/23499 +WT/HK/23500 +WT/HK/23501 +WT/HK/23504 +WT/HK/23505 +WT/HK/23507 +WT/HK/23508 +WT/HK/23509 +WT/HK/23510 +WT/HK/23513 +WT/HK/23515 +WT/HK/23516 +WT/HK/23517 +WT/HK/23518 +WT/HK/23519 +WT/HK/23520 +WT/HK/23521 +WT/HK/23522 +WT/HK/23523 +WT/HK/23524 +WT/HK/23525 +WT/HK/23526 +WT/HK/23527 +WT/HK/23530 +WT/HK/23531 +WT/HK/23532 +WT/HK/23533 +WT/HK/23534 +WT/HK/23535 +WT/HK/23536 +WT/HK/23537 +WT/HK/23539 +WT/HK/23540 +WT/HK/23541 +WT/HK/23542 +WT/HK/23543 +WT/HK/23544 +WT/HK/23545 +WT/HK/23546 +WT/HK/23547 +WT/HK/23548 +WT/HK/23549 +WT/HK/23550 +WT/HK/23551 +WT/HK/23553 +WT/HK/23554 +WT/HK/23555 +WT/HK/23556 +WT/HK/23557 +WT/HK/23558 +WT/HK/23559 +WT/HK/23560 +WT/HK/23561 +WT/HK/23562 +WT/HK/23563 +WT/HK/23564 +WT/HK/23565 +WT/HK/23566 +WT/HK/23567 +WT/HK/23568 +WT/HK/23569 +WT/HK/23570 +WT/HK/23571 +WT/HK/23572 +WT/HK/23573 +WT/HK/23574 +WT/HK/23575 +WT/HK/23577 +WT/HK/23579 +WT/HK/23580 +WT/HK/23581 +WT/HK/23582 +WT/HK/23583 +WT/HK/23584 +WT/HK/23585 +WT/HK/23586 +WT/HK/23587 +WT/HK/23588 +WT/HK/23589 +WT/HK/23590 +WT/HK/23591 +WT/HK/23592 +WT/HK/23593 +WT/HK/23594 +WT/HK/23596 +WT/HK/23598 +WT/HK/23599 +WT/HK/23600 +WT/HK/23602 +WT/HK/23603 +WT/HK/23604 +WT/HK/23605 +WT/HK/23606 +WT/HK/23607 +WT/HK/23609 +WT/HK/23610 +WT/HK/23611 +WT/HK/23612 +WT/HK/23613 +WT/HK/23614 +WT/HK/23615 +WT/HK/23617 +WT/HK/23618 +WT/HK/23619 +WT/HK/23620 +WT/HK/23621 +WT/HK/23622 +WT/HK/23624 +WT/HK/23625 +WT/HK/23627 +WT/HK/23628 +WT/HK/23629 +WT/HK/23630 +WT/HK/23631 +WT/HK/23633 +WT/HK/23634 +WT/HK/23635 +WT/HK/23637 +WT/HK/23638 +WT/HK/23640 +WT/HK/23641 +WT/HK/23643 +WT/HK/23644 +WT/HK/23646 +WT/HK/23647 +WT/HK/23649 +WT/HK/23650 +WT/HK/23651 +WT/HK/23652 +WT/HK/23654 +WT/HK/23655 +WT/HK/23656 +WT/HK/23657 +WT/HK/23658 +WT/HK/23659 +WT/HK/23660 +WT/HK/23662 +WT/HK/23663 +WT/HK/23665 +WT/HK/23667 +WT/HK/23668 +WT/HK/23669 +WT/HK/23670 +WT/HK/23671 +WT/HK/23672 +WT/HK/23673 +WT/HK/23675 +WT/HK/23676 +WT/HK/23677 +WT/HK/23678 +WT/HK/23679 +WT/HK/23683 +WT/HK/23685 +WT/HK/23686 +WT/HK/23687 +WT/HK/23688 +WT/HK/23689 +WT/HK/23690 +WT/HK/23691 +WT/HK/23692 +WT/HK/23693 +WT/HK/23694 +WT/HK/23695 +WT/HK/23696 +WT/HK/23698 +WT/HK/23699 +WT/HK/23700 +WT/HK/23701 +WT/HK/23702 +WT/HK/23703 +WT/HK/23704 +WT/HK/23705 +WT/HK/23706 +WT/HK/23707 +WT/HK/23708 +WT/HK/23709 +WT/HK/23710 +WT/HK/23711 +WT/HK/23714 +WT/HK/23715 +WT/HK/23716 +WT/HK/23717 +WT/HK/23718 +WT/HK/23719 +WT/HK/23720 +WT/HK/23721 +WT/HK/23723 +WT/HK/23724 +WT/HK/23725 +WT/HK/23726 +WT/HK/23727 +WT/HK/23728 +WT/HK/23729 +WT/HK/23731 +WT/HK/23732 +WT/HK/23733 +WT/HK/23734 +WT/HK/23735 +WT/HK/23738 +WT/HK/23739 +WT/HK/23741 +WT/HK/23743 +WT/HK/23744 +WT/HK/23745 +WT/HK/23746 +WT/HK/23748 +WT/HK/23749 +WT/HK/23751 +WT/HK/23752 +WT/HK/23753 +WT/HK/23754 +WT/HK/23756 +WT/HK/23759 +WT/HK/23760 +WT/HK/23761 +WT/HK/23762 +WT/HK/23763 +WT/HK/23764 +WT/HK/23765 +WT/HK/23766 +WT/HK/23767 +WT/HK/23769 +WT/HK/23770 +WT/HK/23771 +WT/HK/23772 +WT/HK/23774 +WT/HK/23775 +WT/HK/23776 +WT/HK/23777 +WT/HK/23778 +WT/HK/23779 +WT/HK/23780 +WT/HK/23781 +WT/HK/23782 +WT/HK/23783 +WT/HK/23785 +WT/HK/23786 +WT/HK/23787 +WT/HK/23788 +WT/HK/23789 +WT/HK/23790 +WT/HK/23791 +WT/HK/23792 +WT/HK/23793 +WT/HK/23794 +WT/HK/23795 +WT/HK/23797 +WT/HK/23798 +WT/HK/23799 +WT/HK/23801 +WT/HK/23802 +WT/HK/23803 +WT/HK/23804 +WT/HK/23805 +WT/HK/23806 +WT/HK/23807 +WT/HK/23808 +WT/HK/23809 +WT/HK/23810 +WT/HK/23811 +WT/HK/23812 +WT/HK/23814 +WT/HK/23815 +WT/HK/23816 +WT/HK/23817 +WT/HK/23818 +WT/HK/23819 +WT/HK/23820 +WT/HK/23821 +WT/HK/23822 +WT/HK/23823 +WT/HK/23824 +WT/HK/23825 +WT/HK/23826 +WT/HK/23827 +WT/HK/23828 +WT/HK/23829 +WT/HK/23830 +WT/HK/23831 +WT/HK/23832 +WT/HK/23834 +WT/HK/23835 +WT/HK/23836 +WT/HK/23837 +WT/HK/23838 +WT/HK/23839 +WT/HK/23840 +WT/HK/23841 +WT/HK/23842 +WT/HK/23843 +WT/HK/23844 +WT/HK/23848 +WT/HK/23850 +WT/HK/23851 +WT/HK/23852 +WT/HK/23854 +WT/HK/23855 +WT/HK/23857 +WT/HK/23858 +WT/HK/23859 +WT/HK/23861 +WT/HK/23862 +WT/HK/23864 +WT/HK/23865 +WT/HK/23866 +WT/HK/23867 +WT/HK/23868 +WT/HK/23869 +WT/HK/23870 +WT/HK/23871 +WT/HK/23872 +WT/HK/23873 +WT/HK/23874 +WT/HK/23875 +WT/HK/23876 +WT/HK/23878 +WT/HK/23879 +WT/HK/23880 +WT/HK/23881 +WT/HK/23882 +WT/HK/23883 +WT/HK/23884 +WT/HK/23885 +WT/HK/23886 +WT/HK/23887 +WT/HK/23888 +WT/HK/23889 +WT/HK/23890 +WT/HK/23891 +WT/HK/23892 +WT/HK/23894 +WT/HK/23895 +WT/HK/23896 +WT/HK/23897 +WT/HK/23898 +WT/HK/23899 +WT/HK/23900 +WT/HK/23901 +WT/HK/23902 +WT/HK/23903 +WT/HK/23904 +WT/HK/23905 +WT/HK/23906 +WT/HK/23907 +WT/HK/23908 +WT/HK/23909 +WT/HK/23911 +WT/HK/23912 +WT/HK/23913 +WT/HK/23914 +WT/HK/23915 +WT/HK/23916 +WT/HK/23919 +WT/HK/23920 +WT/HK/23923 +WT/HK/23924 +WT/HK/23925 +WT/HK/23926 +WT/HK/23927 +WT/HK/23928 +WT/HK/23929 +WT/HK/23930 +WT/HK/23931 +WT/HK/23932 +WT/HK/23933 +WT/HK/23934 +WT/HK/23935 +WT/HK/23936 +WT/HK/23937 +WT/HK/23938 +WT/HK/23939 +WT/HK/23940 +WT/HK/23943 +WT/HK/23944 +WT/HK/23945 +WT/HK/23946 +WT/HK/23947 +WT/HK/23948 +WT/HK/23949 +WT/HK/23950 +WT/HK/23951 +WT/HK/23952 +WT/HK/23954 +WT/HK/23955 +WT/HK/23956 +WT/HK/23957 +WT/HK/23958 +WT/HK/23959 +WT/HK/23960 +WT/HK/23961 +WT/HK/23962 +WT/HK/23964 +WT/HK/23965 +WT/HK/23966 +WT/HK/23967 +WT/HK/23968 +WT/HK/23969 +WT/HK/23970 +WT/HK/23971 +WT/HK/23972 +WT/HK/23973 +WT/HK/23974 +WT/HK/23975 +WT/HK/23976 +WT/HK/23977 +WT/HK/23978 +WT/HK/23979 +WT/HK/23981 +WT/HK/23982 +WT/HK/23983 +WT/HK/23984 +WT/HK/23985 +WT/HK/23986 +WT/HK/23987 +WT/HK/23988 +WT/HK/23989 +WT/HK/23990 +WT/HK/23991 +WT/HK/23992 +WT/HK/23993 +WT/HK/23994 +WT/HK/23995 +WT/HK/23997 +WT/HK/23998 +WT/HK/23999 +WT/HK/24000 +WT/HK/24001 +WT/HK/24003 +WT/HK/24004 +WT/HK/24005 +WT/HK/24007 +WT/HK/24008 +WT/HK/24009 +WT/HK/24010 +WT/HK/24011 +WT/HK/24012 +WT/HK/24013 +WT/HK/24014 +WT/HK/24015 +WT/HK/24016 +WT/HK/24017 +WT/HK/24018 +WT/HK/24019 +WT/HK/24020 +WT/HK/24021 +WT/HK/24022 +WT/HK/24023 +WT/HK/24024 +WT/HK/24025 +WT/HK/24026 +WT/HK/24027 +WT/HK/24029 +WT/HK/24030 +WT/HK/24031 +WT/HK/24033 +WT/HK/24034 +WT/HK/24035 +WT/HK/24036 +WT/HK/24040 +WT/HK/24041 +WT/HK/24042 +WT/HK/24043 +WT/HK/24044 +WT/HK/24045 +WT/HK/24046 +WT/HK/24047 +WT/HK/24048 +WT/HK/24050 +WT/HK/24051 +WT/HK/24052 +WT/HK/24054 +WT/HK/24056 +WT/HK/24058 +WT/HK/24059 +WT/HK/24060 +WT/HK/24061 +WT/HK/24062 +WT/HK/24063 +WT/HK/24064 +WT/HK/24065 +WT/HK/24066 +WT/HK/24067 +WT/HK/24068 +WT/HK/24069 +WT/HK/24070 +WT/HK/24073 +WT/HK/24074 +WT/HK/24075 +WT/HK/24077 +WT/HK/24078 +WT/HK/24079 +WT/HK/24080 +WT/HK/24081 +WT/HK/24083 +WT/HK/24084 +WT/HK/24085 +WT/HK/24086 +WT/HK/24089 +WT/HK/24090 +WT/HK/24091 +WT/HK/24093 +WT/HK/24094 +WT/HK/24097 +WT/HK/24098 +WT/HK/24099 +WT/HK/24100 +WT/HK/24101 +WT/HK/24102 +WT/HK/24103 +WT/HK/24104 +WT/HK/24105 +WT/HK/24106 +WT/HK/24107 +WT/HK/24108 +WT/HK/24109 +WT/HK/24110 +WT/HK/24111 +WT/HK/24112 +WT/HK/24113 +WT/HK/24114 +WT/HK/24116 +WT/HK/24117 +WT/HK/24118 +WT/HK/24119 +WT/HK/24120 +WT/HK/24121 +WT/HK/24122 +WT/HK/24124 +WT/HK/24125 +WT/HK/24126 +WT/HK/24127 +WT/HK/24128 +WT/HK/24129 +WT/HK/24130 +WT/HK/24131 +WT/HK/24132 +WT/HK/24133 +WT/HK/24134 +WT/HK/24135 +WT/HK/24136 +WT/HK/24137 +WT/HK/24138 +WT/HK/24139 +WT/HK/24140 +WT/HK/24141 +WT/HK/24142 +WT/HK/24143 +WT/HK/24144 +WT/HK/24146 +WT/HK/24147 +WT/HK/24148 +WT/HK/24149 +WT/HK/24150 +WT/HK/24152 +WT/HK/24153 +WT/HK/24155 +WT/HK/24156 +WT/HK/24157 +WT/HK/24158 +WT/HK/24159 +WT/HK/24160 +WT/HK/24162 +WT/HK/24163 +WT/HK/24164 +WT/HK/24165 +WT/HK/24166 +WT/HK/24167 +WT/HK/24168 +WT/HK/24169 +WT/HK/24170 +WT/HK/24171 +WT/HK/24173 +WT/HK/24174 +WT/HK/24175 +WT/HK/24176 +WT/HK/24177 +WT/HK/24178 +WT/HK/24179 +WT/HK/24181 +WT/HK/24182 +WT/HK/24183 +WT/HK/24184 +WT/HK/24185 +WT/HK/24186 +WT/HK/24187 +WT/HK/24188 +WT/HK/24189 +WT/HK/24190 +WT/HK/24191 +WT/HK/24192 +WT/HK/24194 +WT/HK/24195 +WT/HK/24196 +WT/HK/24197 +WT/HK/24198 +WT/HK/24199 +WT/HK/24200 +WT/HK/24202 +WT/HK/24203 +WT/HK/24204 +WT/HK/24205 +WT/HK/24206 +WT/HK/24207 +WT/HK/24208 +WT/HK/24209 +WT/HK/24210 +WT/HK/24211 +WT/HK/24212 +WT/HK/24213 +WT/HK/24214 +WT/HK/24215 +WT/HK/24216 +WT/HK/24217 +WT/HK/24218 +WT/HK/24219 +WT/HK/24220 +WT/HK/24221 +WT/HK/24222 +WT/HK/24223 +WT/HK/24224 +WT/HK/24225 +WT/HK/24226 +WT/HK/24228 +WT/HK/24230 +WT/HK/24231 +WT/HK/24232 +WT/HK/24234 +WT/HK/24236 +WT/HK/24238 +WT/HK/24239 +WT/HK/24241 +WT/HK/24242 +WT/HK/24243 +WT/HK/24244 +WT/HK/24245 +WT/HK/24246 +WT/HK/24248 +WT/HK/24249 +WT/HK/24250 +WT/HK/24251 +WT/HK/24252 +WT/HK/24253 +WT/HK/24254 +WT/HK/24255 +WT/HK/24256 +WT/HK/24257 +WT/HK/24258 +WT/HK/24259 +WT/HK/24260 +WT/HK/24261 +WT/HK/24262 +WT/HK/24263 +WT/HK/24264 +WT/HK/24265 +WT/HK/24266 +WT/HK/24268 +WT/HK/24269 +WT/HK/24270 +WT/HK/24271 +WT/HK/24272 +WT/HK/24273 +WT/HK/24274 +WT/HK/24276 +WT/HK/24277 +WT/HK/24278 +WT/HK/24280 +WT/HK/24281 +WT/HK/24282 +WT/HK/24283 +WT/HK/24284 +WT/HK/24285 +WT/HK/24286 +WT/HK/24287 +WT/HK/24288 +WT/HK/24289 +WT/HK/24290 +WT/HK/24291 +WT/HK/24292 +WT/HK/24293 +WT/HK/24294 +WT/HK/24295 +WT/HK/24296 +WT/HK/24298 +WT/HK/24299 +WT/HK/24301 +WT/HK/24302 +WT/HK/24303 +WT/HK/24304 +WT/HK/24305 +WT/HK/24306 +WT/HK/24307 +WT/HK/24308 +WT/HK/24309 +WT/HK/24310 +WT/HK/24311 +WT/HK/24312 +WT/HK/24313 +WT/HK/24314 +WT/HK/24315 +WT/HK/24316 +WT/HK/24317 +WT/HK/24318 +WT/HK/24319 +WT/HK/24320 +WT/HK/24321 +WT/HK/24322 +WT/HK/24323 +WT/HK/24324 +WT/HK/24325 +WT/HK/24326 +WT/HK/24327 +WT/HK/24328 +WT/HK/24329 +WT/HK/24330 +WT/HK/24331 +WT/HK/24332 +WT/HK/24333 +WT/HK/24334 +WT/HK/24335 +WT/HK/24336 +WT/HK/24338 +WT/HK/24339 +WT/HK/24340 +WT/HK/24341 +WT/HK/24342 +WT/HK/24343 +WT/HK/24344 +WT/HK/24346 +WT/HK/24347 +WT/HK/24348 +WT/HK/24349 +WT/HK/24350 +WT/HK/24351 +WT/HK/24352 +WT/HK/24353 +WT/HK/24354 +WT/HK/24355 +WT/HK/24356 +WT/HK/24359 +WT/HK/24360 +WT/HK/24361 +WT/HK/24362 +WT/HK/24364 +WT/HK/24366 +WT/HK/24367 +WT/HK/24368 +WT/HK/24370 +WT/HK/24371 +WT/HK/24372 +WT/HK/24373 +WT/HK/24374 +WT/HK/24375 +WT/HK/24376 +WT/HK/24377 +WT/HK/24378 +WT/HK/24379 +WT/HK/24380 +WT/HK/24381 +WT/HK/24382 +WT/HK/24383 +WT/HK/24384 +WT/HK/24385 +WT/HK/24386 +WT/HK/24387 +WT/HK/24388 +WT/HK/24389 +WT/HK/24390 +WT/HK/24391 +WT/HK/24392 +WT/HK/24393 +WT/HK/24394 +WT/HK/24395 +WT/HK/24396 +WT/HK/24397 +WT/HK/24398 +WT/HK/24399 +WT/HK/24400 +WT/HK/24401 +WT/HK/24402 +WT/HK/24403 +WT/HK/24405 +WT/HK/24406 +WT/HK/24408 +WT/HK/24409 +WT/HK/24410 +WT/HK/24411 +WT/HK/24412 +WT/HK/24413 +WT/HK/24414 +WT/HK/24415 +WT/HK/24416 +WT/HK/24417 +WT/HK/24418 +WT/HK/24420 +WT/HK/24421 +WT/HK/24422 +WT/HK/24423 +WT/HK/24424 +WT/HK/24425 +WT/HK/24426 +WT/HK/24427 +WT/HK/24428 +WT/HK/24429 +WT/HK/24430 +WT/HK/24431 +WT/HK/24432 +WT/HK/24433 +WT/HK/24435 +WT/HK/24436 +WT/HK/24437 +WT/HK/24441 +WT/HK/24443 +WT/HK/24444 +WT/HK/24445 +WT/HK/24446 +WT/HK/24447 +WT/HK/24448 +WT/HK/24449 +WT/HK/24450 +WT/HK/24451 +WT/HK/24453 +WT/HK/24454 +WT/HK/24455 +WT/HK/24456 +WT/HK/24457 +WT/HK/24458 +WT/HK/24460 +WT/HK/24461 +WT/HK/24462 +WT/HK/24463 +WT/HK/24464 +WT/HK/24466 +WT/HK/24467 +WT/HK/24468 +WT/HK/24469 +WT/HK/24470 +WT/HK/24471 +WT/HK/24472 +WT/HK/24473 +WT/HK/24474 +WT/HK/24475 +WT/HK/24477 +WT/HK/24478 +WT/HK/24479 +WT/HK/24480 +WT/HK/24481 +WT/HK/24482 +WT/HK/24483 +WT/HK/24484 +WT/HK/24485 +WT/HK/24486 +WT/HK/24487 +WT/HK/24488 +WT/HK/24489 +WT/HK/24490 +WT/HK/24491 +WT/HK/24492 +WT/HK/24495 +WT/HK/24497 +WT/HK/24499 +WT/HK/24501 +WT/HK/24502 +WT/HK/24503 +WT/HK/24505 +WT/HK/24507 +WT/HK/24508 +WT/HK/24509 +WT/HK/24510 +WT/HK/24511 +WT/HK/24512 +WT/HK/24514 +WT/HK/24515 +WT/HK/24516 +WT/HK/24517 +WT/HK/24518 +WT/HK/24519 +WT/HK/24520 +WT/HK/24522 +WT/HK/24524 +WT/HK/24525 +WT/HK/24526 +WT/HK/24527 +WT/HK/24528 +WT/HK/24529 +WT/HK/24531 +WT/HK/24533 +WT/HK/24534 +WT/HK/24535 +WT/HK/24536 +WT/HK/24537 +WT/HK/24538 +WT/HK/24539 +WT/HK/24540 +WT/HK/24541 +WT/HK/24542 +WT/HK/24543 +WT/HK/24544 +WT/HK/24545 +WT/HK/24546 +WT/HK/24547 +WT/HK/24548 +WT/HK/24549 +WT/HK/24550 +WT/HK/24551 +WT/HK/24552 +WT/HK/24553 +WT/HK/24554 +WT/HK/24555 +WT/HK/24556 +WT/HK/24557 +WT/HK/24558 +WT/HK/24559 +WT/HK/24560 +WT/HK/24561 +WT/HK/24562 +WT/HK/24563 +WT/HK/24565 +WT/HK/24566 +WT/HK/24567 +WT/HK/24568 +WT/HK/24569 +WT/HK/24570 +WT/HK/24571 +WT/HK/24572 +WT/HK/24573 +WT/HK/24574 +WT/HK/24575 +WT/HK/24576 +WT/HK/24577 +WT/HK/24578 +WT/HK/24579 +WT/HK/24580 +WT/HK/24581 +WT/HK/24582 +WT/HK/24583 +WT/HK/24584 +WT/HK/24585 +WT/HK/24586 +WT/HK/24587 +WT/HK/24588 +WT/HK/24589 +WT/HK/24590 +WT/HK/24591 +WT/HK/24592 +WT/HK/24593 +WT/HK/24594 +WT/HK/24595 +WT/HK/24597 +WT/HK/24598 +WT/HK/24599 +WT/HK/24600 +WT/HK/24602 +WT/HK/24603 +WT/HK/24604 +WT/HK/24605 +WT/HK/24606 +WT/HK/24608 +WT/HK/24609 +WT/HK/24610 +WT/HK/24611 +WT/HK/24613 +WT/HK/24614 +WT/HK/24615 +WT/HK/24616 +WT/HK/24617 +WT/HK/24618 +WT/HK/24619 +WT/HK/24622 +WT/HK/24623 +WT/HK/24624 +WT/HK/24625 +WT/HK/24626 +WT/HK/24627 +WT/HK/24628 +WT/HK/24631 +WT/HK/24632 +WT/HK/24633 +WT/HK/24634 +WT/HK/24635 +WT/HK/24636 +WT/HK/24638 +WT/HK/24639 +WT/HK/24640 +WT/HK/24641 +WT/HK/24642 +WT/HK/24643 +WT/HK/24644 +WT/HK/24645 +WT/HK/24646 +WT/HK/24647 +WT/HK/24648 +WT/HK/24649 +WT/HK/24650 +WT/HK/24651 +WT/HK/24652 +WT/HK/24653 +WT/HK/24654 +WT/HK/24655 +WT/HK/24656 +WT/HK/24657 +WT/HK/24658 +WT/HK/24659 +WT/HK/24660 +WT/HK/24662 +WT/HK/24663 +WT/HK/24664 +WT/HK/24666 +WT/HK/24667 +WT/HK/24668 +WT/HK/24669 +WT/HK/24671 +WT/HK/24672 +WT/HK/24673 +WT/HK/24675 +WT/HK/24676 +WT/HK/24677 +WT/HK/24679 +WT/HK/24681 +WT/HK/24682 +WT/HK/24684 +WT/HK/24685 +WT/HK/24686 +WT/HK/24687 +WT/HK/24688 +WT/HK/24689 +WT/HK/24690 +WT/HK/24691 +WT/HK/24692 +WT/HK/24693 +WT/HK/24694 +WT/HK/24695 +WT/HK/24696 +WT/HK/24698 +WT/HK/24699 +WT/HK/24700 +WT/HK/24701 +WT/HK/24702 +WT/HK/24703 +WT/HK/24704 +WT/HK/24706 +WT/HK/24707 +WT/HK/24708 +WT/HK/24709 +WT/HK/24710 +WT/HK/24711 +WT/HK/24713 +WT/HK/24714 +WT/HK/24715 +WT/HK/24716 +WT/HK/24717 +WT/HK/24718 +WT/HK/24720 +WT/HK/24721 +WT/HK/24722 +WT/HK/24723 +WT/HK/24724 +WT/HK/24725 +WT/HK/24727 +WT/HK/24728 +WT/HK/24729 +WT/HK/24730 +WT/HK/24731 +WT/HK/24732 +WT/HK/24733 +WT/HK/24735 +WT/HK/24736 +WT/HK/24737 +WT/HK/24739 +WT/HK/24740 +WT/HK/24741 +WT/HK/24742 +WT/HK/24744 +WT/HK/24745 +WT/HK/24746 +WT/HK/24747 +WT/HK/24748 +WT/HK/24749 +WT/HK/24750 +WT/HK/24751 +WT/HK/24752 +WT/HK/24753 +WT/HK/24754 +WT/HK/24755 +WT/HK/24756 +WT/HK/24757 +WT/HK/24758 +WT/HK/24759 +WT/HK/24760 +WT/HK/24761 +WT/HK/24762 +WT/HK/24763 +WT/HK/24764 +WT/HK/24765 +WT/HK/24766 +WT/HK/24767 +WT/HK/24769 +WT/HK/24770 +WT/HK/24771 +WT/HK/24773 +WT/HK/24774 +WT/HK/24775 +WT/HK/24776 +WT/HK/24777 +WT/HK/24778 +WT/HK/24780 +WT/HK/24781 +WT/HK/24782 +WT/HK/24783 +WT/HK/24786 +WT/HK/24788 +WT/HK/24789 +WT/HK/24790 +WT/HK/24791 +WT/HK/24792 +WT/HK/24793 +WT/HK/24794 +WT/HK/24795 +WT/HK/24796 +WT/HK/24797 +WT/HK/24798 +WT/HK/24799 +WT/HK/24800 +WT/HK/24801 +WT/HK/24802 +WT/HK/24804 +WT/HK/24805 +WT/HK/24806 +WT/HK/24807 +WT/HK/24808 +WT/HK/24809 +WT/HK/24811 +WT/HK/24813 +WT/HK/24814 +WT/HK/24815 +WT/HK/24816 +WT/HK/24817 +WT/HK/24819 +WT/HK/24820 +WT/HK/24821 +WT/HK/24822 +WT/HK/24823 +WT/HK/24824 +WT/HK/24825 +WT/HK/24829 +WT/HK/24831 +WT/HK/24832 +WT/HK/24833 +WT/HK/24834 +WT/HK/24835 +WT/HK/24836 +WT/HK/24838 +WT/HK/24839 +WT/HK/24840 +WT/HK/24841 +WT/HK/24844 +WT/HK/24845 +WT/HK/24846 +WT/HK/24847 +WT/HK/24849 +WT/HK/24850 +WT/HK/24851 +WT/HK/24852 +WT/HK/24853 +WT/HK/24854 +WT/HK/24855 +WT/HK/24856 +WT/HK/24857 +WT/HK/24858 +WT/HK/24859 +WT/HK/24860 +WT/HK/24861 +WT/HK/24862 +WT/HK/24863 +WT/HK/24864 +WT/HK/24865 +WT/HK/24866 +WT/HK/24867 +WT/HK/24868 +WT/HK/24869 +WT/HK/24871 +WT/HK/24874 +WT/HK/24875 +WT/HK/24876 +WT/HK/24878 +WT/HK/24879 +WT/HK/24880 +WT/HK/24881 +WT/HK/24882 +WT/HK/24883 +WT/HK/24884 +WT/HK/24885 +WT/HK/24886 +WT/HK/24887 +WT/HK/24888 +WT/HK/24889 +WT/HK/24890 +WT/HK/24891 +WT/HK/24892 +WT/HK/24894 +WT/HK/24895 +WT/HK/24896 +WT/HK/24897 +WT/HK/24898 +WT/HK/24899 +WT/HK/24904 +WT/HK/24905 +WT/HK/24906 +WT/HK/24908 +WT/HK/24909 +WT/HK/24910 +WT/HK/24911 +WT/HK/24915 +WT/HK/24916 +WT/HK/24917 +WT/HK/24918 +WT/HK/24919 +WT/HK/24920 +WT/HK/24921 +WT/HK/24922 +WT/HK/24923 +WT/HK/24925 +WT/HK/24926 +WT/HK/24927 +WT/HK/24928 +WT/HK/24929 +WT/HK/24930 +WT/HK/24931 +WT/HK/24932 +WT/HK/24933 +WT/HK/24934 +WT/HK/24935 +WT/HK/24936 +WT/HK/24937 +WT/HK/24938 +WT/HK/24939 +WT/HK/24940 +WT/HK/24941 +WT/HK/24942 +WT/HK/24943 +WT/HK/24944 +WT/HK/24945 +WT/HK/24946 +WT/HK/24948 +WT/HK/24949 +WT/HK/24950 +WT/HK/24951 +WT/HK/24952 +WT/HK/24953 +WT/HK/24954 +WT/HK/24955 +WT/HK/24956 +WT/HK/24957 +WT/HK/24958 +WT/HK/24959 +WT/HK/24960 +WT/HK/24961 +WT/HK/24962 +WT/HK/24963 +WT/HK/24964 +WT/HK/24965 +WT/HK/24966 +WT/HK/24967 +WT/HK/24968 +WT/HK/24969 +WT/HK/24970 +WT/HK/24971 +WT/HK/24972 +WT/HK/24973 +WT/HK/24974 +WT/HK/24975 +WT/HK/24976 +WT/HK/24977 +WT/HK/24978 +WT/HK/24979 +WT/HK/24980 +WT/HK/24981 +WT/HK/24982 +WT/HK/24983 +WT/HK/24984 +WT/HK/24985 +WT/HK/24986 +WT/HK/24987 +WT/HK/24988 +WT/HK/24989 +WT/HK/24990 +WT/HK/24991 +WT/HK/24992 +WT/HK/24993 +WT/HK/24994 +WT/HK/24996 +WT/HK/24997 +WT/HK/24998 +WT/HK/24999 +WT/HK/25000 +WT/HK/25002 +WT/HK/25003 +WT/HK/25004 +WT/HK/25005 +WT/HK/25006 +WT/HK/25007 +WT/HK/25008 +WT/HK/25009 +WT/HK/25010 +WT/HK/25011 +WT/HK/25012 +WT/HK/25013 +WT/HK/25014 +WT/HK/25015 +WT/HK/25016 +WT/HK/25017 +WT/HK/25019 +WT/HK/25020 +WT/HK/25021 +WT/HK/25022 +WT/HK/25023 +WT/HK/25024 +WT/HK/25026 +WT/HK/25027 +WT/HK/25028 +WT/HK/25029 +WT/HK/25030 +WT/HK/25031 +WT/HK/25032 +WT/HK/25033 +WT/HK/25035 +WT/HK/25036 +WT/HK/25037 +WT/HK/25038 +WT/HK/25039 +WT/HK/25040 +WT/HK/25041 +WT/HK/25042 +WT/HK/25043 +WT/HK/25044 +WT/HK/25045 +WT/HK/25046 +WT/HK/25047 +WT/HK/25048 +WT/HK/25049 +WT/HK/25050 +WT/HK/25051 +WT/HK/25053 +WT/HK/25054 +WT/HK/25055 +WT/HK/25056 +WT/HK/25057 +WT/HK/25058 +WT/HK/25059 +WT/HK/25060 +WT/HK/25061 +WT/HK/25063 +WT/HK/25065 +WT/HK/25066 +WT/HK/25067 +WT/HK/25068 +WT/HK/25069 +WT/HK/25071 +WT/HK/25072 +WT/HK/25073 +WT/HK/25074 +WT/HK/25075 +WT/HK/25077 +WT/HK/25078 +WT/HK/25079 +WT/HK/25081 +WT/HK/25082 +WT/HK/25084 +WT/HK/25085 +WT/HK/25086 +WT/HK/25087 +WT/HK/25088 +WT/HK/25089 +WT/HK/25090 +WT/HK/25091 +WT/HK/25092 +WT/HK/25093 +WT/HK/25094 +WT/HK/25095 +WT/HK/25096 +WT/HK/25097 +WT/HK/25098 +WT/HK/25099 +WT/HK/25100 +WT/HK/25101 +WT/HK/25102 +WT/HK/25103 +WT/HK/25104 +WT/HK/25105 +WT/HK/25106 +WT/HK/25107 +WT/HK/25108 +WT/HK/25109 +WT/HK/25110 +WT/HK/25111 +WT/HK/25112 +WT/HK/25113 +WT/HK/25114 +WT/HK/25116 +WT/HK/25117 +WT/HK/25118 +WT/HK/25119 +WT/HK/25120 +WT/HK/25121 +WT/HK/25123 +WT/HK/25125 +WT/HK/25126 +WT/HK/25127 +WT/HK/25129 +WT/HK/25130 +WT/HK/25131 +WT/HK/25132 +WT/HK/25133 +WT/HK/25134 +WT/HK/25135 +WT/HK/25136 +WT/HK/25137 +WT/HK/25138 +WT/HK/25139 +WT/HK/25140 +WT/HK/25141 +WT/HK/25143 +WT/HK/25144 +WT/HK/25146 +WT/HK/25147 +WT/HK/25148 +WT/HK/25149 +WT/HK/25150 +WT/HK/25151 +WT/HK/25152 +WT/HK/25155 +WT/HK/25156 +WT/HK/25158 +WT/HK/25159 +WT/HK/25160 +WT/HK/25161 +WT/HK/25162 +WT/HK/25163 +WT/HK/25165 +WT/HK/25166 +WT/HK/25167 +WT/HK/25168 +WT/HK/25169 +WT/HK/25170 +WT/HK/25171 +WT/HK/25172 +WT/HK/25173 +WT/HK/25174 +WT/HK/25175 +WT/HK/25176 +WT/HK/25177 +WT/HK/25178 +WT/HK/25179 +WT/HK/25180 +WT/HK/25181 +WT/HK/25182 +WT/HK/25183 +WT/HK/25184 +WT/HK/25185 +WT/HK/25186 +WT/HK/25187 +WT/HK/25188 +WT/HK/25189 +WT/HK/25190 +WT/HK/25191 +WT/HK/25192 +WT/HK/25193 +WT/HK/25194 +WT/HK/25197 +WT/HK/25198 +WT/HK/25200 +WT/HK/25201 +WT/HK/25202 +WT/HK/25203 +WT/HK/25204 +WT/HK/25205 +WT/HK/25206 +WT/HK/25207 +WT/HK/25208 +WT/HK/25209 +WT/HK/25210 +WT/HK/25211 +WT/HK/25212 +WT/HK/25213 +WT/HK/25214 +WT/HK/25215 +WT/HK/25216 +WT/HK/25217 +WT/HK/25218 +WT/HK/25219 +WT/HK/25220 +WT/HK/25221 +WT/HK/25223 +WT/HK/25224 +WT/HK/25225 +WT/HK/25226 +WT/HK/25228 +WT/HK/25229 +WT/HK/25230 +WT/HK/25231 +WT/HK/25232 +WT/HK/25233 +WT/HK/25234 +WT/HK/25235 +WT/HK/25236 +WT/HK/25237 +WT/HK/25238 +WT/HK/25239 +WT/HK/25240 +WT/HK/25241 +WT/HK/25242 +WT/HK/25243 +WT/HK/25244 +WT/HK/25245 +WT/HK/25247 +WT/HK/25248 +WT/HK/25250 +WT/HK/25251 +WT/HK/25252 +WT/HK/25253 +WT/HK/25254 +WT/HK/25255 +WT/HK/25256 +WT/HK/25257 +WT/HK/25258 +WT/HK/25259 +WT/HK/25260 +WT/HK/25261 +WT/HK/25262 +WT/HK/25263 +WT/HK/25264 +WT/HK/25265 +WT/HK/25266 +WT/HK/25267 +WT/HK/25268 +WT/HK/25269 +WT/HK/25270 +WT/HK/25271 +WT/HK/25272 +WT/HK/25273 +WT/HK/25274 +WT/HK/25275 +WT/HK/25276 +WT/HK/25277 +WT/HK/25278 +WT/HK/25279 +WT/HK/25280 +WT/HK/25281 +WT/HK/25282 +WT/HK/25284 +WT/HK/25285 +WT/HK/25286 +WT/HK/25287 +WT/HK/25288 +WT/HK/25289 +WT/HK/25290 +WT/HK/25291 +WT/HK/25292 +WT/HK/25293 +WT/HK/25294 +WT/HK/25298 +WT/HK/25299 +WT/HK/25301 +WT/HK/25302 +WT/HK/25303 +WT/HK/25304 +WT/HK/25305 +WT/HK/25306 +WT/HK/25308 +WT/HK/25309 +WT/HK/25310 +WT/HK/25311 +WT/HK/25312 +WT/HK/25313 +WT/HK/25314 +WT/HK/25315 +WT/HK/25316 +WT/HK/25317 +WT/HK/25318 +WT/HK/25319 +WT/HK/25320 +WT/HK/25321 +WT/HK/25322 +WT/HK/25323 +WT/HK/25324 +WT/HK/25325 +WT/HK/25326 +WT/HK/25327 +WT/HK/25328 +WT/HK/25329 +WT/HK/25330 +WT/HK/25331 +WT/HK/25332 +WT/HK/25333 +WT/HK/25334 +WT/HK/25335 +WT/HK/25336 +WT/HK/25337 +WT/HK/25338 +WT/HK/25339 +WT/HK/25340 +WT/HK/25341 +WT/HK/25344 +WT/HK/25345 +WT/HK/25346 +WT/HK/25347 +WT/HK/25348 +WT/HK/25349 +WT/HK/25350 +WT/HK/25351 +WT/HK/25352 +WT/HK/25353 +WT/HK/25354 +WT/HK/25355 +WT/HK/25356 +WT/HK/25357 +WT/HK/25358 +WT/HK/25360 +WT/HK/25361 +WT/HK/25362 +WT/HK/25363 +WT/HK/25364 +WT/HK/25365 +WT/HK/25366 +WT/HK/25367 +WT/HK/25368 +WT/HK/25369 +WT/HK/25370 +WT/HK/25371 +WT/HK/25372 +WT/HK/25373 +WT/HK/25374 +WT/HK/25375 +WT/HK/25376 +WT/HK/25379 +WT/HK/25380 +WT/HK/25381 +WT/HK/25382 +WT/HK/25383 +WT/HK/25384 +WT/HK/25385 +WT/HK/25386 +WT/HK/25387 +WT/HK/25388 +WT/HK/25390 +WT/HK/25391 +WT/HK/25393 +WT/HK/25394 +WT/HK/25395 +WT/HK/25397 +WT/HK/25398 +WT/HK/25399 +WT/HK/25400 +WT/HK/25401 +WT/HK/25402 +WT/HK/25403 +WT/HK/25404 +WT/HK/25405 +WT/HK/25406 +WT/HK/25407 +WT/HK/25408 +WT/HK/25409 +WT/HK/25410 +WT/HK/25411 +WT/HK/25413 +WT/HK/25414 +WT/HK/25415 +WT/HK/25416 +WT/HK/25417 +WT/HK/25418 +WT/HK/25419 +WT/HK/25420 +WT/HK/25421 +WT/HK/25422 +WT/HK/25423 +WT/HK/25424 +WT/HK/25425 +WT/HK/25426 +WT/HK/25427 +WT/HK/25428 +WT/HK/25429 +WT/HK/25430 +WT/HK/25431 +WT/HK/25432 +WT/HK/25433 +WT/HK/25434 +WT/HK/25435 +WT/HK/25436 +WT/HK/25437 +WT/HK/25438 +WT/HK/25440 +WT/HK/25441 +WT/HK/25442 +WT/HK/25443 +WT/HK/25444 +WT/HK/25445 +WT/HK/25446 +WT/HK/25447 +WT/HK/25448 +WT/HK/25450 +WT/HK/25452 +WT/HK/25453 +WT/HK/25454 +WT/HK/25455 +WT/HK/25456 +WT/HK/25457 +WT/HK/25458 +WT/HK/25459 +WT/HK/25460 +WT/HK/25461 +WT/HK/25462 +WT/HK/25463 +WT/HK/25464 +WT/HK/25465 +WT/HK/25466 +WT/HK/25467 +WT/HK/25468 +WT/HK/25470 +WT/HK/25471 +WT/HK/25472 +WT/HK/25473 +WT/HK/25474 +WT/HK/25475 +WT/HK/25476 +WT/HK/25477 +WT/HK/25478 +WT/HK/25480 +WT/HK/25481 +WT/HK/25482 +WT/HK/25483 +WT/HK/25484 +WT/HK/25485 +WT/HK/25486 +WT/HK/25487 +WT/HK/25488 +WT/HK/25489 +WT/HK/25490 +WT/HK/25491 +WT/HK/25492 +WT/HK/25493 +WT/HK/25494 +WT/HK/25495 +WT/HK/25496 +WT/HK/25497 +WT/HK/25498 +WT/HK/25499 +WT/HK/25500 +WT/HK/25501 +WT/HK/25502 +WT/HK/25503 +WT/HK/25504 +WT/HK/25505 +WT/HK/25506 +WT/HK/25507 +WT/HK/25509 +WT/HK/25511 +WT/HK/25513 +WT/HK/25514 +WT/HK/25515 +WT/HK/25516 +WT/HK/25517 +WT/HK/25519 +WT/HK/25520 +WT/HK/25521 +WT/HK/25522 +WT/HK/25524 +WT/HK/25525 +WT/HK/25526 +WT/HK/25528 +WT/HK/25529 +WT/HK/25530 +WT/HK/25534 +WT/HK/25535 +WT/HK/25536 +WT/HK/25537 +WT/HK/25538 +WT/HK/25539 +WT/HK/25541 +WT/HK/25542 +WT/HK/25544 +WT/HK/25545 +WT/HK/25546 +WT/HK/25547 +WT/HK/25548 +WT/HK/25549 +WT/HK/25550 +WT/HK/25551 +WT/HK/25552 +WT/HK/25553 +WT/HK/25554 +WT/HK/25555 +WT/HK/25556 +WT/HK/25557 +WT/HK/25559 +WT/HK/25560 +WT/HK/25561 +WT/HK/25562 +WT/HK/25563 +WT/HK/25564 +WT/HK/25565 +WT/HK/25566 +WT/HK/25567 +WT/HK/25568 +WT/HK/25569 +WT/HK/25570 +WT/HK/25571 +WT/HK/25572 +WT/HK/25573 +WT/HK/25574 +WT/HK/25575 +WT/HK/25576 +WT/HK/25577 +WT/HK/25578 +WT/HK/25579 +WT/HK/25580 +WT/HK/25581 +WT/HK/25582 +WT/HK/25583 +WT/HK/25584 +WT/HK/25585 +WT/HK/25586 +WT/HK/25587 +WT/HK/25588 +WT/HK/25589 +WT/HK/25590 +WT/HK/25591 +WT/HK/25592 +WT/HK/25593 +WT/HK/25594 +WT/HK/25595 +WT/HK/25596 +WT/HK/25597 +WT/HK/25599 +WT/HK/25600 +WT/HK/25601 +WT/HK/25602 +WT/HK/25604 +WT/HK/25606 +WT/HK/25607 +WT/HK/25608 +WT/HK/25609 +WT/HK/25610 +WT/HK/25611 +WT/HK/25612 +WT/HK/25613 +WT/HK/25615 +WT/HK/25616 +WT/HK/25619 +WT/HK/25620 +WT/HK/25621 +WT/HK/25623 +WT/HK/25624 +WT/HK/25625 +WT/HK/25628 +WT/HK/25629 +WT/HK/25630 +WT/HK/25632 +WT/HK/25633 +WT/HK/25634 +WT/HK/25635 +WT/HK/25636 +WT/HK/25639 +WT/HK/25641 +WT/HK/25642 +WT/HK/25643 +WT/HK/25644 +WT/HK/25645 +WT/HK/25646 +WT/HK/25647 +WT/HK/25648 +WT/HK/25649 +WT/HK/25651 +WT/HK/25652 +WT/HK/25653 +WT/HK/25654 +WT/HK/25655 +WT/HK/25656 +WT/HK/25657 +WT/HK/25658 +WT/HK/25659 +WT/HK/25660 +WT/HK/25661 +WT/HK/25662 +WT/HK/25664 +WT/HK/25665 +WT/HK/25667 +WT/HK/25668 +WT/HK/25671 +WT/HK/25672 +WT/HK/25674 +WT/HK/25675 +WT/HK/25676 +WT/HK/25677 +WT/HK/25678 +WT/HK/25679 +WT/HK/25680 +WT/HK/25681 +WT/HK/25682 +WT/HK/25683 +WT/HK/25684 +WT/HK/25685 +WT/HK/25686 +WT/HK/25687 +WT/HK/25688 +WT/HK/25689 +WT/HK/25690 +WT/HK/25691 +WT/HK/25692 +WT/HK/25693 +WT/HK/25694 +WT/HK/25697 +WT/HK/25698 +WT/HK/25699 +WT/HK/25700 +WT/HK/25701 +WT/HK/25702 +WT/HK/25703 +WT/HK/25704 +WT/HK/25705 +WT/HK/25707 +WT/HK/25708 +WT/HK/25709 +WT/HK/25710 +WT/HK/25711 +WT/HK/25712 +WT/HK/25713 +WT/HK/25714 +WT/HK/25715 +WT/HK/25716 +WT/HK/25717 +WT/HK/25718 +WT/HK/25719 +WT/HK/25720 +WT/HK/25721 +WT/HK/25722 +WT/HK/25723 +WT/HK/25726 +WT/HK/25727 +WT/HK/25728 +WT/HK/25729 +WT/HK/25730 +WT/HK/25731 +WT/HK/25732 +WT/HK/25733 +WT/HK/25734 +WT/HK/25735 +WT/HK/25737 +WT/HK/25738 +WT/HK/25739 +WT/HK/25740 +WT/HK/25741 +WT/HK/25742 +WT/HK/25746 +WT/HK/25747 +WT/HK/25749 +WT/HK/25750 +WT/HK/25751 +WT/HK/25752 +WT/HK/25753 +WT/HK/25754 +WT/HK/25755 +WT/HK/25756 +WT/HK/25757 +WT/HK/25758 +WT/HK/25759 +WT/HK/25760 +WT/HK/25761 +WT/HK/25762 +WT/HK/25763 +WT/HK/25764 +WT/HK/25765 +WT/HK/25766 +WT/HK/25767 +WT/HK/25768 +WT/HK/25770 +WT/HK/25771 +WT/HK/25773 +WT/HK/25774 +WT/HK/25775 +WT/HK/25777 +WT/HK/25778 +WT/HK/25779 +WT/HK/25780 +WT/HK/25781 +WT/HK/25782 +WT/HK/25785 +WT/HK/25786 +WT/HK/25787 +WT/HK/25788 +WT/HK/25789 +WT/HK/25790 +WT/HK/25791 +WT/HK/25792 +WT/HK/25794 +WT/HK/25795 +WT/HK/25796 +WT/HK/25797 +WT/HK/25799 +WT/HK/25800 +WT/HK/25801 +WT/HK/25802 +WT/HK/25803 +WT/HK/25804 +WT/HK/25805 +WT/HK/25807 +WT/HK/25808 +WT/HK/25811 +WT/HK/25812 +WT/HK/25813 +WT/HK/25814 +WT/HK/25815 +WT/HK/25817 +WT/HK/25819 +WT/HK/25820 +WT/HK/25821 +WT/HK/25822 +WT/HK/25823 +WT/HK/25824 +WT/HK/25825 +WT/HK/25826 +WT/HK/25827 +WT/HK/25828 +WT/HK/25829 +WT/HK/25830 +WT/HK/25831 +WT/HK/25832 +WT/HK/25834 +WT/HK/25835 +WT/HK/25836 +WT/HK/25837 +WT/HK/25839 +WT/HK/25840 +WT/HK/25841 +WT/HK/25842 +WT/HK/25843 +WT/HK/25844 +WT/HK/25845 +WT/HK/25846 +WT/HK/25847 +WT/HK/25849 +WT/HK/25851 +WT/HK/25852 +WT/HK/25854 +WT/HK/25855 +WT/HK/25856 +WT/HK/25857 +WT/HK/25859 +WT/HK/25861 +WT/HK/25862 +WT/HK/25863 +WT/HK/25865 +WT/HK/25866 +WT/HK/25867 +WT/HK/25868 +WT/HK/25869 +WT/HK/25870 +WT/HK/25872 +WT/HK/25873 +WT/HK/25874 +WT/HK/25876 +WT/HK/25877 +WT/HK/25879 +WT/HK/25881 +WT/HK/25883 +WT/HK/25884 +WT/HK/25885 +WT/HK/25886 +WT/HK/25887 +WT/HK/25888 +WT/HK/25889 +WT/HK/25890 +WT/HK/25891 +WT/HK/25892 +WT/HK/25893 +WT/HK/25894 +WT/HK/25895 +WT/HK/25896 +WT/HK/25897 +WT/HK/25898 +WT/HK/25899 +WT/HK/25900 +WT/HK/25901 +WT/HK/25902 +WT/HK/25903 +WT/HK/25904 +WT/HK/25905 +WT/HK/25906 +WT/HK/25907 +WT/HK/25908 +WT/HK/25909 +WT/HK/25910 +WT/HK/25911 +WT/HK/25912 +WT/HK/25916 +WT/HK/25917 +WT/HK/25918 +WT/HK/25919 +WT/HK/25920 +WT/HK/25922 +WT/HK/25924 +WT/HK/25925 +WT/HK/25928 +WT/HK/25929 +WT/HK/25931 +WT/HK/25934 +WT/HK/25936 +WT/HK/25938 +WT/HK/25940 +WT/HK/25941 +WT/HK/25942 +WT/HK/25943 +WT/HK/25944 +WT/HK/25945 +WT/HK/25946 +WT/HK/25947 +WT/HK/25948 +WT/HK/25949 +WT/HK/25950 +WT/HK/25951 +WT/HK/25952 +WT/HK/25954 +WT/HK/25955 +WT/HK/25956 +WT/HK/25957 +WT/HK/25958 +WT/HK/25959 +WT/HK/25960 +WT/HK/25961 +WT/HK/25962 +WT/HK/25963 +WT/HK/25964 +WT/HK/25965 +WT/HK/25966 +WT/HK/25967 +WT/HK/25968 +WT/HK/25970 +WT/HK/25971 +WT/HK/25972 +WT/HK/25973 +WT/HK/25974 +WT/HK/25976 +WT/HK/25977 +WT/HK/25978 +WT/HK/25979 +WT/HK/25980 +WT/HK/25981 +WT/HK/25982 +WT/HK/25983 +WT/HK/25984 +WT/HK/25985 +WT/HK/25986 +WT/HK/25987 +WT/HK/25988 +WT/HK/25990 +WT/HK/25991 +WT/HK/25992 +WT/HK/25993 +WT/HK/25994 +WT/HK/25995 +WT/HK/25996 +WT/HK/25997 +WT/HK/25998 +WT/HK/26001 +WT/HK/26003 +WT/HK/26004 +WT/HK/26005 +WT/HK/26006 +WT/HK/26007 +WT/HK/26008 +WT/HK/26010 +WT/HK/26011 +WT/HK/26012 +WT/HK/26013 +WT/HK/26014 +WT/HK/26015 +WT/HK/26016 +WT/HK/26017 +WT/HK/26018 +WT/HK/26019 +WT/HK/26020 +WT/HK/26021 +WT/HK/26022 +WT/HK/26023 +WT/HK/26024 +WT/HK/26025 +WT/HK/26026 +WT/HK/26027 +WT/HK/26028 +WT/HK/26029 +WT/HK/26030 +WT/HK/26031 +WT/HK/26032 +WT/HK/26033 +WT/HK/26034 +WT/HK/26035 +WT/HK/26036 +WT/HK/26037 +WT/HK/26038 +WT/HK/26039 +WT/HK/26040 +WT/HK/26041 +WT/HK/26043 +WT/HK/26044 +WT/HK/26045 +WT/HK/26046 +WT/HK/26047 +WT/HK/26048 +WT/HK/26049 +WT/HK/26050 +WT/HK/26051 +WT/HK/26052 +WT/HK/26053 +WT/HK/26054 +WT/HK/26055 +WT/HK/26056 +WT/HK/26057 +WT/HK/26058 +WT/HK/26059 +WT/HK/26060 +WT/HK/26061 +WT/HK/26062 +WT/HK/26063 +WT/HK/26064 +WT/HK/26065 +WT/HK/26066 +WT/HK/26067 +WT/HK/26068 +WT/HK/26069 +WT/HK/26070 +WT/HK/26071 +WT/HK/26072 +WT/HK/26073 +WT/HK/26075 +WT/HK/26076 +WT/HK/26077 +WT/HK/26078 +WT/HK/26079 +WT/HK/26080 +WT/HK/26081 +WT/HK/26082 +WT/HK/26083 +WT/HK/26084 +WT/HK/26085 +WT/HK/26086 +WT/HK/26087 +WT/HK/26088 +WT/HK/26090 +WT/HK/26091 +WT/HK/26092 +WT/HK/26093 +WT/HK/26094 +WT/HK/26095 +WT/HK/26096 +WT/HK/26097 +WT/HK/26098 +WT/HK/26099 +WT/HK/26100 +WT/HK/26101 +WT/HK/26102 +WT/HK/26103 +WT/HK/26104 +WT/HK/26106 +WT/HK/26107 +WT/HK/26108 +WT/HK/26109 +WT/HK/26110 +WT/HK/26111 +WT/HK/26112 +WT/HK/26113 +WT/HK/26114 +WT/HK/26115 +WT/HK/26116 +WT/HK/26117 +WT/HK/26118 +WT/HK/26119 +WT/HK/26120 +WT/HK/26121 +WT/HK/26122 +WT/HK/26123 +WT/HK/26125 +WT/HK/26126 +WT/HK/26127 +WT/HK/26128 +WT/HK/26129 +WT/HK/26130 +WT/HK/26131 +WT/HK/26132 +WT/HK/26133 +WT/HK/26135 +WT/HK/26136 +WT/HK/26137 +WT/HK/26138 +WT/HK/26139 +WT/HK/26140 +WT/HK/26141 +WT/HK/26142 +WT/HK/26143 +WT/HK/26144 +WT/HK/26145 +WT/HK/26146 +WT/HK/26148 +WT/HK/26149 +WT/HK/26150 +WT/HK/26151 +WT/HK/26152 +WT/HK/26153 +WT/HK/26154 +WT/HK/26155 +WT/HK/26156 +WT/HK/26157 +WT/HK/26158 +WT/HK/26161 +WT/HK/26162 +WT/HK/26163 +WT/HK/26164 +WT/HK/26165 +WT/HK/26166 +WT/HK/26167 +WT/HK/26169 +WT/HK/26171 +WT/HK/26173 +WT/HK/26174 +WT/HK/26175 +WT/HK/26176 +WT/HK/26177 +WT/HK/26178 +WT/HK/26179 +WT/HK/26180 +WT/HK/26181 +WT/HK/26182 +WT/HK/26183 +WT/HK/26184 +WT/HK/26185 +WT/HK/26186 +WT/HK/26188 +WT/HK/26189 +WT/HK/26190 +WT/HK/26192 +WT/HK/26193 +WT/HK/26194 +WT/HK/26195 +WT/HK/26196 +WT/HK/26197 +WT/HK/26198 +WT/HK/26199 +WT/HK/26200 +WT/HK/26201 +WT/HK/26202 +WT/HK/26203 +WT/HK/26204 +WT/HK/26205 +WT/HK/26206 +WT/HK/26207 +WT/HK/26208 +WT/HK/26209 +WT/HK/26210 +WT/HK/26211 +WT/HK/26213 +WT/HK/26214 +WT/HK/26215 +WT/HK/26216 +WT/HK/26217 +WT/HK/26218 +WT/HK/26219 +WT/HK/26220 +WT/HK/26221 +WT/HK/26222 +WT/HK/26223 +WT/HK/26225 +WT/HK/26226 +WT/HK/26227 +WT/HK/26228 +WT/HK/26230 +WT/HK/26231 +WT/HK/26232 +WT/HK/26233 +WT/HK/26234 +WT/HK/26235 +WT/HK/26236 +WT/HK/26237 +WT/HK/26238 +WT/HK/26240 +WT/HK/26241 +WT/HK/26242 +WT/HK/26243 +WT/HK/26244 +WT/HK/26245 +WT/HK/26246 +WT/HK/26247 +WT/HK/26249 +WT/HK/26250 +WT/HK/26252 +WT/HK/26253 +WT/HK/26254 +WT/HK/26255 +WT/HK/26256 +WT/HK/26257 +WT/HK/26258 +WT/HK/26259 +WT/HK/26260 +WT/HK/26261 +WT/HK/26262 +WT/HK/26263 +WT/HK/26264 +WT/HK/26265 +WT/HK/26266 +WT/HK/26267 +WT/HK/26268 +WT/HK/26269 +WT/HK/26270 +WT/HK/26271 +WT/HK/26273 +WT/HK/26274 +WT/HK/26276 +WT/HK/26277 +WT/HK/26278 +WT/HK/26281 +WT/HK/26283 +WT/HK/26285 +WT/HK/26286 +WT/HK/26287 +WT/HK/26288 +WT/HK/26289 +WT/HK/26291 +WT/HK/26292 +WT/HK/26295 +WT/HK/26296 +WT/HK/26298 +WT/HK/26299 +WT/HK/26300 +WT/HK/26301 +WT/HK/26302 +WT/HK/26303 +WT/HK/26304 +WT/HK/26305 +WT/HK/26306 +WT/HK/26307 +WT/HK/26308 +WT/HK/26309 +WT/HK/26310 +WT/HK/26311 +WT/HK/26312 +WT/HK/26314 +WT/HK/26316 +WT/HK/26317 +WT/HK/26318 +WT/HK/26319 +WT/HK/26320 +WT/HK/26321 +WT/HK/26322 +WT/HK/26323 +WT/HK/26325 +WT/HK/26326 +WT/HK/26327 +WT/HK/26328 +WT/HK/26330 +WT/HK/26333 +WT/HK/26334 +WT/HK/26336 +WT/HK/26337 +WT/HK/26338 +WT/HK/26339 +WT/HK/26340 +WT/HK/26341 +WT/HK/26342 +WT/HK/26343 +WT/HK/26346 +WT/HK/26347 +WT/HK/26348 +WT/HK/26349 +WT/HK/26350 +WT/HK/26351 +WT/HK/26352 +WT/HK/26353 +WT/HK/26354 +WT/HK/26355 +WT/HK/26356 +WT/HK/26358 +WT/HK/26359 +WT/HK/26360 +WT/HK/26361 +WT/HK/26362 +WT/HK/26363 +WT/HK/26364 +WT/HK/26365 +WT/HK/26366 +WT/HK/26367 +WT/HK/26368 +WT/HK/26370 +WT/HK/26371 +WT/HK/26374 +WT/HK/26375 +WT/HK/26376 +WT/HK/26377 +WT/HK/26378 +WT/HK/26379 +WT/HK/26380 +WT/HK/26382 +WT/HK/26383 +WT/HK/26384 +WT/HK/26385 +WT/HK/26387 +WT/HK/26389 +WT/HK/26390 +WT/HK/26391 +WT/HK/26392 +WT/HK/26393 +WT/HK/26394 +WT/HK/26398 +WT/HK/26399 +WT/HK/26400 +WT/HK/26401 +WT/HK/26402 +WT/HK/26403 +WT/HK/26404 +WT/HK/26405 +WT/HK/26406 +WT/HK/26407 +WT/HK/26408 +WT/HK/26410 +WT/HK/26411 +WT/HK/26413 +WT/HK/26414 +WT/HK/26415 +WT/HK/26416 +WT/HK/26417 +WT/HK/26418 +WT/HK/26420 +WT/HK/26421 +WT/HK/26422 +WT/HK/26423 +WT/HK/26424 +WT/HK/26425 +WT/HK/26426 +WT/HK/26427 +WT/HK/26428 +WT/HK/26429 +WT/HK/26430 +WT/HK/26432 +WT/HK/26433 +WT/HK/26434 +WT/HK/26435 +WT/HK/26436 +WT/HK/26437 +WT/HK/26438 +WT/HK/26439 +WT/HK/26440 +WT/HK/26441 +WT/HK/26442 +WT/HK/26443 +WT/HK/26444 +WT/HK/26445 +WT/HK/26446 +WT/HK/26447 +WT/HK/26448 +WT/HK/26449 +WT/HK/26450 +WT/HK/26451 +WT/HK/26452 +WT/HK/26453 +WT/HK/26454 +WT/HK/26455 +WT/HK/26456 +WT/HK/26457 +WT/HK/26459 +WT/HK/26460 +WT/HK/26461 +WT/HK/26462 +WT/HK/26464 +WT/HK/26465 +WT/HK/26466 +WT/HK/26468 +WT/HK/26469 +WT/HK/26470 +WT/HK/26471 +WT/HK/26473 +WT/HK/26474 +WT/HK/26475 +WT/HK/26476 +WT/HK/26477 +WT/HK/26478 +WT/HK/26479 +WT/HK/26480 +WT/HK/26481 +WT/HK/26482 +WT/HK/26483 +WT/HK/26484 +WT/HK/26485 +WT/HK/26486 +WT/HK/26487 +WT/HK/26488 +WT/HK/26490 +WT/HK/26491 +WT/HK/26492 +WT/HK/26493 +WT/HK/26494 +WT/HK/26495 +WT/HK/26496 +WT/HK/26497 +WT/HK/26498 +WT/HK/26499 +WT/HK/26500 +WT/HK/26501 +WT/HK/26502 +WT/HK/26503 +WT/HK/26504 +WT/HK/26505 +WT/HK/26506 +WT/HK/26507 +WT/HK/26508 +WT/HK/26510 +WT/HK/26512 +WT/HK/26513 +WT/HK/26514 +WT/HK/26515 +WT/HK/26516 +WT/HK/26517 +WT/HK/26518 +WT/HK/26519 +WT/HK/26520 +WT/HK/26521 +WT/HK/26522 +WT/HK/26523 +WT/HK/26524 +WT/HK/26525 +WT/HK/26526 +WT/HK/26527 +WT/HK/26528 +WT/HK/26530 +WT/HK/26531 +WT/HK/26532 +WT/HK/26534 +WT/HK/26535 +WT/HK/26536 +WT/HK/26537 +WT/HK/26538 +WT/HK/26541 +WT/HK/26542 +WT/HK/26544 +WT/HK/26545 +WT/HK/26547 +WT/HK/26548 +WT/HK/26549 +WT/HK/26550 +WT/HK/26552 +WT/HK/26553 +WT/HK/26554 +WT/HK/26555 +WT/HK/26556 +WT/HK/26557 +WT/HK/26558 +WT/HK/26559 +WT/HK/26560 +WT/HK/26561 +WT/HK/26562 +WT/HK/26563 +WT/HK/26564 +WT/HK/26565 +WT/HK/26567 +WT/HK/26568 +WT/HK/26569 +WT/HK/26570 +WT/HK/26571 +WT/HK/26573 +WT/HK/26574 +WT/HK/26575 +WT/HK/26577 +WT/HK/26578 +WT/HK/26579 +WT/HK/26580 +WT/HK/26581 +WT/HK/26582 +WT/HK/26583 +WT/HK/26584 +WT/HK/26585 +WT/HK/26587 +WT/HK/26588 +WT/HK/26589 +WT/HK/26590 +WT/HK/26591 +WT/HK/26595 +WT/HK/26598 +WT/HK/26600 +WT/HK/26601 +WT/HK/26603 +WT/HK/26604 +WT/HK/26605 +WT/HK/26606 +WT/HK/26608 +WT/HK/26609 +WT/HK/26610 +WT/HK/26611 +WT/HK/26612 +WT/HK/26613 +WT/HK/26614 +WT/HK/26615 +WT/HK/26616 +WT/HK/26617 +WT/HK/26618 +WT/HK/26619 +WT/HK/26620 +WT/HK/26621 +WT/HK/26622 +WT/HK/26623 +WT/HK/26624 +WT/HK/26625 +WT/HK/26626 +WT/HK/26627 +WT/HK/26628 +WT/HK/26629 +WT/HK/26631 +WT/HK/26632 +WT/HK/26633 +WT/HK/26634 +WT/HK/26635 +WT/HK/26636 +WT/HK/26637 +WT/HK/26638 +WT/HK/26639 +WT/HK/26640 +WT/HK/26641 +WT/HK/26642 +WT/HK/26643 +WT/HK/26645 +WT/HK/26646 +WT/HK/26647 +WT/HK/26648 +WT/HK/26649 +WT/HK/26651 +WT/HK/26653 +WT/HK/26655 +WT/HK/26656 +WT/HK/26658 +WT/HK/26659 +WT/HK/26660 +WT/HK/26661 +WT/HK/26662 +WT/HK/26663 +WT/HK/26664 +WT/HK/26667 +WT/HK/26668 +WT/HK/26669 +WT/HK/26671 +WT/HK/26673 +WT/HK/26674 +WT/HK/26676 +WT/HK/26677 +WT/HK/26678 +WT/HK/26680 +WT/HK/26681 +WT/HK/26682 +WT/HK/26684 +WT/HK/26685 +WT/HK/26686 +WT/HK/26687 +WT/HK/26688 +WT/HK/26689 +WT/HK/26690 +WT/HK/26691 +WT/HK/26692 +WT/HK/26693 +WT/HK/26694 +WT/HK/26695 +WT/HK/26696 +WT/HK/26697 +WT/HK/26698 +WT/HK/26699 +WT/HK/26700 +WT/HK/26701 +WT/HK/26702 +WT/HK/26703 +WT/HK/26706 +WT/HK/26707 +WT/HK/26708 +WT/HK/26709 +WT/HK/26711 +WT/HK/26712 +WT/HK/26714 +WT/HK/26715 +WT/HK/26716 +WT/HK/26717 +WT/HK/26718 +WT/HK/26719 +WT/HK/26720 +WT/HK/26721 +WT/HK/26723 +WT/HK/26724 +WT/HK/26726 +WT/HK/26728 +WT/HK/26729 +WT/HK/26730 +WT/HK/26731 +WT/HK/26732 +WT/HK/26733 +WT/HK/26734 +WT/HK/26735 +WT/HK/26736 +WT/HK/26737 +WT/HK/26738 +WT/HK/26739 +WT/HK/26740 +WT/HK/26741 +WT/HK/26742 +WT/HK/26743 +WT/HK/26744 +WT/HK/26746 +WT/HK/26747 +WT/HK/26748 +WT/HK/26750 +WT/HK/26751 +WT/HK/26752 +WT/HK/26753 +WT/HK/26756 +WT/HK/26757 +WT/HK/26758 +WT/HK/26759 +WT/HK/26760 +WT/HK/26762 +WT/HK/26764 +WT/HK/26765 +WT/HK/26767 +WT/HK/26768 +WT/HK/26769 +WT/HK/26770 +WT/HK/26771 +WT/HK/26774 +WT/HK/26775 +WT/HK/26776 +WT/HK/26777 +WT/HK/26778 +WT/HK/26779 +WT/HK/26780 +WT/HK/26782 +WT/HK/26784 +WT/HK/26786 +WT/HK/26787 +WT/HK/26789 +WT/HK/26790 +WT/HK/26791 +WT/HK/26792 +WT/HK/26793 +WT/HK/26794 +WT/HK/26795 +WT/HK/26796 +WT/HK/26797 +WT/HK/26798 +WT/HK/26800 +WT/HK/26801 +WT/HK/26802 +WT/HK/26803 +WT/HK/26804 +WT/HK/26805 +WT/HK/26806 +WT/HK/26807 +WT/HK/26808 +WT/HK/26809 +WT/HK/26812 +WT/HK/26813 +WT/HK/26814 +WT/HK/26815 +WT/HK/26816 +WT/HK/26818 +WT/HK/26819 +WT/HK/26820 +WT/HK/26821 +WT/HK/26823 +WT/HK/26824 +WT/HK/26825 +WT/HK/26826 +WT/HK/26828 +WT/HK/26829 +WT/HK/26830 +WT/HK/26831 +WT/HK/26832 +WT/HK/26833 +WT/HK/26834 +WT/HK/26837 +WT/HK/26838 +WT/HK/26839 +WT/HK/26840 +WT/HK/26841 +WT/HK/26842 +WT/HK/26843 +WT/HK/26844 +WT/HK/26845 +WT/HK/26846 +WT/HK/26847 +WT/HK/26848 +WT/HK/26849 +WT/HK/26850 +WT/HK/26851 +WT/HK/26853 +WT/HK/26854 +WT/HK/26855 +WT/HK/26856 +WT/HK/26857 +WT/HK/26858 +WT/HK/26859 +WT/HK/26860 +WT/HK/26862 +WT/HK/26863 +WT/HK/26864 +WT/HK/26866 +WT/HK/26869 +WT/HK/26870 +WT/HK/26871 +WT/HK/26873 +WT/HK/26875 +WT/HK/26876 +WT/HK/26877 +WT/HK/26878 +WT/HK/26879 +WT/HK/26880 +WT/HK/26881 +WT/HK/26882 +WT/HK/26883 +WT/HK/26886 +WT/HK/26887 +WT/HK/26888 +WT/HK/26889 +WT/HK/26890 +WT/HK/26891 +WT/HK/26892 +WT/HK/26893 +WT/HK/26894 +WT/HK/26899 +WT/HK/26900 +WT/HK/26901 +WT/HK/26903 +WT/HK/26904 +WT/HK/26905 +WT/HK/26906 +WT/HK/26907 +WT/HK/26908 +WT/HK/26909 +WT/HK/26910 +WT/HK/26911 +WT/HK/26913 +WT/HK/26914 +WT/HK/26915 +WT/HK/26916 +WT/HK/26919 +WT/HK/26921 +WT/HK/26925 +WT/HK/26926 +WT/HK/26927 +WT/HK/26928 +WT/HK/26929 +WT/HK/26930 +WT/HK/26931 +WT/HK/26932 +WT/HK/26933 +WT/HK/26935 +WT/HK/26936 +WT/HK/26937 +WT/HK/26939 +WT/HK/26940 +WT/HK/26941 +WT/HK/26942 +WT/HK/26943 +WT/HK/26944 +WT/HK/26945 +WT/HK/26946 +WT/HK/26947 +WT/HK/26949 +WT/HK/26950 +WT/HK/26952 +WT/HK/26953 +WT/HK/26954 +WT/HK/26955 +WT/HK/26956 +WT/HK/26957 +WT/HK/26959 +WT/HK/26960 +WT/HK/26963 +WT/HK/26964 +WT/HK/26965 +WT/HK/26966 +WT/HK/26967 +WT/HK/26968 +WT/HK/26969 +WT/HK/26970 +WT/HK/26971 +WT/HK/26972 +WT/HK/26974 +WT/HK/26975 +WT/HK/26976 +WT/HK/26977 +WT/HK/26979 +WT/HK/26982 +WT/HK/26983 +WT/HK/26984 +WT/HK/26985 +WT/HK/26987 +WT/HK/26988 +WT/HK/26989 +WT/HK/26990 +WT/HK/26991 +WT/HK/26992 +WT/HK/26993 +WT/HK/26994 +WT/HK/26996 +WT/HK/26998 +WT/HK/26999 +WT/HK/27000 +WT/HK/27001 +WT/HK/27002 +WT/HK/27003 +WT/HK/27004 +WT/HK/27005 +WT/HK/27006 +WT/HK/27007 +WT/HK/27008 +WT/HK/27009 +WT/HK/27010 +WT/HK/27011 +WT/HK/27012 +WT/HK/27013 +WT/HK/27015 +WT/HK/27016 +WT/HK/27017 +WT/HK/27018 +WT/HK/27019 +WT/HK/27020 +WT/HK/27021 +WT/HK/27023 +WT/HK/27025 +WT/HK/27026 +WT/HK/27027 +WT/HK/27030 +WT/HK/27034 +WT/HK/27035 +WT/HK/27036 +WT/HK/27037 +WT/HK/27038 +WT/HK/27039 +WT/HK/27040 +WT/HK/27041 +WT/HK/27044 +WT/HK/27045 +WT/HK/27046 +WT/HK/27048 +WT/HK/27051 +WT/HK/27052 +WT/HK/27053 +WT/HK/27054 +WT/HK/27055 +WT/HK/27056 +WT/HK/27057 +WT/HK/27058 +WT/HK/27059 +WT/HK/27060 +WT/HK/27061 +WT/HK/27063 +WT/HK/27065 +WT/HK/27066 +WT/HK/27067 +WT/HK/27068 +WT/HK/27069 +WT/HK/27070 +WT/HK/27072 +WT/HK/27074 +WT/HK/27075 +WT/HK/27077 +WT/HK/27078 +WT/HK/27079 +WT/HK/27080 +WT/HK/27081 +WT/HK/27082 +WT/HK/27083 +WT/HK/27085 +WT/HK/27086 +WT/HK/27087 +WT/HK/27088 +WT/HK/27089 +WT/HK/27090 +WT/HK/27092 +WT/HK/27093 +WT/HK/27094 +WT/HK/27096 +WT/HK/27097 +WT/HK/27098 +WT/HK/27100 +WT/HK/27101 +WT/HK/27102 +WT/HK/27104 +WT/HK/27105 +WT/HK/27106 +WT/HK/27107 +WT/HK/27108 +WT/HK/27109 +WT/HK/27110 +WT/HK/27111 +WT/HK/27112 +WT/HK/27113 +WT/HK/27114 +WT/HK/27115 +WT/HK/27116 +WT/HK/27117 +WT/HK/27118 +WT/HK/27119 +WT/HK/27120 +WT/HK/27121 +WT/HK/27123 +WT/HK/27125 +WT/HK/27127 +WT/HK/27128 +WT/HK/27129 +WT/HK/27130 +WT/HK/27131 +WT/HK/27132 +WT/HK/27136 +WT/HK/27137 +WT/HK/27138 +WT/HK/27139 +WT/HK/27140 +WT/HK/27141 +WT/HK/27142 +WT/HK/27143 +WT/HK/27144 +WT/HK/27145 +WT/HK/27146 +WT/HK/27147 +WT/HK/27148 +WT/HK/27149 +WT/HK/27150 +WT/HK/27151 +WT/HK/27153 +WT/HK/27154 +WT/HK/27157 +WT/HK/27158 +WT/HK/27161 +WT/HK/27162 +WT/HK/27163 +WT/HK/27164 +WT/HK/27165 +WT/HK/27166 +WT/HK/27168 +WT/HK/27170 +WT/HK/27171 +WT/HK/27172 +WT/HK/27173 +WT/HK/27176 +WT/HK/27177 +WT/HK/27178 +WT/HK/27179 +WT/HK/27180 +WT/HK/27181 +WT/HK/27182 +WT/HK/27183 +WT/HK/27184 +WT/HK/27185 +WT/HK/27186 +WT/HK/27187 +WT/HK/27188 +WT/HK/27189 +WT/HK/27190 +WT/HK/27191 +WT/HK/27192 +WT/HK/27193 +WT/HK/27194 +WT/HK/27195 +WT/HK/27196 +WT/HK/27197 +WT/HK/27198 +WT/HK/27199 +WT/HK/27200 +WT/HK/27201 +WT/HK/27202 +WT/HK/27203 +WT/HK/27204 +WT/HK/27205 +WT/HK/27206 +WT/HK/27207 +WT/HK/27208 +WT/HK/27209 +WT/HK/27210 +WT/HK/27211 +WT/HK/27212 +WT/HK/27213 +WT/HK/27214 +WT/HK/27215 +WT/HK/27216 +WT/HK/27217 +WT/HK/27218 +WT/HK/27219 +WT/HK/27220 +WT/HK/27221 +WT/HK/27222 +WT/HK/27223 +WT/HK/27224 +WT/HK/27226 +WT/HK/27227 +WT/HK/27228 +WT/HK/27229 +WT/HK/27231 +WT/HK/27232 +WT/HK/27233 +WT/HK/27234 +WT/HK/27235 +WT/HK/27236 +WT/HK/27238 +WT/HK/27239 +WT/HK/27240 +WT/HK/27242 +WT/HK/27243 +WT/HK/27244 +WT/HK/27245 +WT/HK/27246 +WT/HK/27247 +WT/HK/27248 +WT/HK/27250 +WT/HK/27251 +WT/HK/27252 +WT/HK/27253 +WT/HK/27256 +WT/HK/27257 +WT/HK/27258 +WT/HK/27259 +WT/HK/27260 +WT/HK/27261 +WT/HK/27262 +WT/HK/27263 +WT/HK/27264 +WT/HK/27265 +WT/HK/27266 +WT/HK/27269 +WT/HK/27270 +WT/HK/27271 +WT/HK/27272 +WT/HK/27273 +WT/HK/27274 +WT/HK/27275 +WT/HK/27277 +WT/HK/27279 +WT/HK/27281 +WT/HK/27282 +WT/HK/27284 +WT/HK/27285 +WT/HK/27286 +WT/HK/27287 +WT/HK/27288 +WT/HK/27289 +WT/HK/27290 +WT/HK/27292 +WT/HK/27293 +WT/HK/27295 +WT/HK/27296 +WT/HK/27298 +WT/HK/27299 +WT/HK/27300 +WT/HK/27301 +WT/HK/27302 +WT/HK/27304 +WT/HK/27306 +WT/HK/27307 +WT/HK/27308 +WT/HK/27309 +WT/HK/27311 +WT/HK/27312 +WT/HK/27313 +WT/HK/27316 +WT/HK/27318 +WT/HK/27319 +WT/HK/27320 +WT/HK/27321 +WT/HK/27323 +WT/HK/27324 +WT/HK/27325 +WT/HK/27326 +WT/HK/27327 +WT/HK/27328 +WT/HK/27329 +WT/HK/27330 +WT/HK/27332 +WT/HK/27333 +WT/HK/27334 +WT/HK/27336 +WT/HK/27337 +WT/HK/27338 +WT/HK/27339 +WT/HK/27340 +WT/HK/27341 +WT/HK/27342 +WT/HK/27343 +WT/HK/27344 +WT/HK/27346 +WT/HK/27347 +WT/HK/27348 +WT/HK/27349 +WT/HK/27351 +WT/HK/27352 +WT/HK/27355 +WT/HK/27356 +WT/HK/27357 +WT/HK/27360 +WT/HK/27362 +WT/HK/27363 +WT/HK/27364 +WT/HK/27365 +WT/HK/27367 +WT/HK/27369 +WT/HK/27370 +WT/HK/27371 +WT/HK/27372 +WT/HK/27374 +WT/HK/27375 +WT/HK/27376 +WT/HK/27377 +WT/HK/27378 +WT/HK/27379 +WT/HK/27380 +WT/HK/27381 +WT/HK/27382 +WT/HK/27383 +WT/HK/27384 +WT/HK/27385 +WT/HK/27386 +WT/HK/27387 +WT/HK/27388 +WT/HK/27389 +WT/HK/27390 +WT/HK/27391 +WT/HK/27392 +WT/HK/27393 +WT/HK/27394 +WT/HK/27396 +WT/HK/27397 +WT/HK/27398 +WT/HK/27401 +WT/HK/27403 +WT/HK/27404 +WT/HK/27405 +WT/HK/27406 +WT/HK/27408 +WT/HK/27409 +WT/HK/27411 +WT/HK/27412 +WT/HK/27416 +WT/HK/27418 +WT/HK/27419 +WT/HK/27420 +WT/HK/27422 +WT/HK/27423 +WT/HK/27424 +WT/HK/27425 +WT/HK/27426 +WT/HK/27428 +WT/HK/27429 +WT/HK/27430 +WT/HK/27431 +WT/HK/27432 +WT/HK/27433 +WT/HK/27434 +WT/HK/27436 +WT/HK/27438 +WT/HK/27439 +WT/HK/27440 +WT/HK/27441 +WT/HK/27442 +WT/HK/27443 +WT/HK/27444 +WT/HK/27445 +WT/HK/27446 +WT/HK/27447 +WT/HK/27449 +WT/HK/27450 +WT/HK/27451 +WT/HK/27452 +WT/HK/27453 +WT/HK/27454 +WT/HK/27455 +WT/HK/27456 +WT/HK/27457 +WT/HK/27458 +WT/HK/27459 +WT/HK/27461 +WT/HK/27462 +WT/HK/27464 +WT/HK/27465 +WT/HK/27467 +WT/HK/27468 +WT/HK/27469 +WT/HK/27471 +WT/HK/27472 +WT/HK/27473 +WT/HK/27474 +WT/HK/27475 +WT/HK/27476 +WT/HK/27477 +WT/HK/27478 +WT/HK/27479 +WT/HK/27481 +WT/HK/27482 +WT/HK/27483 +WT/HK/27484 +WT/HK/27485 +WT/HK/27487 +WT/HK/27488 +WT/HK/27491 +WT/HK/27492 +WT/HK/27493 +WT/HK/27494 +WT/HK/27495 +WT/HK/27496 +WT/HK/27498 +WT/HK/27499 +WT/HK/27500 +WT/HK/27501 +WT/HK/27502 +WT/HK/27504 +WT/HK/27505 +WT/HK/27506 +WT/HK/27507 +WT/HK/27508 +WT/HK/27509 +WT/HK/27510 +WT/HK/27511 +WT/HK/27512 +WT/HK/27513 +WT/HK/27514 +WT/HK/27515 +WT/HK/27516 +WT/HK/27517 +WT/HK/27519 +WT/HK/27520 +WT/HK/27521 +WT/HK/27523 +WT/HK/27524 +WT/HK/27525 +WT/HK/27527 +WT/HK/27529 +WT/HK/27530 +WT/HK/27531 +WT/HK/27532 +WT/HK/27533 +WT/HK/27534 +WT/HK/27535 +WT/HK/27536 +WT/HK/27537 +WT/HK/27538 +WT/HK/27540 +WT/HK/27541 +WT/HK/27542 +WT/HK/27543 +WT/HK/27545 +WT/HK/27546 +WT/HK/27547 +WT/HK/27548 +WT/HK/27549 +WT/HK/27550 +WT/HK/27551 +WT/HK/27552 +WT/HK/27553 +WT/HK/27554 +WT/HK/27555 +WT/HK/27556 +WT/HK/27557 +WT/HK/27558 +WT/HK/27559 +WT/HK/27560 +WT/HK/27561 +WT/HK/27562 +WT/HK/27564 +WT/HK/27565 +WT/HK/27566 +WT/HK/27567 +WT/HK/27568 +WT/HK/27569 +WT/HK/27570 +WT/HK/27571 +WT/HK/27573 +WT/HK/27574 +WT/HK/27575 +WT/HK/27577 +WT/HK/27578 +WT/HK/27582 +WT/HK/27585 +WT/HK/27586 +WT/HK/27587 +WT/HK/27588 +WT/HK/27589 +WT/HK/27590 +WT/HK/27591 +WT/HK/27592 +WT/HK/27594 +WT/HK/27595 +WT/HK/27596 +WT/HK/27597 +WT/HK/27598 +WT/HK/27599 +WT/HK/27600 +WT/HK/27601 +WT/HK/27602 +WT/HK/27603 +WT/HK/27605 +WT/HK/27607 +WT/HK/27608 +WT/HK/27609 +WT/HK/27610 +WT/HK/27611 +WT/HK/27612 +WT/HK/27613 +WT/HK/27614 +WT/HK/27615 +WT/HK/27617 +WT/HK/27618 +WT/HK/27619 +WT/HK/27621 +WT/HK/27622 +WT/HK/27623 +WT/HK/27624 +WT/HK/27625 +WT/HK/27626 +WT/HK/27627 +WT/HK/27628 +WT/HK/27630 +WT/HK/27631 +WT/HK/27632 +WT/HK/27633 +WT/HK/27634 +WT/HK/27635 +WT/HK/27636 +WT/HK/27637 +WT/HK/27638 +WT/HK/27639 +WT/HK/27641 +WT/HK/27642 +WT/HK/27643 +WT/HK/27644 +WT/HK/27645 +WT/HK/27646 +WT/HK/27647 +WT/HK/27649 +WT/HK/27650 +WT/HK/27651 +WT/HK/27653 +WT/HK/27654 +WT/HK/27655 +WT/HK/27656 +WT/HK/27658 +WT/HK/27659 +WT/HK/27661 +WT/HK/27662 +WT/HK/27663 +WT/HK/27664 +WT/HK/27666 +WT/HK/27667 +WT/HK/27671 +WT/HK/27672 +WT/HK/27673 +WT/HK/27674 +WT/HK/27675 +WT/HK/27676 +WT/HK/27677 +WT/HK/27678 +WT/HK/27679 +WT/HK/27680 +WT/HK/27681 +WT/HK/27682 +WT/HK/27683 +WT/HK/27684 +WT/HK/27685 +WT/HK/27686 +WT/HK/27687 +WT/HK/27690 +WT/HK/27691 +WT/HK/27692 +WT/HK/27693 +WT/HK/27694 +WT/HK/27695 +WT/HK/27696 +WT/HK/27700 +WT/HK/27702 +WT/HK/27703 +WT/HK/27704 +WT/HK/27706 +WT/HK/27707 +WT/HK/27708 +WT/HK/27709 +WT/HK/27710 +WT/HK/27711 +WT/HK/27712 +WT/HK/27713 +WT/HK/27714 +WT/HK/27715 +WT/HK/27717 +WT/HK/27718 +WT/HK/27721 +WT/HK/27723 +WT/HK/27724 +WT/HK/27725 +WT/HK/27726 +WT/HK/27727 +WT/HK/27728 +WT/HK/27729 +WT/HK/27730 +WT/HK/27731 +WT/HK/27732 +WT/HK/27733 +WT/HK/27734 +WT/HK/27735 +WT/HK/27736 +WT/HK/27737 +WT/HK/27738 +WT/HK/27739 +WT/HK/27740 +WT/HK/27742 +WT/HK/27744 +WT/HK/27745 +WT/HK/27747 +WT/HK/27749 +WT/HK/27750 +WT/HK/27751 +WT/HK/27752 +WT/HK/27753 +WT/HK/27754 +WT/HK/27755 +WT/HK/27756 +WT/HK/27757 +WT/HK/27758 +WT/HK/27759 +WT/HK/27761 +WT/HK/27763 +WT/HK/27764 +WT/HK/27765 +WT/HK/27766 +WT/HK/27767 +WT/HK/27768 +WT/HK/27769 +WT/HK/27770 +WT/HK/27771 +WT/HK/27772 +WT/HK/27773 +WT/HK/27774 +WT/HK/27775 +WT/HK/27776 +WT/HK/27777 +WT/HK/27779 +WT/HK/27780 +WT/HK/27781 +WT/HK/27782 +WT/HK/27783 +WT/HK/27784 +WT/HK/27785 +WT/HK/27786 +WT/HK/27787 +WT/HK/27788 +WT/HK/27790 +WT/HK/27791 +WT/HK/27792 +WT/HK/27793 +WT/HK/27794 +WT/HK/27795 +WT/HK/27796 +WT/HK/27798 +WT/HK/27799 +WT/HK/27802 +WT/HK/27804 +WT/HK/27805 +WT/HK/27806 +WT/HK/27807 +WT/HK/27808 +WT/HK/27811 +WT/HK/27812 +WT/HK/27813 +WT/HK/27814 +WT/HK/27816 +WT/HK/27821 +WT/HK/27823 +WT/HK/27824 +WT/HK/27825 +WT/HK/27828 +WT/HK/27829 +WT/HK/27830 +WT/HK/27831 +WT/HK/27832 +WT/HK/27834 +WT/HK/27835 +WT/HK/27836 +WT/HK/27838 +WT/HK/27839 +WT/HK/27841 +WT/HK/27843 +WT/HK/27846 +WT/HK/27847 +WT/HK/27848 +WT/HK/27849 +WT/HK/27850 +WT/HK/27851 +WT/HK/27852 +WT/HK/27853 +WT/HK/27854 +WT/HK/27856 +WT/HK/27857 +WT/HK/27858 +WT/HK/27859 +WT/HK/27860 +WT/HK/27861 +WT/HK/27862 +WT/HK/27863 +WT/HK/27864 +WT/HK/27865 +WT/HK/27866 +WT/HK/27867 +WT/HK/27868 +WT/HK/27869 +WT/HK/27870 +WT/HK/27871 +WT/HK/27872 +WT/HK/27873 +WT/HK/27874 +WT/HK/27875 +WT/HK/27876 +WT/HK/27877 +WT/HK/27878 +WT/HK/27879 +WT/HK/27880 +WT/HK/27881 +WT/HK/27882 +WT/HK/27883 +WT/HK/27884 +WT/HK/27886 +WT/HK/27887 +WT/HK/27890 +WT/HK/27891 +WT/HK/27892 +WT/HK/27893 +WT/HK/27894 +WT/HK/27895 +WT/HK/27896 +WT/HK/27897 +WT/HK/27899 +WT/HK/27900 +WT/HK/27903 +WT/HK/27906 +WT/HK/27907 +WT/HK/27909 +WT/HK/27912 +WT/HK/27913 +WT/HK/27915 +WT/HK/27916 +WT/HK/27917 +WT/HK/27918 +WT/HK/27920 +WT/HK/27921 +WT/HK/27922 +WT/HK/27923 +WT/HK/27924 +WT/HK/27927 +WT/HK/27928 +WT/HK/27929 +WT/HK/27930 +WT/HK/27931 +WT/HK/27932 +WT/HK/27933 +WT/HK/27935 +WT/HK/27936 +WT/HK/27937 +WT/HK/27938 +WT/HK/27939 +WT/HK/27940 +WT/HK/27941 +WT/HK/27942 +WT/HK/27943 +WT/HK/27945 +WT/HK/27946 +WT/HK/27947 +WT/HK/27948 +WT/HK/27949 +WT/HK/27950 +WT/HK/27951 +WT/HK/27952 +WT/HK/27953 +WT/HK/27954 +WT/HK/27955 +WT/HK/27956 +WT/HK/27957 +WT/HK/27958 +WT/HK/27959 +WT/HK/27960 +WT/HK/27962 +WT/HK/27963 +WT/HK/27964 +WT/HK/27965 +WT/HK/27966 +WT/HK/27969 +WT/HK/27970 +WT/HK/27971 +WT/HK/27972 +WT/HK/27973 +WT/HK/27974 +WT/HK/27975 +WT/HK/27976 +WT/HK/27978 +WT/HK/27979 +WT/HK/27980 +WT/HK/27981 +WT/HK/27982 +WT/HK/27983 +WT/HK/27984 +WT/HK/27988 +WT/HK/27989 +WT/HK/27990 +WT/HK/27991 +WT/HK/27992 +WT/HK/27993 +WT/HK/27994 +WT/HK/27995 +WT/HK/27996 +WT/HK/27997 +WT/HK/27998 +WT/HK/27999 +WT/HK/28000 +WT/HK/28001 +WT/HK/28002 +WT/HK/28004 +WT/HK/28005 +WT/HK/28006 +WT/HK/28007 +WT/HK/28008 +WT/HK/28009 +WT/HK/28011 +WT/HK/28012 +WT/HK/28013 +WT/HK/28014 +WT/HK/28015 +WT/HK/28016 +WT/HK/28017 +WT/HK/28018 +WT/HK/28019 +WT/HK/28020 +WT/HK/28021 +WT/HK/28022 +WT/HK/28023 +WT/HK/28024 +WT/HK/28025 +WT/HK/28026 +WT/HK/28027 +WT/HK/28028 +WT/HK/28029 +WT/HK/28030 +WT/HK/28031 +WT/HK/28032 +WT/HK/28033 +WT/HK/28034 +WT/HK/28035 +WT/HK/28036 +WT/HK/28037 +WT/HK/28038 +WT/HK/28039 +WT/HK/28040 +WT/HK/28041 +WT/HK/28042 +WT/HK/28043 +WT/HK/28044 +WT/HK/28045 +WT/HK/28046 +WT/HK/28047 +WT/HK/28048 +WT/HK/28049 +WT/HK/28050 +WT/HK/28051 +WT/HK/28052 +WT/HK/28053 +WT/HK/28054 +WT/HK/28055 +WT/HK/28056 +WT/HK/28057 +WT/HK/28058 +WT/HK/28060 +WT/HK/28061 +WT/HK/28062 +WT/HK/28063 +WT/HK/28064 +WT/HK/28065 +WT/HK/28066 +WT/HK/28067 +WT/HK/28070 +WT/HK/28071 +WT/HK/28072 +WT/HK/28073 +WT/HK/28074 +WT/HK/28075 +WT/HK/28076 +WT/HK/28077 +WT/HK/28078 +WT/HK/28081 +WT/HK/28082 +WT/HK/28083 +WT/HK/28084 +WT/HK/28086 +WT/HK/28087 +WT/HK/28090 +WT/HK/28091 +WT/HK/28092 +WT/HK/28093 +WT/HK/28094 +WT/HK/28096 +WT/HK/28097 +WT/HK/28098 +WT/HK/28099 +WT/HK/28100 +WT/HK/28101 +WT/HK/28102 +WT/HK/28103 +WT/HK/28104 +WT/HK/28105 +WT/HK/28106 +WT/HK/28107 +WT/HK/28108 +WT/HK/28109 +WT/HK/28110 +WT/HK/28111 +WT/HK/28112 +WT/HK/28113 +WT/HK/28114 +WT/HK/28115 +WT/HK/28116 +WT/HK/28117 +WT/HK/28118 +WT/HK/28119 +WT/HK/28120 +WT/HK/28122 +WT/HK/28124 +WT/HK/28125 +WT/HK/28126 +WT/HK/28127 +WT/HK/28128 +WT/HK/28129 +WT/HK/28130 +WT/HK/28131 +WT/HK/28132 +WT/HK/28133 +WT/HK/28134 +WT/HK/28135 +WT/HK/28136 +WT/HK/28137 +WT/HK/28138 +WT/HK/28139 +WT/HK/28140 +WT/HK/28141 +WT/HK/28142 +WT/HK/28143 +WT/HK/28144 +WT/HK/28145 +WT/HK/28146 +WT/HK/28148 +WT/HK/28149 +WT/HK/28150 +WT/HK/28151 +WT/HK/28152 +WT/HK/28153 +WT/HK/28154 +WT/HK/28157 +WT/HK/28158 +WT/HK/28159 +WT/HK/28160 +WT/HK/28161 +WT/HK/28162 +WT/HK/28163 +WT/HK/28164 +WT/HK/28166 +WT/HK/28167 +WT/HK/28168 +WT/HK/28169 +WT/HK/28170 +WT/HK/28171 +WT/HK/28172 +WT/HK/28173 +WT/HK/28174 +WT/HK/28176 +WT/HK/28178 +WT/HK/28181 +WT/HK/28183 +WT/HK/28184 +WT/HK/28185 +WT/HK/28186 +WT/HK/28187 +WT/HK/28188 +WT/HK/28189 +WT/HK/28190 +WT/HK/28191 +WT/HK/28192 +WT/HK/28193 +WT/HK/28194 +WT/HK/28195 +WT/HK/28196 +WT/HK/28197 +WT/HK/28198 +WT/HK/28200 +WT/HK/28201 +WT/HK/28202 +WT/HK/28203 +WT/HK/28204 +WT/HK/28205 +WT/HK/28207 +WT/HK/28208 +WT/HK/28209 +WT/HK/28211 +WT/HK/28212 +WT/HK/28213 +WT/HK/28214 +WT/HK/28215 +WT/HK/28216 +WT/HK/28217 +WT/HK/28218 +WT/HK/28219 +WT/HK/28220 +WT/HK/28224 +WT/HK/28225 +WT/HK/28226 +WT/HK/28227 +WT/HK/28228 +WT/HK/28229 +WT/HK/28230 +WT/HK/28231 +WT/HK/28232 +WT/HK/28233 +WT/HK/28234 +WT/HK/28235 +WT/HK/28236 +WT/HK/28237 +WT/HK/28238 +WT/HK/28239 +WT/HK/28240 +WT/HK/28241 +WT/HK/28243 +WT/HK/28244 +WT/HK/28245 +WT/HK/28246 +WT/HK/28247 +WT/HK/28248 +WT/HK/28249 +WT/HK/28250 +WT/HK/28251 +WT/HK/28252 +WT/HK/28253 +WT/HK/28255 +WT/HK/28256 +WT/HK/28257 +WT/HK/28258 +WT/HK/28259 +WT/HK/28260 +WT/HK/28262 +WT/HK/28263 +WT/HK/28264 +WT/HK/28265 +WT/HK/28266 +WT/HK/28268 +WT/HK/28269 +WT/HK/28270 +WT/HK/28271 +WT/HK/28272 +WT/HK/28273 +WT/HK/28274 +WT/HK/28275 +WT/HK/28276 +WT/HK/28277 +WT/HK/28278 +WT/HK/28280 +WT/HK/28282 +WT/HK/28283 +WT/HK/28284 +WT/HK/28285 +WT/HK/28286 +WT/HK/28287 +WT/HK/28288 +WT/HK/28289 +WT/HK/28290 +WT/HK/28291 +WT/HK/28292 +WT/HK/28293 +WT/HK/28294 +WT/HK/28296 +WT/HK/28298 +WT/HK/28299 +WT/HK/28300 +WT/HK/28301 +WT/HK/28302 +WT/HK/28303 +WT/HK/28304 +WT/HK/28305 +WT/HK/28306 +WT/HK/28307 +WT/HK/28308 +WT/HK/28309 +WT/HK/28310 +WT/HK/28312 +WT/HK/28313 +WT/HK/28314 +WT/HK/28315 +WT/HK/28316 +WT/HK/28317 +WT/HK/28318 +WT/HK/28319 +WT/HK/28320 +WT/HK/28321 +WT/HK/28322 +WT/HK/28323 +WT/HK/28325 +WT/HK/28327 +WT/HK/28328 +WT/HK/28329 +WT/HK/28330 +WT/HK/28331 +WT/HK/28332 +WT/HK/28333 +WT/HK/28336 +WT/HK/28337 +WT/HK/28338 +WT/HK/28339 +WT/HK/28340 +WT/HK/28341 +WT/HK/28342 +WT/HK/28343 +WT/HK/28344 +WT/HK/28345 +WT/HK/28346 +WT/HK/28347 +WT/HK/28348 +WT/HK/28349 +WT/HK/28350 +WT/HK/28352 +WT/HK/28353 +WT/HK/28354 +WT/HK/28355 +WT/HK/28356 +WT/HK/28357 +WT/HK/28359 +WT/HK/28360 +WT/HK/28361 +WT/HK/28362 +WT/HK/28363 +WT/HK/28364 +WT/HK/28365 +WT/HK/28366 +WT/HK/28367 +WT/HK/28368 +WT/HK/28369 +WT/HK/28371 +WT/HK/28372 +WT/HK/28373 +WT/HK/28374 +WT/HK/28375 +WT/HK/28376 +WT/HK/28377 +WT/HK/28378 +WT/HK/28379 +WT/HK/28380 +WT/HK/28381 +WT/HK/28382 +WT/HK/28383 +WT/HK/28384 +WT/HK/28385 +WT/HK/28386 +WT/HK/28387 +WT/HK/28389 +WT/HK/28390 +WT/HK/28391 +WT/HK/28392 +WT/HK/28394 +WT/HK/28395 +WT/HK/28396 +WT/HK/28397 +WT/HK/28398 +WT/HK/28399 +WT/HK/28400 +WT/HK/28401 +WT/HK/28402 +WT/HK/28403 +WT/HK/28406 +WT/HK/28407 +WT/HK/28408 +WT/HK/28409 +WT/HK/28410 +WT/HK/28411 +WT/HK/28412 +WT/HK/28413 +WT/HK/28415 +WT/HK/28417 +WT/HK/28419 +WT/HK/28420 +WT/HK/28421 +WT/HK/28422 +WT/HK/28423 +WT/HK/28424 +WT/HK/28425 +WT/HK/28426 +WT/HK/28427 +WT/HK/28428 +WT/HK/28429 +WT/HK/28430 +WT/HK/28431 +WT/HK/28432 +WT/HK/28433 +WT/HK/28434 +WT/HK/28435 +WT/HK/28436 +WT/HK/28437 +WT/HK/28438 +WT/HK/28439 +WT/HK/28440 +WT/HK/28441 +WT/HK/28442 +WT/HK/28443 +WT/HK/28444 +WT/HK/28445 +WT/HK/28446 +WT/HK/28447 +WT/HK/28449 +WT/HK/28451 +WT/HK/28452 +WT/HK/28453 +WT/HK/28454 +WT/HK/28455 +WT/HK/28456 +WT/HK/28457 +WT/HK/28458 +WT/HK/28459 +WT/HK/28460 +WT/HK/28461 +WT/HK/28464 +WT/HK/28465 +WT/HK/28466 +WT/HK/28467 +WT/HK/28468 +WT/HK/28469 +WT/HK/28470 +WT/HK/28471 +WT/HK/28472 +WT/HK/28473 +WT/HK/28474 +WT/HK/28475 +WT/HK/28476 +WT/HK/28477 +WT/HK/28478 +WT/HK/28479 +WT/HK/28480 +WT/HK/28481 +WT/HK/28482 +WT/HK/28483 +WT/HK/28484 +WT/HK/28485 +WT/HK/28486 +WT/HK/28489 +WT/HK/28492 +WT/HK/28493 +WT/HK/28494 +WT/HK/28495 +WT/HK/28497 +WT/HK/28498 +WT/HK/28499 +WT/HK/28500 +WT/HK/28501 +WT/HK/28502 +WT/HK/28503 +WT/HK/28504 +WT/HK/28505 +WT/HK/28506 +WT/HK/28507 +WT/HK/28511 +WT/HK/28512 +WT/HK/28513 +WT/HK/28514 +WT/HK/28515 +WT/HK/28516 +WT/HK/28518 +WT/HK/28519 +WT/HK/28521 +WT/HK/28522 +WT/HK/28523 +WT/HK/28524 +WT/HK/28525 +WT/HK/28526 +WT/HK/28527 +WT/HK/28528 +WT/HK/28531 +WT/HK/28532 +WT/HK/28533 +WT/HK/28536 +WT/HK/28537 +WT/HK/28538 +WT/HK/28539 +WT/HK/28541 +WT/HK/28544 +WT/HK/28545 +WT/HK/28546 +WT/HK/28547 +WT/HK/28548 +WT/HK/28550 +WT/HK/28552 +WT/HK/28553 +WT/HK/28554 +WT/HK/28555 +WT/HK/28556 +WT/HK/28557 +WT/HK/28558 +WT/HK/28559 +WT/HK/28560 +WT/HK/28561 +WT/HK/28562 +WT/HK/28563 +WT/HK/28564 +WT/HK/28566 +WT/HK/28567 +WT/HK/28568 +WT/HK/28570 +WT/HK/28572 +WT/HK/28573 +WT/HK/28574 +WT/HK/28575 +WT/HK/28576 +WT/HK/28577 +WT/HK/28578 +WT/HK/28580 +WT/HK/28581 +WT/HK/28582 +WT/HK/28583 +WT/HK/28584 +WT/HK/28585 +WT/HK/28586 +WT/HK/28587 +WT/HK/28589 +WT/HK/28590 +WT/HK/28591 +WT/HK/28592 +WT/HK/28594 +WT/HK/28596 +WT/HK/28598 +WT/HK/28599 +WT/HK/28600 +WT/HK/28602 +WT/HK/28603 +WT/HK/28604 +WT/HK/28606 +WT/HK/28607 +WT/HK/28610 +WT/HK/28611 +WT/HK/28612 +WT/HK/28614 +WT/HK/28616 +WT/HK/28617 +WT/HK/28618 +WT/HK/28619 +WT/HK/28620 +WT/HK/28621 +WT/HK/28622 +WT/HK/28623 +WT/HK/28624 +WT/HK/28625 +WT/HK/28627 +WT/HK/28628 +WT/HK/28629 +WT/HK/28630 +WT/HK/28631 +WT/HK/28633 +WT/HK/28634 +WT/HK/28636 +WT/HK/28637 +WT/HK/28638 +WT/HK/28639 +WT/HK/28640 +WT/HK/28641 +WT/HK/28642 +WT/HK/28643 +WT/HK/28647 +WT/HK/28648 +WT/HK/28649 +WT/HK/28650 +WT/HK/28651 +WT/HK/28653 +WT/HK/28655 +WT/HK/28656 +WT/HK/28657 +WT/HK/28658 +WT/HK/28659 +WT/HK/28660 +WT/HK/28661 +WT/HK/28662 +WT/HK/28664 +WT/HK/28665 +WT/HK/28667 +WT/HK/28668 +WT/HK/28669 +WT/HK/28670 +WT/HK/28671 +WT/HK/28672 +WT/HK/28673 +WT/HK/28676 +WT/HK/28678 +WT/HK/28679 +WT/HK/28681 +WT/HK/28683 +WT/HK/28684 +WT/HK/28685 +WT/HK/28686 +WT/HK/28687 +WT/HK/28688 +WT/HK/28689 +WT/HK/28690 +WT/HK/28691 +WT/HK/28692 +WT/HK/28694 +WT/HK/28695 +WT/HK/28698 +WT/HK/28699 +WT/HK/28701 +WT/HK/28702 +WT/HK/28703 +WT/HK/28704 +WT/HK/28705 +WT/HK/28707 +WT/HK/28708 +WT/HK/28709 +WT/HK/28710 +WT/HK/28711 +WT/HK/28712 +WT/HK/28713 +WT/HK/28714 +WT/HK/28716 +WT/HK/28717 +WT/HK/28718 +WT/HK/28719 +WT/HK/28720 +WT/HK/28721 +WT/HK/28722 +WT/HK/28723 +WT/HK/28724 +WT/HK/28725 +WT/HK/28726 +WT/HK/28727 +WT/HK/28728 +WT/HK/28729 +WT/HK/28730 +WT/HK/28731 +WT/HK/28732 +WT/HK/28733 +WT/HK/28734 +WT/HK/28735 +WT/HK/28737 +WT/HK/28738 +WT/HK/28739 +WT/HK/28740 +WT/HK/28741 +WT/HK/28742 +WT/HK/28744 +WT/HK/28746 +WT/HK/28747 +WT/HK/28748 +WT/HK/28749 +WT/HK/28750 +WT/HK/28751 +WT/HK/28752 +WT/HK/28753 +WT/HK/28754 +WT/HK/28755 +WT/HK/28756 +WT/HK/28757 +WT/HK/28758 +WT/HK/28760 +WT/HK/28761 +WT/HK/28762 +WT/HK/28764 +WT/HK/28765 +WT/HK/28767 +WT/HK/28768 +WT/HK/28769 +WT/HK/28770 +WT/HK/28771 +WT/HK/28772 +WT/HK/28773 +WT/HK/28774 +WT/HK/28775 +WT/HK/28776 +WT/HK/28777 +WT/HK/28778 +WT/HK/28779 +WT/HK/28781 +WT/HK/28782 +WT/HK/28785 +WT/HK/28788 +WT/HK/28792 +WT/HK/28793 +WT/HK/28794 +WT/HK/28796 +WT/HK/28797 +WT/HK/28798 +WT/HK/28799 +WT/HK/28800 +WT/HK/28801 +WT/HK/28802 +WT/HK/28803 +WT/HK/28806 +WT/HK/28807 +WT/HK/28810 +WT/HK/28811 +WT/HK/28812 +WT/HK/28813 +WT/HK/28814 +WT/HK/28815 +WT/HK/28816 +WT/HK/28818 +WT/HK/28819 +WT/HK/28820 +WT/HK/28821 +WT/HK/28822 +WT/HK/28823 +WT/HK/28824 +WT/HK/28827 +WT/HK/28828 +WT/HK/28829 +WT/HK/28830 +WT/HK/28831 +WT/HK/28832 +WT/HK/28833 +WT/HK/28834 +WT/HK/28835 +WT/HK/28836 +WT/HK/28837 +WT/HK/28838 +WT/HK/28839 +WT/HK/28841 +WT/HK/28842 +WT/HK/28843 +WT/HK/28844 +WT/HK/28845 +WT/HK/28847 +WT/HK/28848 +WT/HK/28849 +WT/HK/28851 +WT/HK/28852 +WT/HK/28853 +WT/HK/28854 +WT/HK/28855 +WT/HK/28856 +WT/HK/28858 +WT/HK/28860 +WT/HK/28861 +WT/HK/28862 +WT/HK/28863 +WT/HK/28864 +WT/HK/28865 +WT/HK/28866 +WT/HK/28867 +WT/HK/28868 +WT/HK/28869 +WT/HK/28870 +WT/HK/28871 +WT/HK/28872 +WT/HK/28873 +WT/HK/28874 +WT/HK/28875 +WT/HK/28876 +WT/HK/28877 +WT/HK/28878 +WT/HK/28879 +WT/HK/28880 +WT/HK/28881 +WT/HK/28882 +WT/HK/28883 +WT/HK/28884 +WT/HK/28885 +WT/HK/28887 +WT/HK/28888 +WT/HK/28890 +WT/HK/28891 +WT/HK/28892 +WT/HK/28893 +WT/HK/28894 +WT/HK/28895 +WT/HK/28896 +WT/HK/28897 +WT/HK/28901 +WT/HK/28902 +WT/HK/28903 +WT/HK/28904 +WT/HK/28905 +WT/HK/28906 +WT/HK/28907 +WT/HK/28908 +WT/HK/28909 +WT/HK/28910 +WT/HK/28913 +WT/HK/28914 +WT/HK/28915 +WT/HK/28916 +WT/HK/28917 +WT/HK/28918 +WT/HK/28920 +WT/HK/28921 +WT/HK/28922 +WT/HK/28923 +WT/HK/28924 +WT/HK/28925 +WT/HK/28926 +WT/HK/28927 +WT/HK/28928 +WT/HK/28929 +WT/HK/28930 +WT/HK/28931 +WT/HK/28932 +WT/HK/28933 +WT/HK/28935 +WT/HK/28936 +WT/HK/28937 +WT/HK/28938 +WT/HK/28939 +WT/HK/28940 +WT/HK/28941 +WT/HK/28942 +WT/HK/28944 +WT/HK/28945 +WT/HK/28946 +WT/HK/28947 +WT/HK/28949 +WT/HK/28952 +WT/HK/28953 +WT/HK/28954 +WT/HK/28956 +WT/HK/28957 +WT/HK/28958 +WT/HK/28960 +WT/HK/28961 +WT/HK/28962 +WT/HK/28963 +WT/HK/28964 +WT/HK/28965 +WT/HK/28967 +WT/HK/28968 +WT/HK/28969 +WT/HK/28970 +WT/HK/28971 +WT/HK/28972 +WT/HK/28973 +WT/HK/28976 +WT/HK/28977 +WT/HK/28982 +WT/HK/28983 +WT/HK/28984 +WT/HK/28985 +WT/HK/28986 +WT/HK/28987 +WT/HK/28988 +WT/HK/28989 +WT/HK/28990 +WT/HK/28991 +WT/HK/28992 +WT/HK/28993 +WT/HK/28994 +WT/HK/28996 +WT/HK/28997 +WT/HK/28998 +WT/HK/28999 +WT/HK/29000 +WT/HK/29001 +WT/HK/29002 +WT/HK/29004 +WT/HK/29006 +WT/HK/29007 +WT/HK/29008 +WT/HK/29009 +WT/HK/29010 +WT/HK/29011 +WT/HK/29012 +WT/HK/29013 +WT/HK/29014 +WT/HK/29015 +WT/HK/29016 +WT/HK/29017 +WT/HK/29018 +WT/HK/29019 +WT/HK/29020 +WT/HK/29022 +WT/HK/29024 +WT/HK/29025 +WT/HK/29027 +WT/HK/29028 +WT/HK/29029 +WT/HK/29031 +WT/HK/29033 +WT/HK/29035 +WT/HK/29036 +WT/HK/29037 +WT/HK/29038 +WT/HK/29039 +WT/HK/29040 +WT/HK/29041 +WT/HK/29042 +WT/HK/29043 +WT/HK/29044 +WT/HK/29045 +WT/HK/29047 +WT/HK/29048 +WT/HK/29049 +WT/HK/29050 +WT/HK/29051 +WT/HK/29053 +WT/HK/29055 +WT/HK/29056 +WT/HK/29057 +WT/HK/29058 +WT/HK/29059 +WT/HK/29060 +WT/HK/29061 +WT/HK/29062 +WT/HK/29064 +WT/HK/29065 +WT/HK/29066 +WT/HK/29067 +WT/HK/29068 +WT/HK/29069 +WT/HK/29070 +WT/HK/29071 +WT/HK/29072 +WT/HK/29073 +WT/HK/29074 +WT/HK/29075 +WT/HK/29076 +WT/HK/29077 +WT/HK/29078 +WT/HK/29079 +WT/HK/29080 +WT/HK/29082 +WT/HK/29083 +WT/HK/29084 +WT/HK/29085 +WT/HK/29086 +WT/HK/29087 +WT/HK/29088 +WT/HK/29089 +WT/HK/29090 +WT/HK/29091 +WT/HK/29093 +WT/HK/29095 +WT/HK/29096 +WT/HK/29097 +WT/HK/29098 +WT/HK/29099 +WT/HK/29100 +WT/HK/29101 +WT/HK/29102 +WT/HK/29104 +WT/HK/29105 +WT/HK/29106 +WT/HK/29107 +WT/HK/29108 +WT/HK/29109 +WT/HK/29110 +WT/HK/29111 +WT/HK/29112 +WT/HK/29113 +WT/HK/29114 +WT/HK/29115 +WT/HK/29116 +WT/HK/29118 +WT/HK/29120 +WT/HK/29121 +WT/HK/29122 +WT/HK/29123 +WT/HK/29125 +WT/HK/29126 +WT/HK/29127 +WT/HK/29128 +WT/HK/29129 +WT/HK/29131 +WT/HK/29132 +WT/HK/29133 +WT/HK/29134 +WT/HK/29135 +WT/HK/29136 +WT/HK/29138 +WT/HK/29139 +WT/HK/29141 +WT/HK/29142 +WT/HK/29143 +WT/HK/29144 +WT/HK/29145 +WT/HK/29146 +WT/HK/29147 +WT/HK/29148 +WT/HK/29149 +WT/HK/29151 +WT/HK/29152 +WT/HK/29153 +WT/HK/29154 +WT/HK/29155 +WT/HK/29156 +WT/HK/29158 +WT/HK/29159 +WT/HK/29160 +WT/HK/29161 +WT/HK/29162 +WT/HK/29163 +WT/HK/29164 +WT/HK/29165 +WT/HK/29166 +WT/HK/29167 +WT/HK/29168 +WT/HK/29169 +WT/HK/29170 +WT/HK/29172 +WT/HK/29173 +WT/HK/29175 +WT/HK/29176 +WT/HK/29177 +WT/HK/29178 +WT/HK/29179 +WT/HK/29180 +WT/HK/29181 +WT/HK/29182 +WT/HK/29183 +WT/HK/29184 +WT/HK/29185 +WT/HK/29186 +WT/HK/29187 +WT/HK/29188 +WT/HK/29189 +WT/HK/29190 +WT/HK/29191 +WT/HK/29192 +WT/HK/29194 +WT/HK/29195 +WT/HK/29196 +WT/HK/29198 +WT/HK/29200 +WT/HK/29201 +WT/HK/29202 +WT/HK/29203 +WT/HK/29205 +WT/HK/29206 +WT/HK/29207 +WT/HK/29208 +WT/HK/29210 +WT/HK/29211 +WT/HK/29212 +WT/HK/29213 +WT/HK/29214 +WT/HK/29216 +WT/HK/29218 +WT/HK/29219 +WT/HK/29220 +WT/HK/29221 +WT/HK/29223 +WT/HK/29224 +WT/HK/29225 +WT/HK/29226 +WT/HK/29228 +WT/HK/29229 +WT/HK/29230 +WT/HK/29231 +WT/HK/29232 +WT/HK/29236 +WT/HK/29237 +WT/HK/29238 +WT/HK/29239 +WT/HK/29240 +WT/HK/29241 +WT/HK/29242 +WT/HK/29243 +WT/HK/29244 +WT/HK/29246 +WT/HK/29247 +WT/HK/29248 +WT/HK/29249 +WT/HK/29250 +WT/HK/29251 +WT/HK/29254 +WT/HK/29255 +WT/HK/29256 +WT/HK/29257 +WT/HK/29258 +WT/HK/29354 +WT/HK/29369 +WT/HK/29371 +WT/HK/29383 +WT/HK/29388 +WT/HK/29396 +WT/HK/29397 +WT/HK/29398 +WT/HK/29400 +WT/HK/29406 +WT/HK/29410 +WT/HK/29416 +WT/HK/29422 +WT/HK/29424 +WT/HK/29433 +WT/HK/29449 +WT/HK/29553 +WT/HK/29574 +WT/HK/29583 +WT/HK/29600 +WT/HK/29601 +WT/HK/29605 +WT/HK/29613 +WT/HK/29655 +WT/HK/29658 +WT/HK/29659 +WT/HK/29663 +WT/HK/29670 +WT/HK/29674 +WT/HK/29684 +WT/HK/29697 +WT/HK/29738 +WT/HK/29749 +WT/HK/29756 +WT/HK/29757 +WT/HK/29763 +WT/HK/29782 +WT/HK/29806 +WT/HK/29815 +WT/HK/29827 +WT/HK/29838 +WT/HK/29856 +WT/HK/29866 +WT/HK/29868 +WT/HK/29896 +WT/HK/29905 +WT/HK/29908 +WT/HK/29920 +WT/HK/29926 +WT/HK/29927 +WT/HK/29930 +WT/HK/29941 +WT/HK/47364 +WT/HK/47503 +WT/HK/47582 +WT/HK/47586 +WT/HK/47591 +WT/HK/47759 +WT/HK/47761 +WT/HK/47796 +WT/HK/47858 +WT/HK/47859 +WT/HK/47957 +WT/HK/47968 +WT/HK/48009 +WT/HK/48010 +WT/HK/48135 +WT/HK/48136 +WT/HK/48137 +WT/HK/48138 +WT/HK/48157 +WT/HK/48263 +WT/HK/48392 +WT/HK/48397 +WT/HK/48469 +WT/HK/48475 +WT/HK/48477 +WT/HK/48656 +WT/HK/48668 +WT/HK/48678 +WT/HK/48711 +WT/HK/48717 +WT/HK/48753 +WT/HK/48756 +WT/HK/48764 +WT/HK/48767 +WT/HK/48773 +WT/HK/48775 +WT/HK/48776 +WT/HK/48777 +WT/HK/48783 +WT/HK/48785 +WT/HK/48788 +WT/HK/48789 +WT/HK/48790 +WT/HK/49501 +WT/HK/49505 +WT/HK/49509 +WT/HK/49510 +WT/HK/49511 +WT/HK/49513 +WT/HK/49514 +WT/HK/49515 +WT/HK/49517 +WT/HK/49518 +WT/HK/49522 +WT/HK/49523 +WT/HK/49524 +WT/HK/49525 +WT/HK/49527 +WT/HK/49530 +WT/HK/49535 +WT/HK/49537 +WT/HK/49539 +WT/HK/49541 +WT/HK/49546 +WT/HK/49549 +WT/HK/49550 +WT/HK/49551 +WT/HK/49553 +WT/HK/49554 +WT/HK/49556 +WT/HK/49557 +WT/HK/49558 +WT/HK/49559 +WT/HK/49560 +WT/HK/49561 +WT/HK/49562 +WT/HK/49563 +WT/HK/49564 +WT/HK/49565 +WT/HK/49566 +WT/HK/49567 +WT/HK/49568 +WT/HK/49569 +WT/HK/49570 +WT/HK/49571 +WT/HK/49572 +WT/HK/49573 +WT/HK/49574 +WT/HK/49575 +WT/HK/49576 +WT/HK/49577 +WT/HK/49578 +WT/HK/49579 +WT/HK/49580 +WT/HK/49581 +WT/HK/49582 +WT/HK/49583 +WT/HK/49584 +WT/HK/49585 +WT/HK/49586 +WT/HK/49587 +WT/HK/49588 +WT/HK/49589 +WT/HK/49590 +WT/HK/49591 +WT/HK/49592 +WT/HK/49593 +WT/HK/49594 +WT/HK/49595 +WT/HK/49596 +WT/HK/49597 +WT/HK/49598 +WT/HK/49599 +WT/HK/49600 +WT/HK/49601 +WT/HK/49602 +WT/HK/49603 +WT/HK/49604 +WT/HK/49605 +WT/HK/49606 +WT/HK/49607 +WT/HK/49608 +WT/HK/49609 +WT/HK/49610 +WT/HK/49611 +WT/HK/49612 +WT/HK/49613 +WT/HK/49614 +WT/HK/49615 +WT/HK/49616 +WT/HK/49617 +WT/HK/49618 +WT/HK/49619 +WT/HK/49620 +WT/HK/49621 +WT/HK/49622 +WT/HK/49623 +WT/HK/49624 +WT/HK/49625 +WT/HK/49626 +WT/HK/49627 +WT/HK/49628 +WT/HK/49629 +WT/HK/49630 +WT/HK/49631 +WT/HK/49773 +WT/HK/49777 +WT/HK/49789 +WT/HK/49791 +WT/HK/49795 +WT/HK/49796 +WT/HK/49803 +WT/HK/49805 +WT/HK/49807 +WT/HK/49810 +WT/HK/49813 +WT/HK/49821 +WT/HK/49824 +WT/HK/49826 +WT/HK/49829 +WT/HK/49831 +WT/HK/49833 +WT/HK/49835 +WT/HK/49836 +WT/HK/49837 +WT/HK/49838 +WT/HK/49847 +WT/HK/49851 +WT/HK/49852 +WT/HK/49855 +WT/HK/49857 +WT/HK/49858 +WT/HK/49860 +WT/HK/49862 +WT/HK/49863 +WT/HK/49865 +WT/HK/49866 +WT/HK/49868 +WT/HK/49869 +WT/HK/49870 +WT/HK/49873 +WT/HK/49874 +WT/HK/49882 +WT/HK/49887 +WT/HK/49892 +WT/HK/49895 +WT/HK/49896 +WT/HK/49925 +WT/HK/49926 +WT/HK/49928 +WT/HK/49936 +WT/HK/49942 +WT/HK/49946 +WT/HK/49950 +WT/HK/49951 +WT/HK/49952 +WT/HK/49954 +WT/HK/49956 +WT/HK/49962 +WT/HK/49970 +WT/HK/49981 +WT/HK/49982 +WT/HK/49983 +WT/HK/49984 +WT/HK/49985 +WT/HK/49986 +WT/HK/49988 +WT/HK/49991 +WT/HK/49993 +WT/HK/50006 +WT/HK/50008 +WT/HK/50010 +WT/HK/50016 +WT/HK/50018 +WT/HK/50045 +WT/HK/50048 +WT/HK/50050 +WT/HK/50051 +WT/HK/50052 +WT/HK/50053 +WT/HK/50057 +WT/HK/50058 +WT/HK/50059 +WT/HK/50060 +WT/HK/50063 +WT/HK/50086 +WT/HK/50099 +WT/HK/50103 +WT/HK/50106 +WT/HK/50114 +WT/HK/50115 +WT/HK/50116 +WT/HK/50131 +WT/HK/50132 +WT/HK/50134 +WT/HK/50136 +WT/HK/50137 +WT/HK/50139 +WT/HK/50140 +WT/HK/50141 +WT/HK/50168 +WT/HK/50169 +WT/HK/50170 +WT/HK/50171 +WT/HK/50175 +WT/HK/50177 +WT/HK/50196 +WT/HK/50205 +WT/HK/50206 +WT/HK/50234 +WT/HK/50266 +WT/HK/50272 +WT/HK/50276 +WT/HK/50277 +WT/HK/50289 +WT/HK/50290 +WT/HK/50292 +WT/HK/50293 +WT/HK/50294 +WT/HK/50316 +WT/HK/50325 +WT/HK/50330 +WT/HK/50347 +WT/HK/50379 +WT/HK/50384 +WT/HK/50385 +WT/HK/50392 +WT/HK/50400 +WT/HK/50401 +WT/HK/50402 +WT/HK/50403 +WT/HK/50404 +WT/HK/50405 +WT/HK/50411 +WT/HK/50429 +WT/HK/50430 +WT/HK/50432 +WT/HK/50446 +WT/HK/50447 +WT/HK/50453 +WT/HK/50456 +WT/HK/50461 +WT/HK/50463 +WT/HK/50466 +WT/HK/50473 +WT/HK/50482 +WT/HK/50488 +WT/HK/50489 +WT/HK/50490 +WT/HK/50491 +WT/HK/50496 +WT/HK/50503 +WT/HK/50504 +WT/HK/50505 +WT/HK/50514 +WT/HK/50515 +WT/HK/50518 +WT/HK/50522 +WT/HK/50523 +WT/HK/50547 +WT/HK/50556 +WT/HK/50562 +WT/HK/50570 +WT/HK/50584 +WT/HK/50599 +WT/HK/50624 +WT/HK/50626 +WT/HK/50627 +WT/HK/50648 +WT/HK/50649 +WT/HK/50671 +WT/HK/50672 +WT/HK/50673 +WT/HK/50677 +WT/HK/50685 +WT/HK/50688 +WT/HK/50689 +WT/HK/50699 +WT/HK/50702 +WT/HK/50706 +WT/HK/50720 +WT/HK/50754 +WT/HK/50756 +WT/HK/50758 +WT/HK/50771 +WT/HK/50772 +WT/HK/50785 +WT/HK/50802 +WT/HK/50826 +WT/HK/50827 +WT/HK/50842 +WT/HK/50843 +WT/HK/50852 +WT/HK/50863 +WT/HK/50867 +WT/HK/50870 +WT/HK/50871 +WT/HK/50890 +WT/HK/50907 +WT/HK/50914 +WT/HK/50933 +WT/HK/50935 +WT/HK/50936 +WT/HK/50937 +WT/HK/50938 +WT/HK/50940 +WT/HK/50941 +WT/HK/50949 +WT/HK/50957 +WT/HK/50973 +WT/HK/50988 +WT/HK/50989 +WT/HK/51002 +WT/HK/51003 +WT/HK/51005 +WT/HK/51006 +WT/HK/51021 +WT/HK/51030 +WT/HK/51036 +WT/HK/51051 +WT/HK/51052 +WT/HK/51073 +WT/HK/51085 +WT/HK/51088 +WT/HK/51121 +WT/HK/51129 +WT/HK/51137 +WT/HK/51152 +WT/HK/51167 +WT/HK/51171 +WT/HK/51172 +WT/HK/51176 +WT/HK/51224 +WT/HK/51227 +WT/HK/51265 +WT/HK/51267 +WT/HK/51270 +WT/HK/51275 +WT/HK/51346 +WT/HK/51373 +WT/HK/51374 +WT/HK/51391 +WT/HK/51419 +WT/HK/51422 +WT/HK/51447 +WT/HK/51449 +WT/HK/51535 +WT/HK/51554 +WT/HK/51561 +WT/HK/51581 +WT/HK/51602 +WT/HK/51613 +WT/HK/51615 +WT/HK/51622 +WT/HK/51627 +WT/HK/51644 +WT/HK/51657 +WT/HK/51666 +WT/HK/51678 +WT/HK/51833 +WT/HK/51911 +WT/HK/51980 +WT/HK/51984 +WT/HK/51993 +WT/HK/52422 +WT/HK/52450 +WT/HK/52532 +WT/HK/52539 +WT/HK/52559 +WT/HK/52660 +WT/HK/52759 +WT/HK/52809 +WT/HK/52888 +WT/HK/52891 +WT/HK/52942 +WT/HK/53000 +WT/HK/53002 +WT/HK/53003 +WT/HK/53004 +WT/HK/53005 +WT/HK/53008 +WT/HK/53009 +WT/HK/53010 +WT/HK/53011 +WT/HK/53012 +WT/HK/53014 +WT/HK/53015 +WT/HK/53019 +WT/HK/53020 +WT/HK/53021 +WT/HK/53022 +WT/HK/53023 +WT/HK/53024 +WT/HK/53026 +WT/HK/53027 +WT/HK/53030 +WT/HK/53031 +WT/HK/53033 +WT/HK/53038 +WT/HK/53039 +WT/HK/53040 +WT/HK/53041 +WT/HK/53046 +WT/HK/53050 +WT/HK/53053 +WT/HK/53054 +WT/HK/53055 +WT/HK/53056 +WT/HK/53057 +WT/HK/53058 +WT/HK/53059 +WT/HK/53062 +WT/HK/53063 +WT/HK/53070 +WT/HK/53072 +WT/HK/53074 +WT/HK/53079 +WT/HK/53081 +WT/HK/53083 +WT/HK/53088 +WT/HK/53089 +WT/HK/53090 +WT/HK/53091 +WT/HK/53092 +WT/HK/53093 +WT/HK/53094 +WT/HK/53095 +WT/HK/53096 +WT/HK/53097 +WT/HK/53099 +WT/HK/53101 +WT/HK/53106 +WT/HK/53110 +WT/HK/53111 +WT/HK/53114 +WT/HK/53116 +WT/HK/53117 +WT/HK/53118 +WT/HK/53120 +WT/HK/53123 +WT/HK/53125 +WT/HK/53126 +WT/HK/53127 +WT/HK/53129 +WT/HK/53130 +WT/HK/53133 +WT/HK/53134 +WT/HK/53138 +WT/HK/53146 +WT/HK/53148 +WT/HK/53149 +WT/HK/53150 +WT/HK/53151 +WT/HK/53152 +WT/HK/53154 +WT/HK/53155 +WT/HK/53156 +WT/HK/53158 +WT/HK/53159 +WT/HK/53161 +WT/HK/53165 +WT/HK/53166 +WT/HK/53168 +WT/HK/53174 +WT/HK/53176 +WT/HK/53180 +WT/HK/53182 +WT/HK/53183 +WT/HK/53184 +WT/HK/53185 +WT/HK/53187 +WT/HK/53188 +WT/HK/53189 +WT/HK/53190 +WT/HK/53194 +WT/HK/53196 +WT/HK/53197 +WT/HK/53199 +WT/HK/53200 +WT/HK/53204 +WT/HK/53205 +WT/HK/53206 +WT/HK/53213 +WT/HK/53215 +WT/HK/53216 +WT/HK/53219 +WT/HK/53226 +WT/HK/53228 +WT/HK/53233 +WT/HK/53234 +WT/HK/53235 +WT/HK/53238 +WT/HK/53239 +WT/HK/53240 +WT/HK/53241 +WT/HK/53242 +WT/HK/53245 +WT/HK/53246 +WT/HK/53247 +WT/HK/53248 +WT/HK/53249 +WT/HK/53255 +WT/HK/53262 +WT/HK/53263 +WT/HK/53267 +WT/HK/53270 +WT/HK/53273 +WT/HK/53274 +WT/HK/53276 +WT/HK/53281 +WT/HK/53283 +WT/HK/53284 +WT/HK/53285 +WT/HK/53286 +WT/HK/53290 +WT/HK/53292 +WT/HK/53293 +WT/HK/53295 +WT/HK/53297 +WT/HK/53298 +WT/HK/53299 +WT/HK/53300 +WT/HK/53301 +WT/HK/53302 +WT/HK/53303 +WT/HK/53304 +WT/HK/53313 +WT/HK/53315 +WT/HK/53318 +WT/HK/53319 +WT/HK/53320 +WT/HK/53323 +WT/HK/53324 +WT/HK/53325 +WT/HK/53327 +WT/HK/53328 +WT/HK/53329 +WT/HK/53330 +WT/HK/53331 +WT/HK/53332 +WT/HK/53333 +WT/HK/53334 +WT/HK/53335 +WT/HK/53336 +WT/HK/53340 +WT/HK/53341 +WT/HK/53345 +WT/HK/53346 +WT/HK/53348 +WT/HK/53349 +WT/HK/53350 +WT/HK/53355 +WT/HK/53356 +WT/HK/53359 +WT/HK/53363 +WT/HK/53369 +WT/HK/53370 +WT/HK/53371 +WT/HK/53374 +WT/HK/53375 +WT/HK/53378 +WT/HK/53379 +WT/HK/53381 +WT/HK/53384 +WT/HK/53386 +WT/HK/53388 +WT/HK/53389 +WT/HK/53390 +WT/HK/53394 +WT/HK/53398 +WT/HK/53403 +WT/HK/53405 +WT/HK/53406 +WT/HK/53411 +WT/HK/53412 +WT/HK/53413 +WT/HK/53417 +WT/HK/53418 +WT/HK/53419 +WT/HK/53420 +WT/HK/53422 +WT/HK/53429 +WT/HK/53430 +WT/HK/53431 +WT/HK/53432 +WT/HK/53433 +WT/HK/53435 +WT/HK/53436 +WT/HK/53437 +WT/HK/53439 +WT/HK/53440 +WT/HK/53441 +WT/HK/53443 +WT/HK/53444 +WT/HK/53445 +WT/HK/53448 +WT/HK/53449 +WT/HK/53450 +WT/HK/53452 +WT/HK/53453 +WT/HK/53454 +WT/HK/53457 +WT/HK/53462 +WT/HK/53465 +WT/HK/53472 +WT/HK/53473 +WT/HK/53474 +WT/HK/53477 +WT/HK/53478 +WT/HK/53486 +WT/HK/53487 +WT/HK/53488 +WT/HK/53489 +WT/HK/53490 +WT/HK/53491 +WT/HK/53492 +WT/HK/53497 +WT/HK/53498 +WT/HK/53503 +WT/HK/53511 +WT/HK/53513 +WT/HK/53514 +WT/HK/53517 +WT/HK/53520 +WT/HK/53525 +WT/HK/53537 +WT/HK/53548 +WT/HK/53549 +WT/HK/53550 +WT/HK/53561 +WT/HK/53566 +WT/HK/53568 +WT/HK/53570 +WT/HK/53572 +WT/HK/53574 +WT/HK/53575 +WT/HK/53581 +WT/HK/53588 +WT/HK/53589 +WT/HK/53592 +WT/HK/53593 +WT/HK/53596 +WT/HK/53604 +WT/HK/53605 +WT/HK/53607 +WT/HK/53610 +WT/HK/53611 +WT/HK/53612 +WT/HK/53622 +WT/HK/53626 +WT/HK/53629 +WT/HK/53630 +WT/HK/53636 +WT/HK/53640 +WT/HK/53641 +WT/HK/53656 +WT/HK/53657 +WT/HK/53659 +WT/HK/53660 +WT/HK/53662 +WT/HK/53665 +WT/HK/53666 +WT/HK/53672 +WT/HK/53678 +WT/HK/53685 +WT/HK/53686 +WT/HK/53690 +WT/HK/53691 +WT/HK/53693 +WT/HK/53694 +WT/HK/53695 +WT/HK/53696 +WT/HK/53699 +WT/HK/53701 +WT/HK/53704 +WT/HK/53705 +WT/HK/53706 +WT/HK/53712 +WT/HK/53714 +WT/HK/53715 +WT/HK/53718 +WT/HK/53730 +WT/HK/53731 +WT/HK/53732 +WT/HK/53733 +WT/HK/53734 +WT/HK/53736 +WT/HK/53737 +WT/HK/53740 +WT/HK/53742 +WT/HK/53743 +WT/HK/53744 +WT/HK/53745 +WT/HK/53749 +WT/HK/53753 +WT/HK/53758 +WT/HK/53760 +WT/HK/53762 +WT/HK/53763 +WT/HK/53764 +WT/HK/53767 +WT/HK/53770 +WT/HK/53773 +WT/HK/53774 +WT/HK/53777 +WT/HK/53778 +WT/HK/53780 +WT/HK/53786 +WT/HK/53791 +WT/HK/53793 +WT/HK/53796 +WT/HK/53799 +WT/HK/53800 +WT/HK/53801 +WT/HK/53802 +WT/HK/53804 +WT/HK/53807 +WT/HK/53821 +WT/HK/53823 +WT/HK/53827 +WT/HK/53830 +WT/HK/53832 +WT/HK/53833 +WT/HK/53834 +WT/HK/53835 +WT/HK/53837 +WT/HK/53842 +WT/HK/53843 +WT/HK/53846 +WT/HK/53853 +WT/HK/53854 +WT/HK/53858 +WT/HK/53859 +WT/HK/53861 +WT/HK/53862 +WT/HK/53864 +WT/HK/53870 +WT/HK/53873 +WT/HK/53874 +WT/HK/53878 +WT/HK/53881 +WT/HK/53883 +WT/HK/53889 +WT/HK/53890 +WT/HK/53891 +WT/HK/53893 +WT/HK/53899 +WT/HK/53900 +WT/HK/53906 +WT/HK/53908 +WT/HK/53919 +WT/HK/53921 +WT/HK/53922 +WT/HK/53923 +WT/HK/53925 +WT/HK/53927 +WT/HK/53928 +WT/HK/53937 +WT/HK/53938 +WT/HK/53939 +WT/HK/53941 +WT/HK/53942 +WT/HK/53943 +WT/HK/53947 +WT/HK/53949 +WT/HK/53951 +WT/HK/53952 +WT/HK/53954 +WT/HK/53958 +WT/HK/53959 +WT/HK/53961 +WT/HK/53965 +WT/HK/53969 +WT/HK/53971 +WT/HK/53979 +WT/HK/53980 +WT/HK/53981 +WT/HK/53984 +WT/HK/53989 +WT/HK/53993 +WT/HK/53994 +WT/HK/53998 +WT/HK/53999 +WT/HK/54000 +WT/HK/54002 +WT/HK/54004 +WT/HK/54012 +WT/HK/54013 +WT/HK/54015 +WT/HK/54016 +WT/HK/54017 +WT/HK/54019 +WT/HK/54021 +WT/HK/54022 +WT/HK/54026 +WT/HK/54029 +WT/HK/54034 +WT/HK/54038 +WT/HK/54041 +WT/HK/54042 +WT/HK/54046 +WT/HK/54049 +WT/HK/54050 +WT/HK/54053 +WT/HK/54054 +WT/HK/54058 +WT/HK/54060 +WT/HK/54063 +WT/HK/54064 +WT/HK/54065 +WT/HK/54069 +WT/HK/54070 +WT/HK/54073 +WT/HK/54075 +WT/HK/54076 +WT/HK/54079 +WT/HK/54080 +WT/HK/54082 +WT/HK/54084 +WT/HK/54093 +WT/HK/54101 +WT/HK/54102 +WT/HK/54112 +WT/HK/54114 +WT/HK/54115 +WT/HK/54119 +WT/HK/54123 +WT/HK/54135 +WT/HK/54140 +WT/HK/54146 +WT/HK/54151 +WT/HK/54153 +WT/HK/54155 +WT/HK/54156 +WT/HK/54157 +WT/HK/54158 +WT/HK/54159 +WT/HK/54160 +WT/HK/54161 +WT/HK/54162 +WT/HK/54163 +WT/HK/54164 +WT/HK/54166 +WT/HK/54167 +WT/HK/54168 +WT/HK/54169 +WT/HK/54170 +WT/HK/54171 +WT/HK/54172 +WT/HK/54173 +WT/HK/54174 +WT/HK/54175 +WT/HK/54178 +WT/HK/54179 +WT/HK/54181 +WT/HK/54182 +WT/HK/54183 +WT/HK/54184 +WT/HK/54186 +WT/HK/54187 +WT/HK/54188 +WT/HK/54190 +WT/HK/54192 +WT/HK/54193 +WT/HK/54196 +WT/HK/54197 +WT/HK/54198 +WT/HK/54199 +WT/HK/54200 +WT/HK/54201 +WT/HK/54204 +WT/HK/54205 +WT/HK/54206 +WT/HK/54207 +WT/HK/54208 +WT/HK/54210 +WT/HK/54212 +WT/HK/54213 +WT/HK/54218 +WT/HK/54219 +WT/HK/54221 +WT/HK/54222 +WT/HK/54223 +WT/HK/54224 +WT/HK/54225 +WT/HK/54226 +WT/HK/54228 +WT/HK/54229 +WT/HK/54232 +WT/HK/54233 +WT/HK/54235 +WT/HK/54236 +WT/HK/54239 +WT/HK/54240 +WT/HK/54241 +WT/HK/54242 +WT/HK/54244 +WT/HK/54245 +WT/HK/54248 +WT/HK/54250 +WT/HK/54251 +WT/HK/54252 +WT/HK/54253 +WT/HK/54254 +WT/HK/54257 +WT/HK/54258 +WT/HK/54259 +WT/HK/54260 +WT/HK/54261 +WT/HK/54262 +WT/HK/54265 +WT/HK/54266 +WT/HK/54267 +WT/HK/54268 +WT/HK/54269 +WT/HK/54270 +WT/HK/54271 +WT/HK/54272 +WT/HK/54273 +WT/HK/54274 +WT/HK/54276 +WT/HK/54277 +WT/HK/54278 +WT/HK/54279 +WT/HK/54281 +WT/HK/54283 +WT/HK/54284 +WT/HK/54285 +WT/HK/54288 +WT/HK/54289 +WT/HK/54291 +WT/HK/54293 +WT/HK/54294 +WT/HK/54295 +WT/HK/54296 +WT/HK/54297 +WT/HK/54299 +WT/HK/54300 +WT/HK/54301 +WT/HK/54302 +WT/HK/54303 +WT/HK/54304 +WT/HK/54307 +WT/HK/54309 +WT/HK/54310 +WT/HK/54312 +WT/HK/54313 +WT/HK/54318 +WT/HK/54319 +WT/HK/54320 +WT/HK/54321 +WT/HK/54322 +WT/HK/54323 +WT/HK/54324 +WT/HK/54325 +WT/HK/54326 +WT/HK/54327 +WT/HK/54328 +WT/HK/54329 +WT/HK/54331 +WT/HK/54333 +WT/HK/54334 +WT/HK/54336 +WT/HK/54337 +WT/HK/54340 +WT/HK/54342 +WT/HK/54343 +WT/HK/54344 +WT/HK/54345 +WT/HK/54346 +WT/HK/54347 +WT/HK/54348 +WT/HK/54349 +WT/HK/54351 +WT/HK/54352 +WT/HK/54353 +WT/HK/54354 +WT/HK/54355 +WT/HK/54356 +WT/HK/54358 +WT/HK/54360 +WT/HK/54362 +WT/HK/54365 +WT/HK/54366 +WT/HK/54367 +WT/HK/54368 +WT/HK/54370 +WT/HK/54371 +WT/HK/54373 +WT/HK/54374 +WT/HK/54375 +WT/HK/54376 +WT/HK/54379 +WT/HK/54380 +WT/HK/54382 +WT/HK/54383 +WT/HK/54384 +WT/HK/54387 +WT/HK/54390 +WT/HK/54391 +WT/HK/54392 +WT/HK/54393 +WT/HK/54394 +WT/HK/54397 +WT/HK/54402 +WT/HK/54403 +WT/HK/54404 +WT/HK/54405 +WT/HK/54406 +WT/HK/54407 +WT/HK/54408 +WT/HK/54411 +WT/HK/54412 +WT/HK/54413 +WT/HK/54414 +WT/HK/54415 +WT/HK/54417 +WT/HK/54418 +WT/HK/54419 +WT/HK/54422 +WT/HK/54423 +WT/HK/54424 +WT/HK/54426 +WT/HK/54427 +WT/HK/54428 +WT/HK/54430 +WT/HK/54431 +WT/HK/54432 +WT/HK/54433 +WT/HK/54434 +WT/HK/54435 +WT/HK/54436 +WT/HK/54437 +WT/HK/54438 +WT/HK/54439 +WT/HK/54440 +WT/HK/54441 +WT/HK/54442 +WT/HK/54443 +WT/HK/54444 +WT/HK/54445 +WT/HK/54446 +WT/HK/54448 +WT/HK/54450 +WT/HK/54451 +WT/HK/54452 +WT/HK/54453 +WT/HK/54455 +WT/HK/54456 +WT/HK/54459 +WT/HK/54460 +WT/HK/54461 +WT/HK/54465 +WT/HK/54466 +WT/HK/54472 +WT/HK/54474 +WT/HK/54475 +WT/HK/54476 +WT/HK/54481 +WT/HK/54482 +WT/HK/54483 +WT/HK/54484 +WT/HK/54485 +WT/HK/54486 +WT/HK/54487 +WT/HK/54488 +WT/HK/54489 +WT/HK/54490 +WT/HK/54491 +WT/HK/54492 +WT/HK/54493 +WT/HK/54496 +WT/HK/54498 +WT/HK/54500 +WT/HK/54501 +WT/HK/54502 +WT/HK/54503 +WT/HK/54504 +WT/HK/54505 +WT/HK/54506 +WT/HK/54508 +WT/HK/54509 +WT/HK/54510 +WT/HK/54511 +WT/HK/54512 +WT/HK/54514 +WT/HK/54516 +WT/HK/54517 +WT/HK/54518 +WT/HK/54519 +WT/HK/54520 +WT/HK/54522 +WT/HK/54523 +WT/HK/54524 +WT/HK/54525 +WT/HK/54526 +WT/HK/54529 +WT/HK/54530 +WT/HK/54531 +WT/HK/54532 +WT/HK/54533 +WT/HK/54537 +WT/HK/54538 +WT/HK/54539 +WT/HK/54540 +WT/HK/54541 +WT/HK/54542 +WT/HK/54543 +WT/HK/54544 +WT/HK/54545 +WT/HK/54546 +WT/HK/54547 +WT/HK/54548 +WT/HK/54549 +WT/HK/54550 +WT/HK/54551 +WT/HK/54552 +WT/HK/54554 +WT/HK/54555 +WT/HK/54557 +WT/HK/54558 +WT/HK/54559 +WT/HK/54560 +WT/HK/54561 +WT/HK/54562 +WT/HK/54563 +WT/HK/54564 +WT/HK/54565 +WT/HK/54566 +WT/HK/54568 +WT/HK/54569 +WT/HK/54570 +WT/HK/54571 +WT/HK/54577 +WT/HK/54578 +WT/HK/54579 +WT/HK/54580 +WT/HK/54581 +WT/HK/54586 +WT/HK/54588 +WT/HK/54591 +WT/HK/54592 +WT/HK/54593 +WT/HK/54594 +WT/HK/54595 +WT/HK/54596 +WT/HK/54597 +WT/HK/54598 +WT/HK/54599 +WT/HK/54600 +WT/HK/54601 +WT/HK/54602 +WT/HK/54603 +WT/HK/54604 +WT/HK/54605 +WT/HK/54607 +WT/HK/54608 +WT/HK/54609 +WT/HK/54610 +WT/HK/54611 +WT/HK/54612 +WT/HK/54613 +WT/HK/54614 +WT/HK/54615 +WT/HK/54618 +WT/HK/54620 +WT/HK/54622 +WT/HK/54627 +WT/HK/54630 +WT/HK/54632 +WT/HK/54633 +WT/HK/54634 +WT/HK/54635 +WT/HK/54636 +WT/HK/54637 +WT/HK/54639 +WT/HK/54645 +WT/HK/54646 +WT/HK/54647 +WT/HK/54648 +WT/HK/54649 +WT/HK/54650 +WT/HK/54651 +WT/HK/54652 +WT/HK/54653 +WT/HK/54654 +WT/HK/54655 +WT/HK/54658 +WT/HK/54659 +WT/HK/54661 +WT/HK/54662 +WT/HK/54663 +WT/HK/54664 +WT/HK/54665 +WT/HK/54666 +WT/HK/54667 +WT/HK/54668 +WT/HK/54669 +WT/HK/54670 +WT/HK/54674 +WT/HK/54675 +WT/HK/54676 +WT/HK/54677 +WT/HK/54679 +WT/HK/54684 +WT/HK/54686 +WT/HK/54687 +WT/HK/54688 +WT/HK/54689 +WT/HK/54691 +WT/HK/54693 +WT/HK/54694 +WT/HK/54695 +WT/HK/54696 +WT/HK/54697 +WT/HK/54698 +WT/HK/54699 +WT/HK/54700 +WT/HK/54701 +WT/HK/54702 +WT/HK/54703 +WT/HK/54704 +WT/HK/54706 +WT/HK/54708 +WT/HK/54711 +WT/HK/54713 +WT/HK/54714 +WT/HK/54716 +WT/HK/54722 +WT/HK/54723 +WT/HK/54724 +WT/HK/54726 +WT/HK/54728 +WT/HK/54729 +WT/HK/54730 +WT/HK/54731 +WT/HK/54732 +WT/HK/54733 +WT/HK/54734 +WT/HK/54736 +WT/HK/54738 +WT/HK/54739 +WT/HK/54740 +WT/HK/54741 +WT/HK/54742 +WT/HK/54743 +WT/HK/54744 +WT/HK/54745 +WT/HK/54746 +WT/HK/54749 +WT/HK/54750 +WT/HK/54752 +WT/HK/54753 +WT/HK/54754 +WT/HK/54755 +WT/HK/54756 +WT/HK/54758 +WT/HK/54761 +WT/HK/54762 +WT/HK/54763 +WT/HK/54764 +WT/HK/54765 +WT/HK/54767 +WT/HK/54768 +WT/HK/54769 +WT/HK/54770 +WT/HK/54772 +WT/HK/54774 +WT/HK/54776 +WT/HK/54777 +WT/HK/54780 +WT/HK/54783 +WT/HK/54784 +WT/HK/54786 +WT/HK/54788 +WT/HK/54789 +WT/HK/54790 +WT/HK/54791 +WT/HK/54792 +WT/HK/54796 +WT/HK/54797 +WT/HK/54799 +WT/HK/54800 +WT/HK/54801 +WT/HK/54802 +WT/HK/54803 +WT/HK/54804 +WT/HK/54805 +WT/HK/54807 +WT/HK/54809 +WT/HK/54810 +WT/HK/54811 +WT/HK/54812 +WT/HK/54814 +WT/HK/54815 +WT/HK/54816 +WT/HK/54819 +WT/HK/54820 +WT/HK/54821 +WT/HK/54822 +WT/HK/54825 +WT/HK/54828 +WT/HK/54829 +WT/HK/54830 +WT/HK/54831 +WT/HK/54832 +WT/HK/54833 +WT/HK/54834 +WT/HK/54836 +WT/HK/54837 +WT/HK/54838 +WT/HK/54839 +WT/HK/54840 +WT/HK/54841 +WT/HK/54843 +WT/HK/54846 +WT/HK/54847 +WT/HK/54852 +WT/HK/54854 +WT/HK/54855 +WT/HK/54856 +WT/HK/54858 +WT/HK/54859 +WT/HK/54861 +WT/HK/54862 +WT/HK/54863 +WT/HK/54865 +WT/HK/54867 +WT/HK/54868 +WT/HK/54869 +WT/HK/54870 +WT/HK/54873 +WT/HK/54874 +WT/HK/54876 +WT/HK/54877 +WT/HK/54878 +WT/HK/54879 +WT/HK/54881 +WT/HK/54885 +WT/HK/54888 +WT/HK/54889 +WT/HK/54891 +WT/HK/54892 +WT/HK/54895 +WT/HK/54898 +WT/HK/54899 +WT/HK/54900 +WT/HK/54901 +WT/HK/54902 +WT/HK/54903 +WT/HK/54905 +WT/HK/54907 +WT/HK/54909 +WT/HK/54912 +WT/HK/54913 +WT/HK/54914 +WT/HK/54915 +WT/HK/54916 +WT/HK/54917 +WT/HK/54918 +WT/HK/54919 +WT/HK/54920 +WT/HK/54921 +WT/HK/54926 +WT/HK/54927 +WT/HK/54930 +WT/HK/54931 +WT/HK/54933 +WT/HK/54934 +WT/HK/54935 +WT/HK/54937 +WT/HK/54938 +WT/HK/54939 +WT/HK/54944 +WT/HK/54945 +WT/HK/54946 +WT/HK/54947 +WT/HK/54948 +WT/HK/54950 +WT/HK/54953 +WT/HK/54954 +WT/HK/54955 +WT/HK/54957 +WT/HK/54959 +WT/HK/54960 +WT/HK/54961 +WT/HK/54962 +WT/HK/54963 +WT/HK/54964 +WT/HK/54969 +WT/HK/54970 +WT/HK/54972 +WT/HK/54973 +WT/HK/54974 +WT/HK/54977 +WT/HK/54978 +WT/HK/54983 +WT/HK/54984 +WT/HK/54985 +WT/HK/54987 +WT/HK/54988 +WT/HK/54990 +WT/HK/54991 +WT/HK/54992 +WT/HK/54994 +WT/HK/54995 +WT/HK/54996 +WT/HK/54998 +WT/HK/54999 +WT/HK/55000 +WT/HK/55005 +WT/HK/55006 +WT/HK/55007 +WT/HK/55008 +WT/HK/55009 +WT/HK/55012 +WT/HK/55013 +WT/HK/55014 +WT/HK/55015 +WT/HK/55016 +WT/HK/55018 +WT/HK/55019 +WT/HK/55020 +WT/HK/55021 +WT/HK/55022 +WT/HK/55028 +WT/HK/55029 +WT/HK/55030 +WT/HK/55031 +WT/HK/55032 +WT/HK/55034 +WT/HK/55035 +WT/HK/55036 +WT/HK/55037 +WT/HK/55038 +WT/HK/55039 +WT/HK/55040 +WT/HK/55041 +WT/HK/55042 +WT/HK/55047 +WT/HK/55052 +WT/HK/55054 +WT/HK/55055 +WT/HK/55058 +WT/HK/55059 +WT/HK/55060 +WT/HK/55061 +WT/HK/55063 +WT/HK/55065 +WT/HK/55066 +WT/HK/55073 +WT/HK/55074 +WT/HK/55077 +WT/HK/55078 +WT/HK/55079 +WT/HK/55080 +WT/HK/55081 +WT/HK/55082 +WT/HK/55083 +WT/HK/55084 +WT/HK/55085 +WT/HK/55086 +WT/HK/55087 +WT/HK/55088 +WT/HK/55089 +WT/HK/55090 +WT/HK/55091 +WT/HK/55093 +WT/HK/55094 +WT/HK/55097 +WT/HK/55099 +WT/HK/55100 +WT/HK/55102 +WT/HK/55103 +WT/HK/55104 +WT/HK/55105 +WT/HK/55106 +WT/HK/55107 +WT/HK/55108 +WT/HK/55109 +WT/HK/55114 +WT/HK/55115 +WT/HK/55116 +WT/HK/55117 +WT/HK/55118 +WT/HK/55121 +WT/HK/55124 +WT/HK/55127 +WT/HK/55130 +WT/HK/55131 +WT/HK/55135 +WT/HK/55137 +WT/HK/55139 +WT/HK/55140 +WT/HK/55142 +WT/HK/55144 +WT/HK/55145 +WT/HK/55146 +WT/HK/55147 +WT/HK/55148 +WT/HK/55149 +WT/HK/55151 +WT/HK/55152 +WT/HK/55153 +WT/HK/55158 +WT/HK/55159 +WT/HK/55161 +WT/HK/55162 +WT/HK/55163 +WT/HK/55164 +WT/HK/55165 +WT/HK/55166 +WT/HK/55167 +WT/HK/55168 +WT/HK/55169 +WT/HK/55171 +WT/HK/55172 +WT/HK/55173 +WT/HK/55175 +WT/HK/55176 +WT/HK/55177 +WT/HK/55178 +WT/HK/55179 +WT/HK/55180 +WT/HK/55181 +WT/HK/55182 +WT/HK/55187 +WT/HK/55188 +WT/HK/55191 +WT/HK/55194 +WT/HK/55195 +WT/HK/55196 +WT/HK/55197 +WT/HK/55199 +WT/HK/55202 +WT/HK/55203 +WT/HK/55204 +WT/HK/55205 +WT/HK/55206 +WT/HK/55207 +WT/HK/55208 +WT/HK/55209 +WT/HK/55210 +WT/HK/55211 +WT/HK/55214 +WT/HK/55215 +WT/HK/55220 +WT/HK/55223 +WT/HK/55228 +WT/HK/55230 +WT/HK/55233 +WT/HK/55235 +WT/HK/55237 +WT/HK/55241 +WT/HK/55244 +WT/HK/55246 +WT/HK/55247 +WT/HK/55248 +WT/HK/55250 +WT/HK/55251 +WT/HK/55254 +WT/HK/55257 +WT/HK/55258 +WT/HK/55260 +WT/HK/55261 +WT/HK/55262 +WT/HK/55263 +WT/HK/55264 +WT/HK/55267 +WT/HK/55268 +WT/HK/55270 +WT/HK/55272 +WT/HK/55274 +WT/HK/55276 +WT/HK/55278 +WT/HK/55279 +WT/HK/55281 +WT/HK/55282 +WT/HK/55285 +WT/HK/55286 +WT/HK/55288 +WT/HK/55289 +WT/HK/55290 +WT/HK/55292 +WT/HK/55296 +WT/HK/55298 +WT/HK/55302 +WT/HK/55305 +WT/HK/55306 +WT/HK/55307 +WT/HK/55310 +WT/HK/55312 +WT/HK/55314 +WT/HK/55317 +WT/HK/55319 +WT/HK/55320 +WT/HK/55328 +WT/HK/55329 +WT/HK/55330 +WT/HK/55334 +WT/HK/55337 +WT/HK/55340 +WT/HK/55342 +WT/HK/55344 +WT/HK/55346 +WT/HK/55347 +WT/HK/55348 +WT/HK/55349 +WT/HK/55350 +WT/HK/55351 +WT/HK/55353 +WT/HK/55354 +WT/HK/55355 +WT/HK/55356 +WT/HK/55359 +WT/HK/55361 +WT/HK/55363 +WT/HK/55366 +WT/HK/55369 +WT/HK/55370 +WT/HK/55382 +WT/HK/55384 +WT/HK/55385 +WT/HK/55386 +WT/HK/55387 +WT/HK/55388 +WT/HK/55389 +WT/HK/55391 +WT/HK/55392 +WT/HK/55396 +WT/HK/55401 +WT/HK/55402 +WT/HK/55403 +WT/HK/55404 +WT/HK/55405 +WT/HK/55409 +WT/HK/55414 +WT/HK/55415 +WT/HK/55417 +WT/HK/55418 +WT/HK/55422 +WT/HK/55429 +WT/HK/55431 +WT/HK/55432 +WT/HK/55434 +WT/HK/55437 +WT/HK/55438 +WT/HK/55439 +WT/HK/55440 +WT/HK/55441 +WT/HK/55442 +WT/HK/55443 +WT/HK/55450 +WT/HK/55451 +WT/HK/55452 +WT/HK/55454 +WT/HK/55455 +WT/HK/55458 +WT/HK/55461 +WT/HK/55464 +WT/HK/55465 +WT/HK/55467 +WT/HK/55469 +WT/HK/55470 +WT/HK/55471 +WT/HK/55472 +WT/HK/55473 +WT/HK/55474 +WT/HK/55476 +WT/HK/55477 +WT/HK/55478 +WT/HK/55480 +WT/HK/55481 +WT/HK/55484 +WT/HK/55485 +WT/HK/55489 +WT/HK/55491 +WT/HK/55493 +WT/HK/55494 +WT/HK/55496 +WT/HK/55497 +WT/HK/55499 +WT/HK/55503 +WT/HK/55504 +WT/HK/55505 +WT/HK/55506 +WT/HK/55508 +WT/HK/55509 +WT/HK/55510 +WT/HK/55511 +WT/HK/55512 +WT/HK/55515 +WT/HK/55519 +WT/HK/55524 +WT/HK/55527 +WT/HK/55531 +WT/HK/55532 +WT/HK/55533 +WT/HK/55537 +WT/HK/55539 +WT/HK/55542 +WT/HK/55543 +WT/HK/55544 +WT/HK/55545 +WT/HK/55548 +WT/HK/55550 +WT/HK/55551 +WT/HK/55552 +WT/HK/55553 +WT/HK/55554 +WT/HK/55555 +WT/HK/55556 +WT/HK/55557 +WT/HK/55560 +WT/HK/55561 +WT/HK/55574 +WT/HK/55578 +WT/HK/55585 +WT/HK/55586 +WT/HK/55590 +WT/HK/55591 +WT/HK/55593 +WT/HK/55594 +WT/HK/55599 +WT/HK/55600 +WT/HK/55601 +WT/HK/55602 +WT/HK/55603 +WT/HK/55605 +WT/HK/55606 +WT/HK/55608 +WT/HK/55610 +WT/HK/55612 +WT/HK/55614 +WT/HK/55615 +WT/HK/55617 +WT/HK/55624 +WT/HK/55625 +WT/HK/55629 +WT/HK/55630 +WT/HK/55631 +WT/HK/55634 +WT/HK/55635 +WT/HK/55636 +WT/HK/55648 +WT/HK/55649 +WT/HK/55651 +WT/HK/55652 +WT/HK/55653 +WT/HK/55654 +WT/HK/55655 +WT/HK/55657 +WT/HK/55658 +WT/HK/55661 +WT/HK/55663 +WT/HK/55665 +WT/HK/55666 +WT/HK/55669 +WT/HK/55670 +WT/HK/55671 +WT/HK/55672 +WT/HK/55673 +WT/HK/55674 +WT/HK/55676 +WT/HK/55677 +WT/HK/55678 +WT/HK/55681 +WT/HK/55682 +WT/HK/55684 +WT/HK/55685 +WT/HK/55687 +WT/HK/55693 +WT/HK/55695 +WT/HK/55697 +WT/HK/55700 +WT/HK/55701 +WT/HK/55702 +WT/HK/55703 +WT/HK/55704 +WT/HK/55705 +WT/HK/55706 +WT/HK/55707 +WT/HK/55710 +WT/HK/55711 +WT/HK/55712 +WT/HK/55713 +WT/HK/55714 +WT/HK/55715 +WT/HK/55717 +WT/HK/55718 +WT/HK/55720 +WT/HK/55721 +WT/HK/55722 +WT/HK/55723 +WT/HK/55725 +WT/HK/55728 +WT/HK/55729 +WT/HK/55730 +WT/HK/55731 +WT/HK/55732 +WT/HK/55733 +WT/HK/55734 +WT/HK/55735 +WT/HK/55737 +WT/HK/55741 +WT/HK/55743 +WT/HK/55745 +WT/HK/55746 +WT/HK/55753 +WT/HK/55754 +WT/HK/55755 +WT/HK/55756 +WT/HK/55757 +WT/HK/55761 +WT/HK/55763 +WT/HK/55764 +WT/HK/55767 +WT/HK/55768 +WT/HK/55771 +WT/HK/55775 +WT/HK/55784 +WT/HK/55785 +WT/HK/55787 +WT/HK/55788 +WT/HK/55791 +WT/HK/55792 +WT/HK/55794 +WT/HK/55797 +WT/HK/55800 +WT/HK/55803 +WT/HK/55806 +WT/HK/55807 +WT/HK/55810 +WT/HK/55811 +WT/HK/55819 +WT/HK/55824 +WT/HK/55825 +WT/HK/55829 +WT/HK/55830 +WT/HK/55833 +WT/HK/55837 +WT/HK/55838 +WT/HK/55841 +WT/HK/55842 +WT/HK/55843 +WT/HK/55846 +WT/HK/55847 +WT/HK/55848 +WT/HK/55851 +WT/HK/55852 +WT/HK/55857 +WT/HK/55858 +WT/HK/55862 +WT/HK/55866 +WT/HK/55869 +WT/HK/55872 +WT/HK/55875 +WT/HK/55877 +WT/HK/55879 +WT/HK/55883 +WT/HK/55884 +WT/HK/55888 +WT/HK/55890 +WT/HK/55892 +WT/HK/55894 +WT/HK/55895 +WT/HK/55896 +WT/HK/55900 +WT/HK/55901 +WT/HK/55902 +WT/HK/55903 +WT/HK/55904 +WT/HK/55905 +WT/HK/55906 +WT/HK/55907 +WT/HK/55911 +WT/HK/55912 +WT/HK/55918 +WT/HK/55919 +WT/HK/55922 +WT/HK/55923 +WT/HK/55925 +WT/HK/55927 +WT/HK/55931 +WT/HK/55933 +WT/HK/55935 +WT/HK/55939 +WT/HK/55942 +WT/HK/55946 +WT/HK/55947 +WT/HK/55949 +WT/HK/55952 +WT/HK/55953 +WT/HK/55955 +WT/HK/55956 +WT/HK/55957 +WT/HK/55958 +WT/HK/55959 +WT/HK/55960 +WT/HK/55966 +WT/HK/55967 +WT/HK/55968 +WT/HK/55970 +WT/HK/55972 +WT/HK/55974 +WT/HK/55975 +WT/HK/55976 +WT/HK/55977 +WT/HK/55979 +WT/HK/55981 +WT/HK/55982 +WT/HK/55983 +WT/HK/55984 +WT/HK/55985 +WT/HK/55991 +WT/HK/55995 +WT/HK/55997 +WT/HK/56002 +WT/HK/56006 +WT/HK/56009 +WT/HK/56011 +WT/HK/56013 +WT/HK/56014 +WT/HK/56015 +WT/HK/56017 +WT/HK/56018 +WT/HK/56019 +WT/HK/56020 +WT/HK/56021 +WT/HK/56024 +WT/HK/56025 +WT/HK/56027 +WT/HK/56028 +WT/HK/56030 +WT/HK/56031 +WT/HK/56032 +WT/HK/56034 +WT/HK/56035 +WT/HK/56036 +WT/HK/56037 +WT/HK/56039 +WT/HK/56040 +WT/HK/56041 +WT/HK/56043 +WT/HK/56045 +WT/HK/56047 +WT/HK/56048 +WT/HK/56049 +WT/HK/56051 +WT/HK/56052 +WT/HK/56053 +WT/HK/56054 +WT/HK/56056 +WT/HK/56057 +WT/HK/56058 +WT/HK/56065 +WT/HK/56068 +WT/HK/56069 +WT/HK/56070 +WT/HK/56072 +WT/HK/56076 +WT/HK/56078 +WT/HK/56080 +WT/HK/56081 +WT/HK/56082 +WT/HK/56086 +WT/HK/56092 +WT/HK/56093 +WT/HK/56097 +WT/HK/56102 +WT/HK/56104 +WT/HK/56107 +WT/HK/56114 +WT/HK/56116 +WT/HK/56120 +WT/HK/56121 +WT/HK/56122 +WT/HK/56123 +WT/HK/56125 +WT/HK/56126 +WT/HK/56129 +WT/HK/56131 +WT/HK/56132 +WT/HK/56133 +WT/HK/56134 +WT/HK/56135 +WT/HK/56136 +WT/HK/56140 +WT/HK/56141 +WT/HK/56143 +WT/HK/56145 +WT/HK/56146 +WT/HK/56147 +WT/HK/56149 +WT/HK/56151 +WT/HK/56155 +WT/HK/56157 +WT/HK/56158 +WT/HK/56159 +WT/HK/56162 +WT/HK/56163 +WT/HK/56165 +WT/HK/56167 +WT/HK/56169 +WT/HK/56170 +WT/HK/56173 +WT/HK/56175 +WT/HK/56176 +WT/HK/56178 +WT/HK/56190 +WT/HK/56193 +WT/HK/56197 +WT/HK/56198 +WT/HK/56201 +WT/HK/56202 +WT/HK/56203 +WT/HK/56204 +WT/HK/56205 +WT/HK/56206 +WT/HK/56207 +WT/HK/56209 +WT/HK/56210 +WT/HK/56211 +WT/HK/56212 +WT/HK/56213 +WT/HK/56214 +WT/HK/56215 +WT/HK/56217 +WT/HK/56218 +WT/HK/56219 +WT/HK/56220 +WT/HK/56221 +WT/HK/56223 +WT/HK/56224 +WT/HK/56225 +WT/HK/56226 +WT/HK/56227 +WT/HK/56229 +WT/HK/56231 +WT/HK/56232 +WT/HK/56233 +WT/HK/56234 +WT/HK/56235 +WT/HK/56237 +WT/HK/56241 +WT/HK/56243 +WT/HK/56244 +WT/HK/56245 +WT/HK/56246 +WT/HK/56247 +WT/HK/56249 +WT/HK/56250 +WT/HK/56251 +WT/HK/56252 +WT/HK/56253 +WT/HK/56255 +WT/HK/56258 +WT/HK/56259 +WT/HK/56260 +WT/HK/56262 +WT/HK/56264 +WT/HK/56265 +WT/HK/56270 +WT/HK/56274 +WT/HK/56278 +WT/HK/56279 +WT/HK/56280 +WT/HK/56281 +WT/HK/56283 +WT/HK/56286 +WT/HK/56288 +WT/HK/56289 +WT/HK/56302 +WT/HK/56303 +WT/HK/56304 +WT/HK/56308 +WT/HK/56309 +WT/HK/56310 +WT/HK/56312 +WT/HK/56313 +WT/HK/56314 +WT/HK/56315 +WT/HK/56316 +WT/HK/56317 +WT/HK/56319 +WT/HK/56320 +WT/HK/56321 +WT/HK/56324 +WT/HK/56325 +WT/HK/56326 +WT/HK/56327 +WT/HK/56331 +WT/HK/56334 +WT/HK/56336 +WT/HK/56337 +WT/HK/56338 +WT/HK/56339 +WT/HK/56340 +WT/HK/56342 +WT/HK/56344 +WT/HK/56346 +WT/HK/56347 +WT/HK/56349 +WT/HK/56350 +WT/HK/56352 +WT/HK/56353 +WT/HK/56354 +WT/HK/56355 +WT/HK/56356 +WT/HK/56358 +WT/HK/56360 +WT/HK/56361 +WT/HK/56362 +WT/HK/56363 +WT/HK/56364 +WT/HK/56366 +WT/HK/56367 +WT/HK/56370 +WT/HK/56371 +WT/HK/56377 +WT/HK/56378 +WT/HK/56379 +WT/HK/56380 +WT/HK/56382 +WT/HK/56384 +WT/HK/56385 +WT/HK/56388 +WT/HK/56390 +WT/HK/56392 +WT/HK/56393 +WT/HK/56394 +WT/HK/56395 +WT/HK/56396 +WT/HK/56397 +WT/HK/56399 +WT/HK/56401 +WT/HK/56405 +WT/HK/56406 +WT/HK/56408 +WT/HK/56410 +WT/HK/56411 +WT/HK/56412 +WT/HK/56413 +WT/HK/56414 +WT/HK/56416 +WT/HK/56417 +WT/HK/56418 +WT/HK/56421 +WT/HK/56424 +WT/HK/56425 +WT/HK/56428 +WT/HK/56429 +WT/HK/56430 +WT/HK/56431 +WT/HK/56432 +WT/HK/56433 +WT/HK/56434 +WT/HK/56435 +WT/HK/56438 +WT/HK/56440 +WT/HK/56443 +WT/HK/56444 +WT/HK/56445 +WT/HK/56446 +WT/HK/56448 +WT/HK/56449 +WT/HK/56450 +WT/HK/56452 +WT/HK/56453 +WT/HK/56454 +WT/HK/56456 +WT/HK/56460 +WT/HK/56462 +WT/HK/56463 +WT/HK/56465 +WT/HK/56466 +WT/HK/56468 +WT/HK/56469 +WT/HK/56470 +WT/HK/56471 +WT/HK/56472 +WT/HK/56473 +WT/HK/56474 +WT/HK/56475 +WT/HK/56476 +WT/HK/56477 +WT/HK/56479 +WT/HK/56483 +WT/HK/56484 +WT/HK/56487 +WT/HK/56490 +WT/HK/56491 +WT/HK/56492 +WT/HK/56494 +WT/HK/56495 +WT/HK/56498 +WT/HK/56499 +WT/HK/56500 +WT/HK/56503 +WT/HK/56504 +WT/HK/56505 +WT/HK/56506 +WT/HK/56507 +WT/HK/56508 +WT/HK/56511 +WT/HK/56512 +WT/HK/56514 +WT/HK/56516 +WT/HK/56517 +WT/HK/56520 +WT/HK/56521 +WT/HK/56522 +WT/HK/56523 +WT/HK/56525 +WT/HK/56528 +WT/HK/56529 +WT/HK/56530 +WT/HK/56531 +WT/HK/56534 +WT/HK/56536 +WT/HK/56538 +WT/HK/56539 +WT/HK/56544 +WT/HK/56545 +WT/HK/56547 +WT/HK/56548 +WT/HK/56549 +WT/HK/56550 +WT/HK/56551 +WT/HK/56552 +WT/HK/56553 +WT/HK/56554 +WT/HK/56555 +WT/HK/56556 +WT/HK/56557 +WT/HK/56558 +WT/HK/56559 +WT/HK/56560 +WT/HK/56561 +WT/HK/56562 +WT/HK/56564 +WT/HK/56568 +WT/HK/56569 +WT/HK/56571 +WT/HK/56574 +WT/HK/56576 +WT/HK/56579 +WT/HK/56580 +WT/HK/56584 +WT/HK/56588 +WT/HK/56590 +WT/HK/56592 +WT/HK/56593 +WT/HK/56594 +WT/HK/56595 +WT/HK/56597 +WT/HK/56598 +WT/HK/56599 +WT/HK/56600 +WT/HK/56601 +WT/HK/56602 +WT/HK/56604 +WT/HK/56606 +WT/HK/56610 +WT/HK/56617 +WT/HK/56618 +WT/HK/56619 +WT/HK/56622 +WT/HK/56623 +WT/HK/56624 +WT/HK/56625 +WT/HK/56626 +WT/HK/56628 +WT/HK/56629 +WT/HK/56630 +WT/HK/56631 +WT/HK/56632 +WT/HK/56633 +WT/HK/56636 +WT/HK/56639 +WT/HK/56640 +WT/HK/56641 +WT/HK/56642 +WT/HK/56643 +WT/HK/56645 +WT/HK/56646 +WT/HK/56651 +WT/HK/56652 +WT/HK/56653 +WT/HK/56656 +WT/HK/56659 +WT/HK/56660 +WT/HK/56661 +WT/HK/56662 +WT/HK/56663 +WT/HK/56664 +WT/HK/56666 +WT/HK/56667 +WT/HK/56668 +WT/HK/56669 +WT/HK/56671 +WT/HK/56672 +WT/HK/56673 +WT/HK/56674 +WT/HK/56675 +WT/HK/56676 +WT/HK/56678 +WT/HK/56679 +WT/HK/56680 +WT/HK/56681 +WT/HK/56682 +WT/HK/56683 +WT/HK/56684 +WT/HK/56685 +WT/HK/56686 +WT/HK/56687 +WT/HK/56688 +WT/HK/56690 +WT/HK/56691 +WT/HK/56694 +WT/HK/56697 +WT/HK/56698 +WT/HK/56701 +WT/HK/56702 +WT/HK/56703 +WT/HK/56707 +WT/HK/56708 +WT/HK/56711 +WT/HK/56712 +WT/HK/56714 +WT/HK/56715 +WT/HK/56716 +WT/HK/56718 +WT/HK/56719 +WT/HK/56720 +WT/HK/56724 +WT/HK/56725 +WT/HK/56726 +WT/HK/56727 +WT/HK/56728 +WT/HK/56731 +WT/HK/56732 +WT/HK/56733 +WT/HK/56734 +WT/HK/56735 +WT/HK/56737 +WT/HK/56738 +WT/HK/56739 +WT/HK/56740 +WT/HK/56741 +WT/HK/56745 +WT/HK/56747 +WT/HK/56751 +WT/HK/56752 +WT/HK/56758 +WT/HK/56760 +WT/HK/56761 +WT/HK/56768 +WT/HK/56769 +WT/HK/56771 +WT/HK/56773 +WT/HK/56778 +WT/HK/56779 +WT/HK/56780 +WT/HK/56781 +WT/HK/56783 +WT/HK/56784 +WT/HK/56786 +WT/HK/56789 +WT/HK/56790 +WT/HK/56791 +WT/HK/56792 +WT/HK/56797 +WT/HK/56800 +WT/HK/56801 +WT/HK/56802 +WT/HK/56803 +WT/HK/56804 +WT/HK/56805 +WT/HK/56807 +WT/HK/56808 +WT/HK/56809 +WT/HK/56812 +WT/HK/56815 +WT/HK/56817 +WT/HK/56825 +WT/HK/56826 +WT/HK/56827 +WT/HK/56828 +WT/HK/56829 +WT/HK/56830 +WT/HK/56831 +WT/HK/56832 +WT/HK/56833 +WT/HK/56835 +WT/HK/56838 +WT/HK/56839 +WT/HK/56840 +WT/HK/56843 +WT/HK/56844 +WT/HK/56847 +WT/HK/56848 +WT/HK/56849 +WT/HK/56850 +WT/HK/56851 +WT/HK/56852 +WT/HK/56853 +WT/HK/56855 +WT/HK/56858 +WT/HK/56863 +WT/HK/56866 +WT/HK/56868 +WT/HK/56869 +WT/HK/56870 +WT/HK/56871 +WT/HK/56873 +WT/HK/56874 +WT/HK/56877 +WT/HK/56878 +WT/HK/56879 +WT/HK/56880 +WT/HK/56881 +WT/HK/56882 +WT/HK/56883 +WT/HK/56884 +WT/HK/56885 +WT/HK/56887 +WT/HK/56890 +WT/HK/56893 +WT/HK/56894 +WT/HK/56895 +WT/HK/56896 +WT/HK/56898 +WT/HK/56899 +WT/HK/56900 +WT/HK/56902 +WT/HK/56904 +WT/HK/56908 +WT/HK/56909 +WT/HK/56911 +WT/HK/56912 +WT/HK/56913 +WT/HK/56914 +WT/HK/56918 +WT/HK/56920 +WT/HK/56926 +WT/HK/56927 +WT/HK/56928 +WT/HK/56929 +WT/HK/56930 +WT/HK/56931 +WT/HK/56932 +WT/HK/56933 +WT/HK/56934 +WT/HK/56938 +WT/HK/56939 +WT/HK/56941 +WT/HK/56943 +WT/HK/56945 +WT/HK/56949 +WT/HK/56951 +WT/HK/56952 +WT/HK/56953 +WT/HK/56954 +WT/HK/56955 +WT/HK/56956 +WT/HK/56957 +WT/HK/56959 +WT/HK/56960 +WT/HK/56961 +WT/HK/56962 +WT/HK/56963 +WT/HK/56964 +WT/HK/56966 +WT/HK/56968 +WT/HK/56969 +WT/HK/56970 +WT/HK/56971 +WT/HK/56972 +WT/HK/56974 +WT/HK/56975 +WT/HK/56977 +WT/HK/56978 +WT/HK/56980 +WT/HK/56982 +WT/HK/56989 +WT/HK/56990 +WT/HK/56991 +WT/HK/56993 +WT/HK/56994 +WT/HK/56995 +WT/HK/56997 +WT/HK/57000 +WT/HK/57001 +WT/HK/57005 +WT/HK/57006 +WT/HK/57007 +WT/HK/57008 +WT/HK/57012 +WT/HK/57021 +WT/HK/57025 +WT/HK/57026 +WT/HK/57027 +WT/HK/57029 +WT/HK/57031 +WT/HK/57032 +WT/HK/57033 +WT/HK/57035 +WT/HK/57038 +WT/HK/57039 +WT/HK/57040 +WT/HK/57041 +WT/HK/57042 +WT/HK/57043 +WT/HK/57044 +WT/HK/57048 +WT/HK/57053 +WT/HK/57057 +WT/HK/57059 +WT/HK/57060 +WT/HK/57062 +WT/HK/57063 +WT/HK/57064 +WT/HK/57065 +WT/HK/57068 +WT/HK/57069 +WT/HK/57070 +WT/HK/57072 +WT/HK/57073 +WT/HK/57074 +WT/HK/57075 +WT/HK/57076 +WT/HK/57077 +WT/HK/57080 +WT/HK/57082 +WT/HK/57084 +WT/HK/57086 +WT/HK/57087 +WT/HK/57095 +WT/HK/57097 +WT/HK/57100 +WT/HK/57101 +WT/HK/57103 +WT/HK/57107 +WT/HK/57108 +WT/HK/57110 +WT/HK/57111 +WT/HK/57112 +WT/HK/57113 +WT/HK/57116 +WT/HK/57120 +WT/HK/57122 +WT/HK/57126 +WT/HK/57127 +WT/HK/57128 +WT/HK/57131 +WT/HK/57132 +WT/HK/57133 +WT/HK/57136 +WT/HK/57137 +WT/HK/57142 +WT/HK/57143 +WT/HK/57146 +WT/HK/57148 +WT/HK/57149 +WT/HK/57150 +WT/HK/57152 +WT/HK/57156 +WT/HK/57158 +WT/HK/57159 +WT/HK/57162 +WT/HK/57164 +WT/HK/57169 +WT/HK/57170 +WT/HK/57172 +WT/HK/57173 +WT/HK/57174 +WT/HK/57175 +WT/HK/57177 +WT/HK/57180 +WT/HK/57181 +WT/HK/57182 +WT/HK/57183 +WT/HK/57184 +WT/HK/57185 +WT/HK/57188 +WT/HK/57191 +WT/HK/57192 +WT/HK/57193 +WT/HK/57195 +WT/HK/57196 +WT/HK/57197 +WT/HK/57198 +WT/HK/57199 +WT/HK/57201 +WT/HK/57202 +WT/HK/57203 +WT/HK/57204 +WT/HK/57211 +WT/HK/57212 +WT/HK/57219 +WT/HK/57221 +WT/HK/57222 +WT/HK/57223 +WT/HK/57224 +WT/HK/57225 +WT/HK/57226 +WT/HK/57228 +WT/HK/57229 +WT/HK/57230 +WT/HK/57231 +WT/HK/57232 +WT/HK/57233 +WT/HK/57234 +WT/HK/57235 +WT/HK/57236 +WT/HK/57237 +WT/HK/57238 +WT/HK/57240 +WT/HK/57242 +WT/HK/57247 +WT/HK/57251 +WT/HK/57254 +WT/HK/57255 +WT/HK/57256 +WT/HK/57257 +WT/HK/57259 +WT/HK/57260 +WT/HK/57261 +WT/HK/57262 +WT/HK/57266 +WT/HK/57267 +WT/HK/57272 +WT/HK/57277 +WT/HK/57281 +WT/HK/57284 +WT/HK/57289 +WT/HK/57290 +WT/HK/57291 +WT/HK/57294 +WT/HK/57295 +WT/HK/57300 +WT/HK/57302 +WT/HK/57303 +WT/HK/57305 +WT/HK/57307 +WT/HK/57308 +WT/HK/57310 +WT/HK/57312 +WT/HK/57313 +WT/HK/57314 +WT/HK/57317 +WT/HK/57318 +WT/HK/57321 +WT/HK/57322 +WT/HK/57326 +WT/HK/57327 +WT/HK/57329 +WT/HK/57330 +WT/HK/57331 +WT/HK/57335 +WT/HK/57336 +WT/HK/57337 +WT/HK/57339 +WT/HK/57340 +WT/HK/57341 +WT/HK/57342 +WT/HK/57343 +WT/HK/57345 +WT/HK/57347 +WT/HK/57349 +WT/HK/57361 +WT/HK/57362 +WT/HK/57364 +WT/HK/57367 +WT/HK/57368 +WT/HK/57370 +WT/HK/57371 +WT/HK/57373 +WT/HK/57374 +WT/HK/57375 +WT/HK/57376 +WT/HK/57377 +WT/HK/57378 +WT/HK/57379 +WT/HK/57382 +WT/HK/57383 +WT/HK/57385 +WT/HK/57388 +WT/HK/57389 +WT/HK/57390 +WT/HK/57394 +WT/HK/57396 +WT/HK/57399 +WT/HK/57401 +WT/HK/57404 +WT/HK/57408 +WT/HK/57409 +WT/HK/57413 +WT/HK/57414 +WT/HK/57415 +WT/HK/57420 +WT/HK/57424 +WT/HK/57426 +WT/HK/57427 +WT/HK/57428 +WT/HK/57429 +WT/HK/57430 +WT/HK/57431 +WT/HK/57432 +WT/HK/57433 +WT/HK/57434 +WT/HK/57435 +WT/HK/57437 +WT/HK/57438 +WT/HK/57441 +WT/HK/57443 +WT/HK/57444 +WT/HK/57446 +WT/HK/57452 +WT/HK/57453 +WT/HK/57455 +WT/HK/57457 +WT/HK/57458 +WT/HK/57459 +WT/HK/57460 +WT/HK/57463 +WT/HK/57464 +WT/HK/57465 +WT/HK/57468 +WT/HK/57470 +WT/HK/57472 +WT/HK/57479 +WT/HK/57480 +WT/HK/57483 +WT/HK/57486 +WT/HK/57489 +WT/HK/57490 +WT/HK/57491 +WT/HK/57492 +WT/HK/57495 +WT/HK/57496 +WT/HK/57501 +WT/HK/57503 +WT/HK/57504 +WT/HK/57511 +WT/HK/57512 +WT/HK/57514 +WT/HK/57521 +WT/HK/57525 +WT/HK/57527 +WT/HK/57532 +WT/HK/57534 +WT/HK/57536 +WT/HK/57538 +WT/HK/57539 +WT/HK/57544 +WT/HK/57549 +WT/HK/57553 +WT/HK/57556 +WT/HK/57558 +WT/HK/57563 +WT/HK/57565 +WT/HK/57566 +WT/HK/57568 +WT/HK/57571 +WT/HK/57572 +WT/HK/57576 +WT/HK/57577 +WT/HK/57580 +WT/HK/57581 +WT/HK/57582 +WT/HK/57584 +WT/HK/57585 +WT/HK/57586 +WT/HK/57588 +WT/HK/57593 +WT/HK/57595 +WT/HK/57597 +WT/HK/57598 +WT/HK/57599 +WT/HK/57601 +WT/HK/57602 +WT/HK/57605 +WT/HK/57606 +WT/HK/57607 +WT/HK/57608 +WT/HK/57612 +WT/HK/57614 +WT/HK/57619 +WT/HK/57622 +WT/HK/57623 +WT/HK/57626 +WT/HK/57630 +WT/HK/57631 +WT/HK/57632 +WT/HK/57633 +WT/HK/57636 +WT/HK/57637 +WT/HK/57638 +WT/HK/57642 +WT/HK/57643 +WT/HK/57648 +WT/HK/57650 +WT/HK/57656 +WT/HK/57657 +WT/HK/57658 +WT/HK/57660 +WT/HK/57661 +WT/HK/57662 +WT/HK/57663 +WT/HK/57664 +WT/HK/57665 +WT/HK/57666 +WT/HK/57673 +WT/HK/57677 +WT/HK/57678 +WT/HK/57679 +WT/HK/57680 +WT/HK/57686 +WT/HK/57687 +WT/HK/57688 +WT/HK/57691 +WT/HK/57692 +WT/HK/57693 +WT/HK/57699 +WT/HK/57700 +WT/HK/57701 +WT/HK/57702 +WT/HK/57705 +WT/HK/57709 +WT/HK/57715 +WT/HK/57717 +WT/HK/57719 +WT/HK/57721 +WT/HK/57722 +WT/HK/57723 +WT/HK/57724 +WT/HK/57725 +WT/HK/57730 +WT/HK/57731 +WT/HK/57738 +WT/HK/57739 +WT/HK/57741 +WT/HK/57742 +WT/HK/57743 +WT/HK/57745 +WT/HK/57746 +WT/HK/57753 +WT/HK/57756 +WT/HK/57758 +WT/HK/57763 +WT/HK/57767 +WT/HK/57768 +WT/HK/57772 +WT/HK/57773 +WT/HK/57774 +WT/HK/57775 +WT/HK/57776 +WT/HK/57778 +WT/HK/57781 +WT/HK/57782 +WT/HK/57783 +WT/HK/57786 +WT/HK/57787 +WT/HK/57789 +WT/HK/57790 +WT/HK/57793 +WT/HK/57794 +WT/HK/57795 +WT/HK/57796 +WT/HK/57797 +WT/HK/57799 +WT/HK/57800 +WT/HK/57802 +WT/HK/57804 +WT/HK/57805 +WT/HK/57806 +WT/HK/57808 +WT/HK/57810 +WT/HK/57811 +WT/HK/57819 +WT/HK/57821 +WT/HK/57822 +WT/HK/57823 +WT/HK/57824 +WT/HK/57826 +WT/HK/57827 +WT/HK/57828 +WT/HK/57829 +WT/HK/57831 +WT/HK/57832 +WT/HK/57835 +WT/HK/57836 +WT/HK/57840 +WT/HK/57841 +WT/HK/57842 +WT/HK/57844 +WT/HK/57847 +WT/HK/57848 +WT/HK/57850 +WT/HK/57851 +WT/HK/57852 +WT/HK/57853 +WT/HK/57854 +WT/HK/57855 +WT/HK/57859 +WT/HK/57862 +WT/HK/57865 +WT/HK/57868 +WT/HK/57870 +WT/HK/57872 +WT/HK/57875 +WT/HK/57879 +WT/HK/57882 +WT/HK/57885 +WT/HK/57886 +WT/HK/57888 +WT/HK/57889 +WT/HK/57890 +WT/HK/57892 +WT/HK/57897 +WT/HK/57898 +WT/HK/57900 +WT/HK/57901 +WT/HK/57910 +WT/HK/57911 +WT/HK/57914 +WT/HK/57915 +WT/HK/57917 +WT/HK/57919 +WT/HK/57921 +WT/HK/57922 +WT/HK/57923 +WT/HK/57925 +WT/HK/57930 +WT/HK/57932 +WT/HK/57935 +WT/HK/57936 +WT/HK/57939 +WT/HK/57940 +WT/HK/57941 +WT/HK/57946 +WT/HK/57947 +WT/HK/57952 +WT/HK/57953 +WT/HK/57954 +WT/HK/57956 +WT/HK/57960 +WT/HK/57962 +WT/HK/57966 +WT/HK/57968 +WT/HK/57970 +WT/HK/57971 +WT/HK/57972 +WT/HK/57973 +WT/HK/57975 +WT/HK/57976 +WT/HK/57978 +WT/HK/57979 +WT/HK/57981 +WT/HK/57983 +WT/HK/57984 +WT/HK/57985 +WT/HK/57987 +WT/HK/57992 +WT/HK/57993 +WT/HK/57994 +WT/HK/57999 +WT/HK/58000 +WT/HK/58001 +WT/HK/58002 +WT/HK/58003 +WT/HK/58007 +WT/HK/58014 +WT/HK/58015 +WT/HK/58016 +WT/HK/58018 +WT/HK/58019 +WT/HK/58020 +WT/HK/58025 +WT/HK/58026 +WT/HK/58027 +WT/HK/58028 +WT/HK/58029 +WT/HK/58030 +WT/HK/58031 +WT/HK/58033 +WT/HK/58034 +WT/HK/58036 +WT/HK/58038 +WT/HK/58041 +WT/HK/58043 +WT/HK/58045 +WT/HK/58047 +WT/HK/58049 +WT/HK/58050 +WT/HK/58051 +WT/HK/58052 +WT/HK/58055 +WT/HK/58056 +WT/HK/58057 +WT/HK/58062 +WT/HK/58063 +WT/HK/58064 +WT/HK/58065 +WT/HK/58066 +WT/HK/58067 +WT/HK/58069 +WT/HK/58070 +WT/HK/58071 +WT/HK/58073 +WT/HK/58074 +WT/HK/58075 +WT/HK/58076 +WT/HK/58078 +WT/HK/58081 +WT/HK/58083 +WT/HK/58087 +WT/HK/58088 +WT/HK/58090 +WT/HK/58091 +WT/HK/58092 +WT/HK/58096 +WT/HK/58097 +WT/HK/58098 +WT/HK/58099 +WT/HK/58103 +WT/HK/58104 +WT/HK/58105 +WT/HK/58106 +WT/HK/58107 +WT/HK/58109 +WT/HK/58112 +WT/HK/58113 +WT/HK/58114 +WT/HK/58117 +WT/HK/58118 +WT/HK/58119 +WT/HK/58120 +WT/HK/58124 +WT/HK/58125 +WT/HK/58127 +WT/HK/58129 +WT/HK/58132 +WT/HK/58133 +WT/HK/58136 +WT/HK/58138 +WT/HK/58140 +WT/HK/58141 +WT/HK/58144 +WT/HK/58146 +WT/HK/58149 +WT/HK/58150 +WT/HK/58151 +WT/HK/58152 +WT/HK/58154 +WT/HK/58155 +WT/HK/58156 +WT/HK/58157 +WT/HK/58158 +WT/HK/58159 +WT/HK/58160 +WT/HK/58161 +WT/HK/58162 +WT/HK/58163 +WT/HK/58164 +WT/HK/58165 +WT/HK/58170 +WT/HK/58171 +WT/HK/58173 +WT/HK/58174 +WT/HK/58175 +WT/HK/58177 +WT/HK/58179 +WT/HK/58180 +WT/HK/58181 +WT/HK/58183 +WT/HK/58187 +WT/HK/58188 +WT/HK/58193 +WT/HK/58196 +WT/HK/58197 +WT/HK/58199 +WT/HK/58200 +WT/HK/58202 +WT/HK/58203 +WT/HK/58205 +WT/HK/58206 +WT/HK/58211 +WT/HK/58213 +WT/HK/58215 +WT/HK/58217 +WT/HK/58218 +WT/HK/58219 +WT/HK/58220 +WT/HK/58221 +WT/HK/58223 +WT/HK/58224 +WT/HK/58229 +WT/HK/58230 +WT/HK/58231 +WT/HK/58235 +WT/HK/58236 +WT/HK/58238 +WT/HK/58241 +WT/HK/58242 +WT/HK/58247 +WT/HK/58248 +WT/HK/58249 +WT/HK/58251 +WT/HK/58252 +WT/HK/58253 +WT/HK/58254 +WT/HK/58256 +WT/HK/58259 +WT/HK/58262 +WT/HK/58269 +WT/HK/58272 +WT/HK/58273 +WT/HK/58274 +WT/HK/58276 +WT/HK/58286 +WT/HK/58289 +WT/HK/58290 +WT/HK/58292 +WT/HK/58296 +WT/HK/58298 +WT/HK/58299 +WT/HK/58301 +WT/HK/58308 +WT/HK/58310 +WT/HK/58312 +WT/HK/58313 +WT/HK/58314 +WT/HK/58321 +WT/HK/58325 +WT/HK/58326 +WT/HK/58327 +WT/HK/58328 +WT/HK/58332 +WT/HK/58337 +WT/HK/58340 +WT/HK/58342 +WT/HK/58344 +WT/HK/58345 +WT/HK/58346 +WT/HK/58347 +WT/HK/58349 +WT/HK/58353 +WT/HK/58354 +WT/HK/58355 +WT/HK/58356 +WT/HK/58357 +WT/HK/58359 +WT/HK/58360 +WT/HK/58369 +WT/HK/58373 +WT/HK/58374 +WT/HK/58378 +WT/HK/58381 +WT/HK/58383 +WT/HK/58384 +WT/HK/58386 +WT/HK/58387 +WT/HK/58391 +WT/HK/58397 +WT/HK/58402 +WT/HK/58403 +WT/HK/58408 +WT/HK/58412 +WT/HK/58414 +WT/HK/58416 +WT/HK/58417 +WT/HK/58418 +WT/HK/58420 +WT/HK/58421 +WT/HK/58422 +WT/HK/58426 +WT/HK/58428 +WT/HK/58430 +WT/HK/58433 +WT/HK/58437 +WT/HK/58441 +WT/HK/58444 +WT/HK/58447 +WT/HK/58448 +WT/HK/58450 +WT/HK/58451 +WT/HK/58452 +WT/HK/58453 +WT/HK/58454 +WT/HK/58455 +WT/HK/58458 +WT/HK/58459 +WT/HK/58460 +WT/HK/58462 +WT/HK/58463 +WT/HK/58464 +WT/HK/58465 +WT/HK/58466 +WT/HK/58467 +WT/HK/58468 +WT/HK/58469 +WT/HK/58470 +WT/HK/58474 +WT/HK/58477 +WT/HK/58479 +WT/HK/58481 +WT/HK/58486 +WT/HK/58489 +WT/HK/58492 +WT/HK/58495 +WT/HK/58500 +WT/HK/58504 +WT/HK/58506 +WT/HK/58509 +WT/HK/58511 +WT/HK/58523 +WT/HK/58524 +WT/HK/58525 +WT/HK/58536 +WT/HK/58542 +WT/HK/58546 +WT/HK/58556 +WT/HK/58558 +WT/HK/58560 +WT/HK/58566 +WT/HK/58567 +WT/HK/58568 +WT/HK/58570 +WT/HK/58576 +WT/HK/58596 +WT/HK/58597 +WT/HK/58598 +WT/HK/58599 +WT/HK/58601 +WT/HK/58605 +WT/HK/58620 +WT/HK/58622 +WT/HK/58631 +WT/HK/58634 +WT/HK/58636 +WT/HK/58639 +WT/HK/58640 +WT/HK/58641 +WT/HK/58645 +WT/HK/58646 +WT/HK/58650 +WT/HK/58651 +WT/HK/58656 +WT/HK/58658 +WT/HK/58662 +WT/HK/58665 +WT/HK/58667 +WT/HK/58668 +WT/HK/58669 +WT/HK/58671 +WT/HK/58672 +WT/HK/58673 +WT/HK/58676 +WT/HK/58677 +WT/HK/58683 +WT/HK/58685 +WT/HK/58686 +WT/HK/58687 +WT/HK/58688 +WT/HK/58702 +WT/HK/58708 +WT/HK/58710 +WT/HK/58719 +WT/HK/58725 +WT/HK/58727 +WT/HK/58728 +WT/HK/58730 +WT/HK/58744 +WT/HK/58745 +WT/HK/58746 +WT/HK/58748 +WT/HK/58752 +WT/HK/58755 +WT/HK/58758 +WT/HK/58767 +WT/HK/58769 +WT/HK/58774 +WT/HK/58779 +WT/HK/58782 +WT/HK/58787 +WT/HK/58793 +WT/HK/58797 +WT/HK/58805 +WT/HK/58807 +WT/HK/58811 +WT/HK/58814 +WT/HK/58818 +WT/HK/58821 +WT/HK/58822 +WT/HK/58824 +WT/HK/58826 +WT/HK/58829 +WT/HK/58834 +WT/HK/58837 +WT/HK/58842 +WT/HK/58846 +WT/HK/58847 +WT/HK/58850 +WT/HK/58853 +WT/HK/58867 +WT/HK/58871 +WT/HK/58874 +WT/HK/58875 +WT/HK/58879 +WT/HK/58895 +WT/HK/58896 +WT/HK/58897 +WT/HK/58898 +WT/HK/58905 +WT/HK/58906 +WT/HK/58909 +WT/HK/58910 +WT/HK/58911 +WT/HK/58914 +WT/HK/58918 +WT/HK/58923 +WT/HK/58927 +WT/HK/58929 +WT/HK/58930 +WT/HK/58935 +WT/HK/58939 +WT/HK/58941 +WT/HK/58960 +WT/HK/58974 +WT/HK/58986 +WT/HK/58998 +WT/HK/59003 +WT/HK/59008 +WT/HK/59010 +WT/HK/59035 +WT/HK/59037 +WT/HK/59038 +WT/HK/59040 +WT/HK/59041 +WT/HK/59050 +WT/HK/59051 +WT/HK/59054 +WT/HK/59063 +WT/HK/59070 +WT/HK/59072 +WT/HK/59075 +WT/HK/59076 +WT/HK/59086 +WT/HK/59088 +WT/HK/59092 +WT/HK/59095 +WT/HK/59099 +WT/HK/59105 +WT/HK/59106 +WT/HK/59109 +WT/HK/59112 +WT/HK/59115 +WT/HK/59121 +WT/HK/59122 +WT/HK/59125 +WT/HK/59136 +WT/HK/59144 +WT/HK/59152 +WT/HK/59166 +WT/HK/59171 +WT/HK/59176 +WT/HK/59179 +WT/HK/59181 +WT/HK/59190 +WT/HK/59192 +WT/HK/59200 +WT/HK/59217 +WT/HK/59228 +WT/HK/59238 +WT/HK/59251 +WT/HK/59252 +WT/HK/59255 +WT/HK/59257 +WT/HK/59261 +WT/HK/59263 +WT/HK/59264 +WT/HK/59265 +WT/HK/59267 +WT/HK/59268 +WT/HK/59270 +WT/HK/59272 +WT/HK/59274 +WT/HK/59287 +WT/HK/59291 +WT/HK/59292 +WT/HK/59293 +WT/HK/59295 +WT/HK/59296 +WT/HK/59302 +WT/HK/59306 +WT/HK/59307 +WT/HK/59309 +WT/HK/59310 +WT/HK/59313 +WT/HK/59317 +WT/HK/59318 +WT/HK/59320 +WT/HK/59321 +WT/HK/59325 +WT/HK/59329 +WT/HK/59332 +WT/HK/59336 +WT/HK/59339 +WT/HK/59340 +WT/HK/59341 +WT/HK/59342 +WT/HK/59344 +WT/HK/59345 +WT/HK/59346 +WT/HK/59348 +WT/HK/59355 +WT/HK/59356 +WT/HK/59361 +WT/HK/59363 +WT/HK/59364 +WT/HK/59368 +WT/HK/59369 +WT/HK/59371 +WT/HK/59374 +WT/HK/59375 +WT/HK/59377 +WT/HK/59384 +WT/HK/59385 +WT/HK/59386 +WT/HK/59393 +WT/HK/59396 +WT/HK/59398 +WT/HK/59399 +WT/HK/59401 +WT/HK/59402 +WT/HK/59403 +WT/HK/59404 +WT/HK/59405 +WT/HK/59407 +WT/HK/59408 +WT/HK/59410 +WT/HK/59411 +WT/HK/59412 +WT/HK/59413 +WT/HK/59415 +WT/HK/59416 +WT/HK/59417 +WT/HK/59418 +WT/HK/59419 +WT/HK/59420 +WT/HK/59422 +WT/HK/59423 +WT/HK/59425 +WT/HK/59427 +WT/HK/59428 +WT/HK/59429 +WT/HK/59431 +WT/HK/59432 +WT/HK/59433 +WT/HK/59434 +WT/HK/59435 +WT/HK/59436 +WT/HK/59437 +WT/HK/59441 +WT/HK/59442 +WT/HK/59443 +WT/HK/59446 +WT/HK/59448 +WT/HK/59450 +WT/HK/59451 +WT/HK/59453 +WT/HK/59457 +WT/HK/59458 +WT/HK/59460 +WT/HK/59461 +WT/HK/59462 +WT/HK/59463 +WT/HK/59464 +WT/HK/59467 +WT/HK/59469 +WT/HK/59470 +WT/HK/59472 +WT/HK/59474 +WT/HK/59475 +WT/HK/59476 +WT/HK/59478 +WT/HK/59479 +WT/HK/59480 +WT/HK/59481 +WT/HK/59490 +WT/HK/59493 +WT/HK/59494 +WT/HK/59502 +WT/HK/59505 +WT/HK/59512 +WT/HK/59519 +WT/HK/59521 +WT/HK/59526 +WT/HK/59533 +WT/HK/59534 +WT/HK/59535 +WT/HK/59537 +WT/HK/59538 +WT/HK/59539 +WT/HK/59540 +WT/HK/59551 +WT/HK/59559 +WT/HK/59560 +WT/HK/59562 +WT/HK/59566 +WT/HK/59567 +WT/HK/59568 +WT/HK/59569 +WT/HK/59570 +WT/HK/59572 +WT/HK/59577 +WT/HK/59579 +WT/HK/59580 +WT/HK/59592 +WT/HK/59598 +WT/HK/59601 +WT/HK/59607 +WT/HK/59609 +WT/HK/59612 +WT/HK/59613 +WT/HK/59619 +WT/HK/59621 +WT/HK/59623 +WT/HK/59625 +WT/HK/59627 +WT/HK/59634 +WT/HK/59643 +WT/HK/59645 +WT/HK/59648 +WT/HK/59656 +WT/HK/59658 +WT/HK/59664 +WT/HK/59674 +WT/HK/59677 +WT/HK/59680 +WT/HK/59682 +WT/HK/59684 +WT/HK/59686 +WT/HK/59687 +WT/HK/59691 +WT/HK/59692 +WT/HK/59715 +WT/HK/59725 +WT/HK/59732 +WT/HK/59733 +WT/HK/59742 +WT/HK/59743 +WT/HK/59744 +WT/HK/59751 +WT/HK/59753 +WT/HK/59757 +WT/HK/59767 +WT/HK/59768 +WT/HK/59770 +WT/HK/59775 +WT/HK/59779 +WT/HK/59781 +WT/HK/59783 +WT/HK/59784 +WT/HK/59791 +WT/HK/59793 +WT/HK/59794 +WT/HK/59795 +WT/HK/59801 +WT/HK/59813 +WT/HK/59814 +WT/HK/59815 +WT/HK/59821 +WT/HK/59824 +WT/HK/59828 +WT/HK/59831 +WT/HK/59832 +WT/HK/59836 +WT/HK/59839 +WT/HK/59849 +WT/HK/59850 +WT/HK/59851 +WT/HK/59852 +WT/HK/59861 +WT/HK/59863 +WT/HK/59867 +WT/HK/59873 +WT/HK/59875 +WT/HK/59877 +WT/HK/59882 +WT/HK/59883 +WT/HK/59887 +WT/HK/59891 +WT/HK/59892 +WT/HK/59897 +WT/HK/59908 +WT/HK/59909 +WT/HK/59911 +WT/HK/59913 +WT/HK/59914 +WT/HK/59917 +WT/HK/59925 +WT/HK/59929 +WT/HK/59932 +WT/HK/59933 +WT/HK/59935 +WT/HK/59937 +WT/HK/59938 +WT/HK/59939 +WT/HK/59941 +WT/HK/59942 +WT/HK/59953 +WT/HK/59962 +WT/HK/59965 +WT/HK/59977 +WT/HK/59982 +WT/HK/59985 +WT/HK/59988 +WT/HK/59990 +WT/HK/59991 +WT/HK/59992 +WT/HK/59994 +WT/HK/59998 +WT/HK/60000 +WT/HK/60002 +WT/HK/60003 +WT/HK/60007 +WT/HK/60008 +WT/HK/60009 +WT/HK/60012 +WT/HK/60014 +WT/HK/60020 +WT/HK/60021 +WT/HK/60022 +WT/HK/60023 +WT/HK/60024 +WT/HK/60026 +WT/HK/60028 +WT/HK/60029 +WT/HK/60030 +WT/HK/60031 +WT/HK/60032 +WT/HK/60036 +WT/HK/60048 +WT/HK/60049 +WT/HK/60050 +WT/HK/60054 +WT/HK/60061 +WT/HK/60062 +WT/HK/60068 +WT/HK/60082 +WT/HK/60083 +WT/HK/60087 +WT/HK/60088 +WT/HK/60091 +WT/HK/60096 +WT/HK/60101 +WT/HK/60103 +WT/HK/60111 +WT/HK/60114 +WT/HK/60125 +WT/HK/60128 +WT/HK/60130 +WT/HK/60138 +WT/HK/60139 +WT/HK/60141 +WT/HK/60142 +WT/HK/60143 +WT/HK/60144 +WT/HK/60145 +WT/HK/60147 +WT/HK/60148 +WT/HK/60149 +WT/HK/60152 +WT/HK/60155 +WT/HK/60156 +WT/HK/60157 +WT/HK/60158 +WT/HK/60160 +WT/HK/60164 +WT/HK/60168 +WT/HK/60170 +WT/HK/60171 +WT/HK/60173 +WT/HK/60174 +WT/HK/60176 +WT/HK/60177 +WT/HK/60179 +WT/HK/60180 +WT/HK/60184 +WT/HK/60190 +WT/HK/60196 +WT/HK/60200 +WT/HK/60201 +WT/HK/60210 +WT/HK/60211 +WT/HK/60217 +WT/HK/60224 +WT/HK/60227 +WT/HK/60236 +WT/HK/60243 +WT/HK/60249 +WT/HK/60255 +WT/HK/60260 +WT/HK/60264 +WT/HK/60265 +WT/HK/60277 +WT/HK/60284 +WT/HK/60285 +WT/HK/60286 +WT/HK/60287 +WT/HK/60288 +WT/HK/60289 +WT/HK/60292 +WT/HK/60295 +WT/HK/60297 +WT/HK/60299 +WT/HK/60304 +WT/HK/60305 +WT/HK/60312 +WT/HK/60325 +WT/HK/60327 +WT/HK/60333 +WT/HK/60340 +WT/HK/60343 +WT/HK/60347 +WT/HK/60349 +WT/HK/60351 +WT/HK/60352 +WT/HK/60353 +WT/HK/60355 +WT/HK/60356 +WT/HK/60357 +WT/HK/60363 +WT/HK/60364 +WT/HK/60366 +WT/HK/60367 +WT/HK/60368 +WT/HK/60373 +WT/HK/60376 +WT/HK/60377 +WT/HK/60378 +WT/HK/60385 +WT/HK/60386 +WT/HK/60387 +WT/HK/60388 +WT/HK/60398 +WT/HK/60410 +WT/HK/60411 +WT/HK/60416 +WT/HK/60417 +WT/HK/60423 +WT/HK/60426 +WT/HK/60427 +WT/HK/60428 +WT/HK/60431 +WT/HK/60433 +WT/HK/60434 +WT/HK/60435 +WT/HK/60436 +WT/HK/60446 +WT/HK/60453 +WT/HK/60462 +WT/HK/60465 +WT/HK/60466 +WT/HK/60468 +WT/HK/60469 +WT/HK/60475 +WT/HK/60476 +WT/HK/60477 +WT/HK/60485 +WT/HK/60486 +WT/HK/60488 +WT/HK/60493 +WT/HK/60502 +WT/HK/60503 +WT/HK/60506 +WT/HK/60508 +WT/HK/60510 +WT/HK/60515 +WT/HK/60520 +WT/HK/60522 +WT/HK/60523 +WT/HK/60524 +WT/HK/60529 +WT/HK/60530 +WT/HK/60541 +WT/HK/60544 +WT/HK/60550 +WT/HK/60555 +WT/HK/60561 +WT/HK/60562 +WT/HK/60563 +WT/HK/60565 +WT/HK/60567 +WT/HK/60568 +WT/HK/60569 +WT/HK/60572 +WT/HK/60573 +WT/HK/60580 +WT/HK/60583 +WT/HK/60590 +WT/HK/60592 +WT/HK/60599 +WT/HK/60602 +WT/HK/60604 +WT/HK/60606 +WT/HK/60610 +WT/HK/60612 +WT/HK/60613 +WT/HK/60616 +WT/HK/60621 +WT/HK/60624 +WT/HK/60626 +WT/HK/60629 +WT/HK/60642 +WT/HK/60645 +WT/HK/60646 +WT/HK/60647 +WT/HK/60648 +WT/HK/60652 +WT/HK/60653 +WT/HK/60656 +WT/HK/60663 +WT/HK/60664 +WT/HK/60665 +WT/HK/60668 +WT/HK/60669 +WT/HK/60671 +WT/HK/60672 +WT/HK/60682 +WT/HK/60693 +WT/HK/60701 +WT/HK/60704 +WT/HK/60710 +WT/HK/60712 +WT/HK/60714 +WT/HK/60716 +WT/HK/60718 +WT/HK/60719 +WT/HK/60721 +WT/HK/60723 +WT/HK/60725 +WT/HK/60726 +WT/HK/60727 +WT/HK/60729 +WT/HK/60736 +WT/HK/60737 +WT/HK/60738 +WT/HK/60739 +WT/HK/60744 +WT/HK/60745 +WT/HK/60746 +WT/HK/60747 +WT/HK/60752 +WT/HK/60754 +WT/HK/60758 +WT/HK/60761 +WT/HK/60765 +WT/HK/60771 +WT/HK/60772 +WT/HK/60774 +WT/HK/60775 +WT/HK/60777 +WT/HK/60779 +WT/HK/60780 +WT/HK/60782 +WT/HK/60787 +WT/HK/60789 +WT/HK/60794 +WT/HK/60795 +WT/HK/60796 +WT/HK/60797 +WT/HK/60798 +WT/HK/60803 +WT/HK/60805 +WT/HK/60809 +WT/HK/60816 +WT/HK/60817 +WT/HK/60821 +WT/HK/60824 +WT/HK/60826 +WT/HK/60829 +WT/HK/60833 +WT/HK/60834 +WT/HK/60836 +WT/HK/60839 +WT/HK/60841 +WT/HK/60842 +WT/HK/60843 +WT/HK/60844 +WT/HK/60847 +WT/HK/60849 +WT/HK/60854 +WT/HK/60863 +WT/HK/60865 +WT/HK/60866 +WT/HK/60873 +WT/HK/60875 +WT/HK/60876 +WT/HK/60877 +WT/HK/60878 +WT/HK/60882 +WT/HK/60883 +WT/HK/60884 +WT/HK/60886 +WT/HK/60889 +WT/HK/60890 +WT/HK/60891 +WT/HK/60892 +WT/HK/60893 +WT/HK/60896 +WT/HK/60897 +WT/HK/60898 +WT/HK/60905 +WT/HK/60906 +WT/HK/60911 +WT/HK/60912 +WT/HK/60916 +WT/HK/60923 +WT/HK/60928 +WT/HK/60938 +WT/HK/60941 +WT/HK/60942 +WT/HK/60945 +WT/HK/60948 +WT/HK/60950 +WT/HK/60956 +WT/HK/60958 +WT/HK/60959 +WT/HK/60964 +WT/HK/60967 +WT/HK/60970 +WT/HK/60976 +WT/HK/60981 +WT/HK/60983 +WT/HK/60987 +WT/HK/60992 +WT/HK/60994 +WT/HK/60997 +WT/HK/60998 +WT/HK/60999 +WT/HK/61007 +WT/HK/61009 +WT/HK/61013 +WT/HK/61016 +WT/HK/61017 +WT/HK/61018 +WT/HK/61026 +WT/HK/61030 +WT/HK/61033 +WT/HK/61042 +WT/HK/61043 +WT/HK/61053 +WT/HK/61054 +WT/HK/61055 +WT/HK/61056 +WT/HK/61057 +WT/HK/61062 +WT/HK/61070 +WT/HK/61072 +WT/HK/61077 +WT/HK/61088 +WT/HK/61089 +WT/HK/61103 +WT/HK/61104 +WT/HK/61110 +WT/HK/61113 +WT/HK/61120 +WT/HK/61121 +WT/HK/61122 +WT/HK/61125 +WT/HK/61128 +WT/HK/61134 +WT/HK/61138 +WT/HK/61141 +WT/HK/61150 +WT/HK/61157 +WT/HK/61158 +WT/HK/61159 +WT/HK/61161 +WT/HK/61162 +WT/HK/61165 +WT/HK/61184 +WT/HK/61185 +WT/HK/61194 +WT/HK/61195 +WT/HK/61197 +WT/HK/61198 +WT/HK/61199 +WT/HK/61200 +WT/HK/61202 +WT/HK/61203 +WT/HK/61205 +WT/HK/61207 +WT/HK/61212 +WT/HK/61213 +WT/HK/61214 +WT/HK/61217 +WT/HK/61222 +WT/HK/61223 +WT/HK/61227 +WT/HK/61229 +WT/HK/61230 +WT/HK/61235 +WT/HK/61242 +WT/HK/61243 +WT/HK/61249 +WT/HK/61251 +WT/HK/61254 +WT/HK/61255 +WT/HK/61256 +WT/HK/61258 +WT/HK/61259 +WT/HK/61262 +WT/HK/61263 +WT/HK/61267 +WT/HK/61268 +WT/HK/61269 +WT/HK/61272 +WT/HK/61273 +WT/HK/61274 +WT/HK/61278 +WT/HK/61280 +WT/HK/61284 +WT/HK/61288 +WT/HK/61295 +WT/HK/61296 +WT/HK/61297 +WT/HK/61298 +WT/HK/61299 +WT/HK/61303 +WT/HK/61304 +WT/HK/61305 +WT/HK/61312 +WT/HK/61317 +WT/HK/61318 +WT/HK/61320 +WT/HK/61322 +WT/HK/61323 +WT/HK/61324 +WT/HK/61326 +WT/HK/61332 +WT/HK/61333 +WT/HK/61334 +WT/HK/61335 +WT/HK/61337 +WT/HK/61339 +WT/HK/61342 +WT/HK/61343 +WT/HK/61344 +WT/HK/61347 +WT/HK/61349 +WT/HK/61351 +WT/HK/61352 +WT/HK/61355 +WT/HK/61356 +WT/HK/61357 +WT/HK/61358 +WT/HK/61359 +WT/HK/61360 +WT/HK/61361 +WT/HK/61362 +WT/HK/61364 +WT/HK/61379 +WT/HK/61380 +WT/HK/61381 +WT/HK/61382 +WT/HK/61384 +WT/HK/61386 +WT/HK/61387 +WT/HK/61394 +WT/HK/61395 +WT/HK/61397 +WT/HK/61399 +WT/HK/61400 +WT/HK/61402 +WT/HK/61405 +WT/HK/61407 +WT/HK/61412 +WT/HK/61414 +WT/HK/61416 +WT/HK/61417 +WT/HK/61419 +WT/HK/61422 +WT/HK/61423 +WT/HK/61431 +WT/HK/61433 +WT/HK/61437 +WT/HK/61438 +WT/HK/61442 +WT/HK/61444 +WT/HK/61446 +WT/HK/61447 +WT/HK/61450 +WT/HK/61451 +WT/HK/61455 +WT/HK/61456 +WT/HK/61463 +WT/HK/61470 +WT/HK/61471 +WT/HK/61472 +WT/HK/61473 +WT/HK/61476 +WT/HK/61481 +WT/HK/61486 +WT/HK/61488 +WT/HK/61489 +WT/HK/61490 +WT/HK/61491 +WT/HK/61497 +WT/HK/61501 +WT/HK/61505 +WT/HK/61509 +WT/HK/61513 +WT/HK/61515 +WT/HK/61519 +WT/HK/61521 +WT/HK/61524 +WT/HK/61531 +WT/HK/61532 +WT/HK/61536 +WT/HK/61538 +WT/HK/61540 +WT/HK/61541 +WT/HK/61551 +WT/HK/61552 +WT/HK/61554 +WT/HK/61556 +WT/HK/61564 +WT/HK/61566 +WT/HK/61568 +WT/HK/61573 +WT/HK/61574 +WT/HK/61575 +WT/HK/61578 +WT/HK/61583 +WT/HK/61599 +WT/HK/61600 +WT/HK/61601 +WT/HK/61602 +WT/HK/61606 +WT/HK/61608 +WT/HK/61611 +WT/HK/61612 +WT/HK/61613 +WT/HK/61614 +WT/HK/61615 +WT/HK/61617 +WT/HK/61622 +WT/HK/61628 +WT/HK/61637 +WT/HK/61638 +WT/HK/61639 +WT/HK/61640 +WT/HK/61642 +WT/HK/61647 +WT/HK/61648 +WT/HK/61650 +WT/HK/61661 +WT/HK/61670 +WT/HK/61677 +WT/HK/61679 +WT/HK/61680 +WT/HK/61682 +WT/HK/61683 +WT/HK/61685 +WT/HK/61686 +WT/HK/61687 +WT/HK/61688 +WT/HK/61691 +WT/HK/61694 +WT/HK/61696 +WT/HK/61697 +WT/HK/61702 +WT/HK/61705 +WT/HK/61711 +WT/HK/61714 +WT/HK/61716 +WT/HK/61720 +WT/HK/61721 +WT/HK/61724 +WT/HK/61725 +WT/HK/61727 +WT/HK/61730 +WT/HK/61732 +WT/HK/61733 +WT/HK/61738 +WT/HK/61740 +WT/HK/61741 +WT/HK/61757 +WT/HK/61758 +WT/HK/61759 +WT/HK/61760 +WT/HK/61761 +WT/HK/61768 +WT/HK/61769 +WT/HK/61770 +WT/HK/61772 +WT/HK/61773 +WT/HK/61774 +WT/HK/61776 +WT/HK/61777 +WT/HK/61778 +WT/HK/61780 +WT/HK/61781 +WT/HK/61785 +WT/HK/61786 +WT/HK/61791 +WT/HK/61792 +WT/HK/61798 +WT/HK/61803 +WT/HK/61804 +WT/HK/61805 +WT/HK/61806 +WT/HK/61808 +WT/HK/61810 +WT/HK/61813 +WT/HK/61817 +WT/HK/61819 +WT/HK/61821 +WT/HK/61823 +WT/HK/61825 +WT/HK/61829 +WT/HK/61831 +WT/HK/61833 +WT/HK/61834 +WT/HK/61837 +WT/HK/61838 +WT/HK/61839 +WT/HK/61840 +WT/HK/61841 +WT/HK/61847 +WT/HK/61852 +WT/HK/61856 +WT/HK/61858 +WT/HK/61859 +WT/HK/61860 +WT/HK/61862 +WT/HK/61864 +WT/HK/61866 +WT/HK/61870 +WT/HK/61871 +WT/HK/61873 +WT/HK/61878 +WT/HK/61880 +WT/HK/61882 +WT/HK/61889 +WT/HK/61890 +WT/HK/61891 +WT/HK/61893 +WT/HK/61894 +WT/HK/61895 +WT/HK/61896 +WT/HK/61897 +WT/HK/61900 +WT/HK/61902 +WT/HK/61904 +WT/HK/61906 +WT/HK/61910 +WT/HK/61911 +WT/HK/61913 +WT/HK/61915 +WT/HK/61917 +WT/HK/61918 +WT/HK/61919 +WT/HK/61922 +WT/HK/61923 +WT/HK/61924 +WT/HK/61928 +WT/HK/61932 +WT/HK/61934 +WT/HK/61935 +WT/HK/61936 +WT/HK/61937 +WT/HK/61939 +WT/HK/61940 +WT/HK/61943 +WT/HK/61946 +WT/HK/61947 +WT/HK/61948 +WT/HK/61951 +WT/HK/61952 +WT/HK/61955 +WT/HK/61957 +WT/HK/61958 +WT/HK/61959 +WT/HK/61960 +WT/HK/61966 +WT/HK/61968 +WT/HK/61971 +WT/HK/61972 +WT/HK/61976 +WT/HK/61977 +WT/HK/61978 +WT/HK/61981 +WT/HK/61982 +WT/HK/61983 +WT/HK/61986 +WT/HK/61991 +WT/HK/61992 +WT/HK/61993 +WT/HK/61997 +WT/HK/62000 +WT/HK/62002 +WT/HK/62013 +WT/HK/62014 +WT/HK/62020 +WT/HK/62021 +WT/HK/62026 +WT/HK/62027 +WT/HK/62032 +WT/HK/62034 +WT/HK/62035 +WT/HK/62036 +WT/HK/62038 +WT/HK/62040 +WT/HK/62041 +WT/HK/62045 +WT/HK/62051 +WT/HK/62053 +WT/HK/62054 +WT/HK/62058 +WT/HK/62059 +WT/HK/62061 +WT/HK/62062 +WT/HK/62071 +WT/HK/62072 +WT/HK/62073 +WT/HK/62074 +WT/HK/62078 +WT/HK/62079 +WT/HK/62091 +WT/HK/62096 +WT/HK/62097 +WT/HK/62098 +WT/HK/62102 +WT/HK/62103 +WT/HK/62105 +WT/HK/62108 +WT/HK/62111 +WT/HK/62112 +WT/HK/62115 +WT/HK/62119 +WT/HK/62131 +WT/HK/62134 +WT/HK/62136 +WT/HK/62137 +WT/HK/62138 +WT/HK/62139 +WT/HK/62143 +WT/HK/62146 +WT/HK/62148 +WT/HK/62150 +WT/HK/62151 +WT/HK/62152 +WT/HK/62155 +WT/HK/62157 +WT/HK/62159 +WT/HK/62161 +WT/HK/62162 +WT/HK/62164 +WT/HK/62165 +WT/HK/62166 +WT/HK/62167 +WT/HK/62172 +WT/HK/62173 +WT/HK/62177 +WT/HK/62178 +WT/HK/62181 +WT/HK/62182 +WT/HK/62188 +WT/HK/62190 +WT/HK/62191 +WT/HK/62197 +WT/HK/62198 +WT/HK/62200 +WT/HK/62202 +WT/HK/62205 +WT/HK/62206 +WT/HK/62207 +WT/HK/62208 +WT/HK/62218 +WT/HK/62219 +WT/HK/62221 +WT/HK/62222 +WT/HK/62225 +WT/HK/62226 +WT/HK/62228 +WT/HK/62229 +WT/HK/62231 +WT/HK/62232 +WT/HK/62235 +WT/HK/62243 +WT/HK/62247 +WT/HK/62249 +WT/HK/62250 +WT/HK/62251 +WT/HK/62253 +WT/HK/62254 +WT/HK/62255 +WT/HK/62256 +WT/HK/62258 +WT/HK/62259 +WT/HK/62261 +WT/HK/62263 +WT/HK/62266 +WT/HK/62271 +WT/HK/62272 +WT/HK/62276 +WT/HK/62277 +WT/HK/62280 +WT/HK/62282 +WT/HK/62283 +WT/HK/62287 +WT/HK/62289 +WT/HK/62290 +WT/HK/62291 +WT/HK/62293 +WT/HK/62295 +WT/HK/62300 +WT/HK/62301 +WT/HK/62303 +WT/HK/62304 +WT/HK/62305 +WT/HK/62306 +WT/HK/62308 +WT/HK/62309 +WT/HK/62310 +WT/HK/62311 +WT/HK/62312 +WT/HK/62314 +WT/HK/62315 +WT/HK/62316 +WT/HK/62318 +WT/HK/62319 +WT/HK/62320 +WT/HK/62321 +WT/HK/62326 +WT/HK/62328 +WT/HK/62330 +WT/HK/62332 +WT/HK/62336 +WT/HK/62338 +WT/HK/62342 +WT/HK/62343 +WT/HK/62344 +WT/HK/62345 +WT/HK/62346 +WT/HK/62347 +WT/HK/62349 +WT/HK/62351 +WT/HK/62359 +WT/HK/62361 +WT/HK/62362 +WT/HK/62369 +WT/HK/62372 +WT/HK/62373 +WT/HK/62375 +WT/HK/62377 +WT/HK/62379 +WT/HK/62380 +WT/HK/62383 +WT/HK/62385 +WT/HK/62387 +WT/HK/62390 +WT/HK/62392 +WT/HK/62398 +WT/HK/62399 +WT/HK/62401 +WT/HK/62402 +WT/HK/62405 +WT/HK/62406 +WT/HK/62407 +WT/HK/62408 +WT/HK/62409 +WT/HK/62410 +WT/HK/62411 +WT/HK/62412 +WT/HK/62413 +WT/HK/62414 +WT/HK/62416 +WT/HK/62417 +WT/HK/62418 +WT/HK/62419 +WT/HK/62422 +WT/HK/62423 +WT/HK/62424 +WT/HK/62426 +WT/HK/62430 +WT/HK/62433 +WT/HK/62434 +WT/HK/62435 +WT/HK/62436 +WT/HK/62437 +WT/HK/62438 +WT/HK/62439 +WT/HK/62441 +WT/HK/62446 +WT/HK/62447 +WT/HK/62449 +WT/HK/62450 +WT/HK/62451 +WT/HK/62454 +WT/HK/62460 +WT/HK/62461 +WT/HK/62469 +WT/HK/62476 +WT/HK/62481 +WT/HK/62482 +WT/HK/62487 +WT/HK/62488 +WT/HK/62489 +WT/HK/62492 +WT/HK/62493 +WT/HK/62494 +WT/HK/62501 +WT/HK/62503 +WT/HK/62505 +WT/HK/62507 +WT/HK/62508 +WT/HK/62518 +WT/HK/62529 +WT/HK/62531 +WT/HK/62532 +WT/HK/62533 +WT/HK/62543 +WT/HK/62544 +WT/HK/62548 +WT/HK/62549 +WT/HK/62551 +WT/HK/62554 +WT/HK/62562 +WT/HK/62567 +WT/HK/62568 +WT/HK/62571 +WT/HK/62572 +WT/HK/62577 +WT/HK/62583 +WT/HK/62584 +WT/HK/62590 +WT/HK/62599 +WT/HK/62603 +WT/HK/62607 +WT/HK/62612 +WT/HK/62615 +WT/HK/62616 +WT/HK/62623 +WT/HK/62625 +WT/HK/62630 +WT/HK/62631 +WT/HK/62633 +WT/HK/62638 +WT/HK/62640 +WT/HK/62643 +WT/HK/62651 +WT/HK/62652 +WT/HK/62653 +WT/HK/62655 +WT/HK/62659 +WT/HK/62660 +WT/HK/62663 +WT/HK/62666 +WT/HK/62667 +WT/HK/62670 +WT/HK/62676 +WT/HK/62677 +WT/HK/62692 +WT/HK/62693 +WT/HK/62694 +WT/HK/62695 +WT/HK/62697 +WT/HK/62700 +WT/HK/62705 +WT/HK/62708 +WT/HK/62709 +WT/HK/62711 +WT/HK/62712 +WT/HK/62713 +WT/HK/62714 +WT/HK/62715 +WT/HK/62717 +WT/HK/62719 +WT/HK/62720 +WT/HK/62722 +WT/HK/62723 +WT/HK/62725 +WT/HK/62727 +WT/HK/62735 +WT/HK/62737 +WT/HK/62739 +WT/HK/62741 +WT/HK/62747 +WT/HK/62750 +WT/HK/62752 +WT/HK/62755 +WT/HK/62756 +WT/HK/62761 +WT/HK/62762 +WT/HK/62763 +WT/HK/62767 +WT/HK/62770 +WT/HK/62771 +WT/HK/62772 +WT/HK/62783 +WT/HK/62785 +WT/HK/62787 +WT/HK/62789 +WT/HK/62790 +WT/HK/62792 +WT/HK/62798 +WT/HK/62800 +WT/HK/62803 +WT/HK/62804 +WT/HK/62815 +WT/HK/62816 +WT/HK/62818 +WT/HK/62819 +WT/HK/62820 +WT/HK/62822 +WT/HK/62823 +WT/HK/62825 +WT/HK/62826 +WT/HK/62828 +WT/HK/62835 +WT/HK/62838 +WT/HK/62840 +WT/HK/62845 +WT/HK/62849 +WT/HK/62852 +WT/HK/62856 +WT/HK/62858 +WT/HK/62859 +WT/HK/62861 +WT/HK/62862 +WT/HK/62866 +WT/HK/62871 +WT/HK/62873 +WT/HK/62875 +WT/HK/62877 +WT/HK/62880 +WT/HK/62886 +WT/HK/62890 +WT/HK/62891 +WT/HK/62893 +WT/HK/62898 +WT/HK/62899 +WT/HK/62901 +WT/HK/62903 +WT/HK/62907 +WT/HK/62908 +WT/HK/62911 +WT/HK/62912 +WT/HK/62914 +WT/HK/62915 +WT/HK/62918 +WT/HK/62919 +WT/HK/62923 +WT/HK/62924 +WT/HK/62928 +WT/HK/62929 +WT/HK/62937 +WT/HK/62939 +WT/HK/62940 +WT/HK/62943 +WT/HK/62949 +WT/HK/62951 +WT/HK/62952 +WT/HK/62958 +WT/HK/62959 +WT/HK/62960 +WT/HK/62961 +WT/HK/62965 +WT/HK/62968 +WT/HK/62969 +WT/HK/62970 +WT/HK/62971 +WT/HK/62972 +WT/HK/62983 +WT/HK/62988 +WT/HK/62992 +WT/HK/62993 +WT/HK/62994 +WT/HK/62998 +WT/HK/63000 +WT/HK/63008 +WT/HK/63012 +WT/HK/63013 +WT/HK/63017 +WT/HK/63020 +WT/HK/63021 +WT/HK/63022 +WT/HK/63025 +WT/HK/63026 +WT/HK/63034 +WT/HK/63039 +WT/HK/63045 +WT/HK/63046 +WT/HK/63047 +WT/HK/63048 +WT/HK/63049 +WT/HK/63050 +WT/HK/63051 +WT/HK/63052 +WT/HK/63053 +WT/HK/63054 +WT/HK/63055 +WT/HK/63059 +WT/HK/63060 +WT/HK/63065 +WT/HK/63067 +WT/HK/63071 +WT/HK/63073 +WT/HK/63081 +WT/HK/63082 +WT/HK/63085 +WT/HK/63088 +WT/HK/63092 +WT/HK/63094 +WT/HK/63095 +WT/HK/63105 +WT/HK/63106 +WT/HK/63108 +WT/HK/63111 +WT/HK/63112 +WT/HK/63113 +WT/HK/63114 +WT/HK/63115 +WT/HK/63120 +WT/HK/63123 +WT/HK/63125 +WT/HK/63126 +WT/HK/63133 +WT/HK/63136 +WT/HK/63137 +WT/HK/63151 +WT/HK/63158 +WT/HK/63169 +WT/HK/63170 +WT/HK/63175 +WT/HK/63177 +WT/HK/63182 +WT/HK/63183 +WT/HK/63184 +WT/HK/63185 +WT/HK/63186 +WT/HK/63189 +WT/HK/63193 +WT/HK/63197 +WT/HK/63201 +WT/HK/63202 +WT/HK/63203 +WT/HK/63207 +WT/HK/63208 +WT/HK/63211 +WT/HK/63217 +WT/HK/63218 +WT/HK/63224 +WT/HK/63232 +WT/HK/63237 +WT/HK/63239 +WT/HK/63244 +WT/HK/63246 +WT/HK/63249 +WT/HK/63250 +WT/HK/63251 +WT/HK/63256 +WT/HK/63257 +WT/HK/63258 +WT/HK/63264 +WT/HK/63266 +WT/HK/63267 +WT/HK/63270 +WT/HK/63276 +WT/HK/63278 +WT/HK/63280 +WT/HK/63281 +WT/HK/63283 +WT/HK/63287 +WT/HK/63290 +WT/HK/63291 +WT/HK/63296 +WT/HK/63297 +WT/HK/63308 +WT/HK/63309 +WT/HK/63313 +WT/HK/63320 +WT/HK/63322 +WT/HK/63329 +WT/HK/63330 +WT/HK/63332 +WT/HK/63333 +WT/HK/63334 +WT/HK/63339 +WT/HK/63353 +WT/HK/63354 +WT/HK/63355 +WT/HK/63356 +WT/HK/63359 +WT/HK/63361 +WT/HK/63364 +WT/HK/63369 +WT/HK/63372 +WT/HK/63374 +WT/HK/63380 +WT/HK/63381 +WT/HK/63388 +WT/HK/63390 +WT/HK/63395 +WT/HK/63400 +WT/HK/63402 +WT/HK/63404 +WT/HK/63412 +WT/HK/63415 +WT/HK/63419 +WT/HK/63423 +WT/HK/63424 +WT/HK/63436 +WT/HK/63441 +WT/HK/63442 +WT/HK/63446 +WT/HK/63464 +WT/HK/63467 +WT/HK/63476 +WT/HK/63478 +WT/HK/63481 +WT/HK/63485 +WT/HK/63487 +WT/HK/63491 +WT/HK/63492 +WT/HK/63496 +WT/HK/63497 +WT/HK/63500 +WT/HK/63503 +WT/HK/63508 +WT/HK/63510 +WT/HK/63511 +WT/HK/63513 +WT/HK/63517 +WT/HK/63522 +WT/HK/63525 +WT/HK/63529 +WT/HK/63531 +WT/HK/63532 +WT/HK/63533 +WT/HK/63534 +WT/HK/63535 +WT/HK/63540 +WT/HK/63543 +WT/HK/63545 +WT/HK/63546 +WT/HK/63547 +WT/HK/63548 +WT/HK/63549 +WT/HK/63550 +WT/HK/63551 +WT/HK/63552 +WT/HK/63554 +WT/HK/63556 +WT/HK/63558 +WT/HK/63562 +WT/HK/63564 +WT/HK/63569 +WT/HK/63575 +WT/HK/63577 +WT/HK/63582 +WT/HK/63585 +WT/HK/63587 +WT/HK/63593 +WT/HK/63598 +WT/HK/63603 +WT/HK/63604 +WT/HK/63605 +WT/HK/63606 +WT/HK/63609 +WT/HK/63611 +WT/HK/63613 +WT/HK/63614 +WT/HK/63617 +WT/HK/63619 +WT/HK/63620 +WT/HK/63637 +WT/HK/63639 +WT/HK/63646 +WT/HK/63651 +WT/HK/63652 +WT/HK/63653 +WT/HK/63654 +WT/HK/63657 +WT/HK/63658 +WT/HK/63664 +WT/HK/63667 +WT/HK/63689 +WT/HK/63694 +WT/HK/63705 +WT/HK/63706 +WT/HK/63707 +WT/HK/63711 +WT/HK/63720 +WT/HK/63722 +WT/HK/63733 +WT/HK/63739 +WT/HK/63741 +WT/HK/63742 +WT/HK/63743 +WT/HK/63744 +WT/HK/63745 +WT/HK/63746 +WT/HK/63747 +WT/HK/63750 +WT/HK/63753 +WT/HK/63756 +WT/HK/63757 +WT/HK/63758 +WT/HK/63760 +WT/HK/63762 +WT/HK/63765 +WT/HK/63766 +WT/HK/63768 +WT/HK/63773 +WT/HK/63774 +WT/HK/63776 +WT/HK/63777 +WT/HK/63778 +WT/HK/63781 +WT/HK/63784 +WT/HK/63786 +WT/HK/63787 +WT/HK/63789 +WT/HK/63792 +WT/HK/63793 +WT/HK/63797 +WT/HK/63802 +WT/HK/63803 +WT/HK/63805 +WT/HK/63807 +WT/HK/63808 +WT/HK/63809 +WT/HK/63811 +WT/HK/63815 +WT/HK/63816 +WT/HK/63819 +WT/HK/63820 +WT/HK/63822 +WT/HK/63829 +WT/HK/63830 +WT/HK/63838 +WT/HK/63846 +WT/HK/63847 +WT/HK/63849 +WT/HK/63850 +WT/HK/63851 +WT/HK/63852 +WT/HK/63854 +WT/HK/63855 +WT/HK/63857 +WT/HK/63860 +WT/HK/63862 +WT/HK/63875 +WT/HK/63878 +WT/HK/63880 +WT/HK/63881 +WT/HK/63885 +WT/HK/63886 +WT/HK/63888 +WT/HK/63890 +WT/HK/63891 +WT/HK/63896 +WT/HK/63897 +WT/HK/63901 +WT/HK/63903 +WT/HK/63906 +WT/HK/63912 +WT/HK/63915 +WT/HK/63917 +WT/HK/63921 +WT/HK/63923 +WT/HK/63926 +WT/HK/63929 +WT/HK/63934 +WT/HK/63936 +WT/HK/63946 +WT/HK/63953 +WT/HK/63955 +WT/HK/63967 +WT/HK/63968 +WT/HK/63975 +WT/HK/63988 +WT/HK/64012 +WT/HK/64017 +WT/HK/64020 +WT/HK/64027 +WT/HK/64030 +WT/HK/64031 +WT/HK/64041 +WT/HK/64042 +WT/HK/64052 +WT/HK/64060 +WT/HK/64063 +WT/HK/64066 +WT/HK/64069 +WT/HK/64071 +WT/HK/64075 +WT/HK/64078 +WT/HK/64079 +WT/HK/64080 +WT/HK/64081 +WT/HK/64082 +WT/HK/64085 +WT/HK/64086 +WT/HK/64090 +WT/HK/64091 +WT/HK/64092 +WT/HK/64100 +WT/HK/64101 +WT/HK/64103 +WT/HK/64104 +WT/HK/64105 +WT/HK/64108 +WT/HK/64110 +WT/HK/64116 +WT/HK/64118 +WT/HK/64119 +WT/HK/64120 +WT/HK/64122 +WT/HK/64123 +WT/HK/64127 +WT/HK/64130 +WT/HK/64134 +WT/HK/64143 +WT/HK/64148 +WT/HK/64149 +WT/HK/64151 +WT/HK/64153 +WT/HK/64154 +WT/HK/64155 +WT/HK/64156 +WT/HK/64157 +WT/HK/64158 +WT/HK/64159 +WT/HK/64160 +WT/HK/64161 +WT/HK/64164 +WT/HK/64165 +WT/HK/64167 +WT/HK/64168 +WT/HK/64169 +WT/HK/64171 +WT/HK/64172 +WT/HK/64176 +WT/HK/64177 +WT/HK/64178 +WT/HK/64180 +WT/HK/64181 +WT/HK/64186 +WT/HK/64187 +WT/HK/64190 +WT/HK/64191 +WT/HK/64193 +WT/HK/64194 +WT/HK/64203 +WT/HK/64206 +WT/HK/64209 +WT/HK/64210 +WT/HK/64216 +WT/HK/64218 +WT/HK/64220 +WT/HK/64225 +WT/HK/64226 +WT/HK/64227 +WT/HK/64229 +WT/HK/64230 +WT/HK/64231 +WT/HK/64233 +WT/HK/64234 +WT/HK/64239 +WT/HK/64241 +WT/HK/64245 +WT/HK/64247 +WT/HK/64253 +WT/HK/64254 +WT/HK/64255 +WT/HK/64257 +WT/HK/64260 +WT/HK/64261 +WT/HK/64263 +WT/HK/64265 +WT/HK/64267 +WT/HK/64268 +WT/HK/64274 +WT/HK/64276 +WT/HK/64277 +WT/HK/64283 +WT/HK/64287 +WT/HK/64293 +WT/HK/64294 +WT/HK/64295 +WT/HK/64301 +WT/HK/64304 +WT/HK/64305 +WT/HK/64306 +WT/HK/64308 +WT/HK/64312 +WT/HK/64313 +WT/HK/64315 +WT/HK/64317 +WT/HK/64318 +WT/HK/64325 +WT/HK/64327 +WT/HK/64329 +WT/HK/64331 +WT/HK/64343 +WT/HK/64347 +WT/HK/64348 +WT/HK/64350 +WT/HK/64359 +WT/HK/64361 +WT/HK/64369 +WT/HK/64373 +WT/HK/64374 +WT/HK/64378 +WT/HK/64379 +WT/HK/64383 +WT/HK/64392 +WT/HK/64396 +WT/HK/64460 +WT/HK/64473 +WT/HK/64484 +WT/HK/64491 +WT/HK/64493 +WT/HK/64509 +WT/HK/64510 +WT/HK/64511 +WT/HK/64512 +WT/HK/64516 +WT/HK/64518 +WT/HK/64520 +WT/HK/64521 +WT/HK/64522 +WT/HK/64525 +WT/HK/64529 +WT/HK/64531 +WT/HK/64536 +WT/HK/64547 +WT/HK/64549 +WT/HK/64550 +WT/HK/64551 +WT/HK/64553 +WT/HK/64556 +WT/HK/64557 +WT/HK/64566 +WT/HK/64567 +WT/HK/64570 +WT/HK/64573 +WT/HK/64574 +WT/HK/64577 +WT/HK/64578 +WT/HK/64581 +WT/HK/64584 +WT/HK/64586 +WT/HK/64587 +WT/HK/64591 +WT/HK/64592 +WT/HK/64594 +WT/HK/64595 +WT/HK/64600 +WT/HK/64604 +WT/HK/64605 +WT/HK/64606 +WT/HK/64608 +WT/HK/64611 +WT/HK/64612 +WT/HK/64613 +WT/HK/64615 +WT/HK/64617 +WT/HK/64618 +WT/HK/64619 +WT/HK/64620 +WT/HK/64623 +WT/HK/64625 +WT/HK/64628 +WT/HK/64632 +WT/HK/64633 +WT/HK/64635 +WT/HK/64636 +WT/HK/64640 +WT/HK/64655 +WT/HK/64665 +WT/HK/64667 +WT/HK/64678 +WT/HK/64686 +WT/HK/64687 +WT/HK/64688 +WT/HK/64690 +WT/HK/64697 +WT/HK/64704 +WT/HK/64706 +WT/HK/64710 +WT/HK/64715 +WT/HK/64717 +WT/HK/64718 +WT/HK/64719 +WT/HK/64721 +WT/HK/64722 +WT/HK/64723 +WT/HK/64724 +WT/HK/64725 +WT/HK/64731 +WT/HK/64734 +WT/HK/64737 +WT/HK/64738 +WT/HK/64740 +WT/HK/64741 +WT/HK/64746 +WT/HK/64750 +WT/HK/64751 +WT/HK/64753 +WT/HK/64754 +WT/HK/64758 +WT/HK/64761 +WT/HK/64764 +WT/HK/64768 +WT/HK/64769 +WT/HK/64787 +WT/HK/64788 +WT/HK/64795 +WT/HK/64799 +WT/HK/64804 +WT/HK/64807 +WT/HK/64809 +WT/HK/64812 +WT/HK/64817 +WT/HK/64824 +WT/HK/64826 +WT/HK/64836 +WT/HK/64838 +WT/HK/64840 +WT/HK/64843 +WT/HK/64848 +WT/HK/64849 +WT/HK/64850 +WT/HK/64851 +WT/HK/64852 +WT/HK/64854 +WT/HK/64863 +WT/HK/64874 +WT/HK/64876 +WT/HK/64880 +WT/HK/64884 +WT/HK/64891 +WT/HK/64892 +WT/HK/64894 +WT/HK/64896 +WT/HK/64899 +WT/HK/64902 +WT/HK/64903 +WT/HK/64904 +WT/HK/64906 +WT/HK/64910 +WT/HK/64920 +WT/HK/64921 +WT/HK/64923 +WT/HK/64924 +WT/HK/64925 +WT/HK/64927 +WT/HK/64929 +WT/HK/64930 +WT/HK/64933 +WT/HK/64934 +WT/HK/64935 +WT/HK/64937 +WT/HK/64938 +WT/HK/64939 +WT/HK/64940 +WT/HK/64942 +WT/HK/64946 +WT/HK/64947 +WT/HK/64948 +WT/HK/64949 +WT/HK/64951 +WT/HK/64960 +WT/HK/64963 +WT/HK/64965 +WT/HK/64966 +WT/HK/64973 +WT/HK/64974 +WT/HK/64977 +WT/HK/64978 +WT/HK/64981 +WT/HK/64983 +WT/HK/64984 +WT/HK/64985 +WT/HK/64986 +WT/HK/64991 +WT/HK/64994 +WT/HK/64996 +WT/HK/64997 +WT/HK/64999 +WT/HK/65001 +WT/HK/65002 +WT/HK/65003 +WT/HK/65004 +WT/HK/65005 +WT/HK/65006 +WT/HK/65010 +WT/HK/65011 +WT/HK/65015 +WT/HK/65016 +WT/HK/65018 +WT/HK/65020 +WT/HK/65022 +WT/HK/65023 +WT/HK/65025 +WT/HK/65026 +WT/HK/65028 +WT/HK/65033 +WT/HK/65034 +WT/HK/65040 +WT/HK/65041 +WT/HK/65043 +WT/HK/65060 +WT/HK/65061 +WT/HK/65062 +WT/HK/65064 +WT/HK/65065 +WT/HK/65068 +WT/HK/65071 +WT/HK/65074 +WT/HK/65076 +WT/HK/65079 +WT/HK/65082 +WT/HK/65083 +WT/HK/65087 +WT/HK/65090 +WT/HK/65091 +WT/HK/65092 +WT/HK/65093 +WT/HK/65097 +WT/HK/65099 +WT/HK/65100 +WT/HK/65101 +WT/HK/65111 +WT/HK/65112 +WT/HK/65113 +WT/HK/65114 +WT/HK/65122 +WT/HK/65124 +WT/HK/65126 +WT/HK/65131 +WT/HK/65134 +WT/HK/65137 +WT/HK/65143 +WT/HK/65144 +WT/HK/65145 +WT/HK/65147 +WT/HK/65148 +WT/HK/65150 +WT/HK/65151 +WT/HK/65157 +WT/HK/65158 +WT/HK/65160 +WT/HK/65162 +WT/HK/65165 +WT/HK/65168 +WT/HK/65170 +WT/HK/65172 +WT/HK/65175 +WT/HK/65176 +WT/HK/65177 +WT/HK/65178 +WT/HK/65179 +WT/HK/65180 +WT/HK/65184 +WT/HK/65185 +WT/HK/65186 +WT/HK/65187 +WT/HK/65188 +WT/HK/65189 +WT/HK/65192 +WT/HK/65194 +WT/HK/65195 +WT/HK/65198 +WT/HK/65200 +WT/HK/65207 +WT/HK/65210 +WT/HK/65212 +WT/HK/65215 +WT/HK/65216 +WT/HK/65217 +WT/HK/65220 +WT/HK/65222 +WT/HK/65225 +WT/HK/65227 +WT/HK/65228 +WT/HK/65230 +WT/HK/65231 +WT/HK/65233 +WT/HK/65239 +WT/HK/65248 +WT/HK/65259 +WT/HK/65264 +WT/HK/65269 +WT/HK/65271 +WT/HK/65272 +WT/HK/65273 +WT/HK/65274 +WT/HK/65276 +WT/HK/65277 +WT/HK/65279 +WT/HK/65280 +WT/HK/65281 +WT/HK/65291 +WT/HK/65294 +WT/HK/65296 +WT/HK/65298 +WT/HK/65303 +WT/HK/65307 +WT/HK/65308 +WT/HK/65309 +WT/HK/65311 +WT/HK/65312 +WT/HK/65313 +WT/HK/65314 +WT/HK/65316 +WT/HK/65318 +WT/HK/65320 +WT/HK/65321 +WT/HK/65322 +WT/HK/65323 +WT/HK/65324 +WT/HK/65325 +WT/HK/65329 +WT/HK/65330 +WT/HK/65332 +WT/HK/65333 +WT/HK/65334 +WT/HK/65336 +WT/HK/65337 +WT/HK/65339 +WT/HK/65343 +WT/HK/65347 +WT/HK/65348 +WT/HK/65350 +WT/HK/65351 +WT/HK/65356 +WT/HK/65357 +WT/HK/65358 +WT/HK/65361 +WT/HK/65365 +WT/HK/65370 +WT/HK/65373 +WT/HK/65377 +WT/HK/65379 +WT/HK/65395 +WT/HK/65397 +WT/HK/65400 +WT/HK/65403 +WT/HK/65405 +WT/HK/65409 +WT/HK/65412 +WT/HK/65417 +WT/HK/65422 +WT/HK/65423 +WT/HK/65425 +WT/HK/65427 +WT/HK/65428 +WT/HK/65429 +WT/HK/65430 +WT/HK/65434 +WT/HK/65436 +WT/HK/65446 +WT/HK/65447 +WT/HK/65449 +WT/HK/65454 +WT/HK/65459 +WT/HK/65460 +WT/HK/65463 +WT/HK/65464 +WT/HK/65466 +WT/HK/65467 +WT/HK/65468 +WT/HK/65469 +WT/HK/65470 +WT/HK/65474 +WT/HK/65477 +WT/HK/65478 +WT/HK/65479 +WT/HK/65480 +WT/HK/65483 +WT/HK/65484 +WT/HK/65487 +WT/HK/65491 +WT/HK/65495 +WT/HK/65499 +WT/HK/65500 +WT/HK/65503 +WT/HK/65504 +WT/HK/65506 +WT/HK/65509 +WT/HK/65510 +WT/HK/65512 +WT/HK/65519 +WT/HK/65520 +WT/HK/65521 +WT/HK/65526 +WT/HK/65527 +WT/HK/65528 +WT/HK/65531 +WT/HK/65534 +WT/HK/65540 +WT/HK/65542 +WT/HK/65543 +WT/HK/65544 +WT/HK/65545 +WT/HK/65546 +WT/HK/65547 +WT/HK/65554 +WT/HK/65555 +WT/HK/65557 +WT/HK/65561 +WT/HK/65564 +WT/HK/65570 +WT/HK/65572 +WT/HK/65575 +WT/HK/65576 +WT/HK/65577 +WT/HK/65578 +WT/HK/65579 +WT/HK/65580 +WT/HK/65581 +WT/HK/65582 +WT/HK/65585 +WT/HK/65586 +WT/HK/65591 +WT/HK/65593 +WT/HK/65596 +WT/HK/65599 +WT/HK/65602 +WT/HK/65605 +WT/HK/65609 +WT/HK/65610 +WT/HK/65611 +WT/HK/65612 +WT/HK/65616 +WT/HK/65617 +WT/HK/65618 +WT/HK/65619 +WT/HK/65621 +WT/HK/65625 +WT/HK/65626 +WT/HK/65627 +WT/HK/65638 +WT/HK/65641 +WT/HK/65644 +WT/HK/65645 +WT/HK/65650 +WT/HK/65655 +WT/HK/65663 +WT/HK/65664 +WT/HK/65665 +WT/HK/65666 +WT/HK/65667 +WT/HK/65668 +WT/HK/65674 +WT/HK/65675 +WT/HK/65678 +WT/HK/65682 +WT/HK/65683 +WT/HK/65688 +WT/HK/65689 +WT/HK/65691 +WT/HK/65699 +WT/HK/65700 +WT/HK/65701 +WT/HK/65702 +WT/HK/65703 +WT/HK/65704 +WT/HK/65705 +WT/HK/65709 +WT/HK/65712 +WT/HK/65713 +WT/HK/65719 +WT/HK/65724 +WT/HK/65725 +WT/HK/65727 +WT/HK/65730 +WT/HK/65732 +WT/HK/65737 +WT/HK/65739 +WT/HK/65743 +WT/HK/65744 +WT/HK/65751 +WT/HK/65753 +WT/HK/65755 +WT/HK/65772 +WT/HK/65773 +WT/HK/65778 +WT/HK/65784 +WT/HK/65786 +WT/HK/65787 +WT/HK/65788 +WT/HK/65792 +WT/HK/65795 +WT/HK/65796 +WT/HK/65798 +WT/HK/65799 +WT/HK/65800 +WT/HK/65813 +WT/HK/65816 +WT/HK/65819 +WT/HK/65822 +WT/HK/65825 +WT/HK/65826 +WT/HK/65827 +WT/HK/65828 +WT/HK/65829 +WT/HK/65831 +WT/HK/65835 +WT/HK/65836 +WT/HK/65838 +WT/HK/65841 +WT/HK/65844 +WT/HK/65846 +WT/HK/65854 +WT/HK/65861 +WT/HK/65864 +WT/HK/65871 +WT/HK/65874 +WT/HK/65887 +WT/HK/65891 +WT/HK/65894 +WT/HK/65901 +WT/HK/65903 +WT/HK/65905 +WT/HK/65906 +WT/HK/65908 +WT/HK/65916 +WT/HK/65920 +WT/HK/65928 +WT/HK/65930 +WT/HK/65931 +WT/HK/65932 +WT/HK/65933 +WT/HK/65935 +WT/HK/65939 +WT/HK/65941 +WT/HK/65942 +WT/HK/65943 +WT/HK/65944 +WT/HK/65945 +WT/HK/65953 +WT/HK/65958 +WT/HK/65959 +WT/HK/65967 +WT/HK/65970 +WT/HK/65973 +WT/HK/65975 +WT/HK/65976 +WT/HK/65979 +WT/HK/65981 +WT/HK/65983 +WT/HK/65984 +WT/HK/65987 +WT/HK/65989 +WT/HK/65991 +WT/HK/65993 +WT/HK/65994 +WT/HK/65999 +WT/HK/66010 +WT/HK/66014 +WT/HK/66015 +WT/HK/66016 +WT/HK/66020 +WT/HK/66021 +WT/HK/66022 +WT/HK/66024 +WT/HK/66028 +WT/HK/66029 +WT/HK/66034 +WT/HK/66036 +WT/HK/66037 +WT/HK/66038 +WT/HK/66041 +WT/HK/66042 +WT/HK/66045 +WT/HK/66053 +WT/HK/66055 +WT/HK/66057 +WT/HK/66058 +WT/HK/66059 +WT/HK/66060 +WT/HK/66061 +WT/HK/66066 +WT/HK/66068 +WT/HK/66071 +WT/HK/66074 +WT/HK/66077 +WT/HK/66081 +WT/HK/66082 +WT/HK/66083 +WT/HK/66086 +WT/HK/66087 +WT/HK/66088 +WT/HK/66094 +WT/HK/66095 +WT/HK/66096 +WT/HK/66097 +WT/HK/66099 +WT/HK/66100 +WT/HK/66101 +WT/HK/66102 +WT/HK/66103 +WT/HK/66106 +WT/HK/66107 +WT/HK/66108 +WT/HK/66109 +WT/HK/66113 +WT/HK/66114 +WT/HK/66115 +WT/HK/66117 +WT/HK/66118 +WT/HK/66120 +WT/HK/66121 +WT/HK/66122 +WT/HK/66123 +WT/HK/66124 +WT/HK/66126 +WT/HK/66128 +WT/HK/66129 +WT/HK/66132 +WT/HK/66134 +WT/HK/66137 +WT/HK/66139 +WT/HK/66142 +WT/HK/66146 +WT/HK/66147 +WT/HK/66150 +WT/HK/66151 +WT/HK/66159 +WT/HK/66164 +WT/HK/66165 +WT/HK/66166 +WT/HK/66167 +WT/HK/66168 +WT/HK/66170 +WT/HK/66171 +WT/HK/66172 +WT/HK/66180 +WT/HK/66184 +WT/HK/66189 +WT/HK/66200 +WT/HK/66201 +WT/HK/66205 +WT/HK/66206 +WT/HK/66209 +WT/HK/66212 +WT/HK/66214 +WT/HK/66215 +WT/HK/66216 +WT/HK/66221 +WT/HK/66223 +WT/HK/66225 +WT/HK/66226 +WT/HK/66227 +WT/HK/66228 +WT/HK/66231 +WT/HK/66232 +WT/HK/66235 +WT/HK/66237 +WT/HK/66238 +WT/HK/66241 +WT/HK/66245 +WT/HK/66247 +WT/HK/66249 +WT/HK/66250 +WT/HK/66251 +WT/HK/66252 +WT/HK/66256 +WT/HK/66257 +WT/HK/66258 +WT/HK/66261 +WT/HK/66266 +WT/HK/66267 +WT/HK/66268 +WT/HK/66270 +WT/HK/66271 +WT/HK/66272 +WT/HK/66273 +WT/HK/66275 +WT/HK/66279 +WT/HK/66280 +WT/HK/66285 +WT/HK/66286 +WT/HK/66287 +WT/HK/66288 +WT/HK/66290 +WT/HK/66291 +WT/HK/66292 +WT/HK/66293 +WT/HK/66294 +WT/HK/66295 +WT/HK/66297 +WT/HK/66299 +WT/HK/66302 +WT/HK/66304 +WT/HK/66305 +WT/HK/66307 +WT/HK/66308 +WT/HK/66309 +WT/HK/66312 +WT/HK/66314 +WT/HK/66316 +WT/HK/66317 +WT/HK/66320 +WT/HK/66325 +WT/HK/66328 +WT/HK/66329 +WT/HK/66330 +WT/HK/66334 +WT/HK/66335 +WT/HK/66337 +WT/HK/66339 +WT/HK/66342 +WT/HK/66348 +WT/HK/66350 +WT/HK/66351 +WT/HK/66352 +WT/HK/66359 +WT/HK/66361 +WT/HK/66378 +WT/HK/66379 +WT/HK/66380 +WT/HK/66381 +WT/HK/66387 +WT/HK/66388 +WT/HK/66391 +WT/HK/66395 +WT/HK/66397 +WT/HK/66401 +WT/HK/66403 +WT/HK/66404 +WT/HK/66405 +WT/HK/66408 +WT/HK/66409 +WT/HK/66411 +WT/HK/66418 +WT/HK/66419 +WT/HK/66422 +WT/HK/66423 +WT/HK/66424 +WT/HK/66425 +WT/HK/66427 +WT/HK/66430 +WT/HK/66433 +WT/HK/66434 +WT/HK/66440 +WT/HK/66441 +WT/HK/66442 +WT/HK/66443 +WT/HK/66445 +WT/HK/66447 +WT/HK/66448 +WT/HK/66449 +WT/HK/66452 +WT/HK/66463 +WT/HK/66465 +WT/HK/66468 +WT/HK/66470 +WT/HK/66471 +WT/HK/66472 +WT/HK/66473 +WT/HK/66474 +WT/HK/66477 +WT/HK/66478 +WT/HK/66479 +WT/HK/66480 +WT/HK/66482 +WT/HK/66483 +WT/HK/66484 +WT/HK/66487 +WT/HK/66488 +WT/HK/66489 +WT/HK/66492 +WT/HK/66498 +WT/HK/66501 +WT/HK/66502 +WT/HK/66503 +WT/HK/66509 +WT/HK/66511 +WT/HK/66514 +WT/HK/66521 +WT/HK/66523 +WT/HK/66524 +WT/HK/66525 +WT/HK/66527 +WT/HK/66528 +WT/HK/66529 +WT/HK/66532 +WT/HK/66534 +WT/HK/66535 +WT/HK/66542 +WT/HK/66545 +WT/HK/66546 +WT/HK/66547 +WT/HK/66548 +WT/HK/66552 +WT/HK/66553 +WT/HK/66554 +WT/HK/66558 +WT/HK/66559 +WT/HK/66564 +WT/HK/66566 +WT/HK/66567 +WT/HK/66569 +WT/HK/66573 +WT/HK/66574 +WT/HK/66576 +WT/HK/66577 +WT/HK/66580 +WT/HK/66582 +WT/HK/66584 +WT/HK/66594 +WT/HK/66595 +WT/HK/66599 +WT/HK/66601 +WT/HK/66605 +WT/HK/66607 +WT/HK/66611 +WT/HK/66613 +WT/HK/66614 +WT/HK/66617 +WT/HK/66622 +WT/HK/66625 +WT/HK/66626 +WT/HK/66631 +WT/HK/66632 +WT/HK/66633 +WT/HK/66635 +WT/HK/66637 +WT/HK/66641 +WT/HK/66642 +WT/HK/66643 +WT/HK/66645 +WT/HK/66646 +WT/HK/66647 +WT/HK/66653 +WT/HK/66655 +WT/HK/66656 +WT/HK/66659 +WT/HK/66661 +WT/HK/66662 +WT/HK/66666 +WT/HK/66667 +WT/HK/66669 +WT/HK/66671 +WT/HK/66675 +WT/HK/66676 +WT/HK/66682 +WT/HK/66683 +WT/HK/66689 +WT/HK/66690 +WT/HK/66692 +WT/HK/66694 +WT/HK/66695 +WT/HK/66696 +WT/HK/66699 +WT/HK/66701 +WT/HK/66718 +WT/HK/66719 +WT/HK/66723 +WT/HK/66726 +WT/HK/66727 +WT/HK/66731 +WT/HK/66732 +WT/HK/66734 +WT/HK/66736 +WT/HK/66740 +WT/HK/66741 +WT/HK/66742 +WT/HK/66743 +WT/HK/66746 +WT/HK/66747 +WT/HK/66748 +WT/HK/66749 +WT/HK/66756 +WT/HK/66757 +WT/HK/66763 +WT/HK/66764 +WT/HK/66765 +WT/HK/66766 +WT/HK/66767 +WT/HK/66768 +WT/HK/66769 +WT/HK/66770 +WT/HK/66771 +WT/HK/66772 +WT/HK/66773 +WT/HK/66776 +WT/HK/66780 +WT/HK/66786 +WT/HK/66787 +WT/HK/66788 +WT/HK/66792 +WT/HK/66796 +WT/HK/66806 +WT/HK/66809 +WT/HK/66816 +WT/HK/66819 +WT/HK/66829 +WT/HK/66831 +WT/HK/66834 +WT/HK/66837 +WT/HK/66843 +WT/HK/66845 +WT/HK/66846 +WT/HK/66847 +WT/HK/66849 +WT/HK/66850 +WT/HK/66854 +WT/HK/66858 +WT/HK/66862 +WT/HK/66863 +WT/HK/66865 +WT/HK/66866 +WT/HK/66870 +WT/HK/66873 +WT/HK/66876 +WT/HK/66883 +WT/HK/66884 +WT/HK/66886 +WT/HK/66890 +WT/HK/66894 +WT/HK/66899 +WT/HK/66900 +WT/HK/66901 +WT/HK/66903 +WT/HK/66905 +WT/HK/66907 +WT/HK/66908 +WT/HK/66911 +WT/HK/66912 +WT/HK/66913 +WT/HK/66916 +WT/HK/66918 +WT/HK/66919 +WT/HK/66920 +WT/HK/66921 +WT/HK/66922 +WT/HK/66923 +WT/HK/66924 +WT/HK/66929 +WT/HK/66930 +WT/HK/66931 +WT/HK/66932 +WT/HK/66934 +WT/HK/66946 +WT/HK/66947 +WT/HK/66951 +WT/HK/66959 +WT/HK/66960 +WT/HK/66967 +WT/HK/66970 +WT/HK/66971 +WT/HK/66985 +WT/HK/66988 +WT/HK/66989 +WT/HK/66991 +WT/HK/66993 +WT/HK/66994 +WT/HK/66995 +WT/HK/66996 +WT/HK/66999 +WT/HK/67000 +WT/HK/67002 +WT/HK/67005 +WT/HK/67006 +WT/HK/67009 +WT/HK/67011 +WT/HK/67013 +WT/HK/67017 +WT/HK/67018 +WT/HK/67020 +WT/HK/67028 +WT/HK/67029 +WT/HK/67031 +WT/HK/67033 +WT/HK/67035 +WT/HK/67036 +WT/HK/67039 +WT/HK/67042 +WT/HK/67049 +WT/HK/67050 +WT/HK/67052 +WT/HK/67056 +WT/HK/67057 +WT/HK/67058 +WT/HK/67063 +WT/HK/67072 +WT/HK/67076 +WT/HK/67077 +WT/HK/67078 +WT/HK/67084 +WT/HK/67087 +WT/HK/67093 +WT/HK/67094 +WT/HK/67099 +WT/HK/67101 +WT/HK/67103 +WT/HK/67106 +WT/HK/67111 +WT/HK/67113 +WT/HK/67116 +WT/HK/67118 +WT/HK/67119 +WT/HK/67121 +WT/HK/67123 +WT/HK/67124 +WT/HK/67130 +WT/HK/67132 +WT/HK/67133 +WT/HK/67134 +WT/HK/67138 +WT/HK/67139 +WT/HK/67140 +WT/HK/67143 +WT/HK/67144 +WT/HK/67145 +WT/HK/67148 +WT/HK/67149 +WT/HK/67150 +WT/HK/67151 +WT/HK/67152 +WT/HK/67153 +WT/HK/67154 +WT/HK/67155 +WT/HK/67156 +WT/HK/67161 +WT/HK/67162 +WT/HK/67163 +WT/HK/67165 +WT/HK/67166 +WT/HK/67168 +WT/HK/67169 +WT/HK/67172 +WT/HK/67176 +WT/HK/67179 +WT/HK/67180 +WT/HK/67187 +WT/HK/67188 +WT/HK/67193 +WT/HK/67194 +WT/HK/67199 +WT/HK/67200 +WT/HK/67201 +WT/HK/67202 +WT/HK/67210 +WT/HK/67218 +WT/HK/67219 +WT/HK/67221 +WT/HK/67222 +WT/HK/67225 +WT/HK/67226 +WT/HK/67230 +WT/HK/67232 +WT/HK/67235 +WT/HK/67242 +WT/HK/67243 +WT/HK/67244 +WT/HK/67250 +WT/HK/67252 +WT/HK/67253 +WT/HK/67260 +WT/HK/67262 +WT/HK/67267 +WT/HK/67274 +WT/HK/67275 +WT/HK/67278 +WT/HK/67282 +WT/HK/67283 +WT/HK/67293 +WT/HK/67294 +WT/HK/67295 +WT/HK/67297 +WT/HK/67298 +WT/HK/67299 +WT/HK/67301 +WT/HK/67302 +WT/HK/67303 +WT/HK/67304 +WT/HK/67305 +WT/HK/67307 +WT/HK/67309 +WT/HK/67310 +WT/HK/67311 +WT/HK/67316 +WT/HK/67317 +WT/HK/67318 +WT/HK/67324 +WT/HK/67326 +WT/HK/67327 +WT/HK/67329 +WT/HK/67330 +WT/HK/67331 +WT/HK/67332 +WT/HK/67335 +WT/HK/67336 +WT/HK/67339 +WT/HK/67340 +WT/HK/67341 +WT/HK/67342 +WT/HK/67343 +WT/HK/67346 +WT/HK/67349 +WT/HK/67354 +WT/HK/67357 +WT/HK/67359 +WT/HK/67360 +WT/HK/67361 +WT/HK/67362 +WT/HK/67363 +WT/HK/67368 +WT/HK/67370 +WT/HK/67371 +WT/HK/67375 +WT/HK/67376 +WT/HK/67378 +WT/HK/67379 +WT/HK/67381 +WT/HK/67382 +WT/HK/67384 +WT/HK/67386 +WT/HK/67389 +WT/HK/67391 +WT/HK/67393 +WT/HK/67394 +WT/HK/67395 +WT/HK/67396 +WT/HK/67398 +WT/HK/67399 +WT/HK/67400 +WT/HK/67401 +WT/HK/67402 +WT/HK/67403 +WT/HK/67404 +WT/HK/67405 +WT/HK/67406 +WT/HK/67408 +WT/HK/67410 +WT/HK/67411 +WT/HK/67412 +WT/HK/67413 +WT/HK/67415 +WT/HK/67417 +WT/HK/67418 +WT/HK/67419 +WT/HK/67420 +WT/HK/67421 +WT/HK/67422 +WT/HK/67423 +WT/HK/67426 +WT/HK/67427 +WT/HK/67428 +WT/HK/67429 +WT/HK/67430 +WT/HK/67432 +WT/HK/67433 +WT/HK/67434 +WT/HK/67437 +WT/HK/67438 +WT/HK/67448 +WT/HK/67450 +WT/HK/67454 +WT/HK/67456 +WT/HK/67459 +WT/HK/67460 +WT/HK/67464 +WT/HK/67470 +WT/HK/67472 +WT/HK/67473 +WT/HK/67474 +WT/HK/67475 +WT/HK/67476 +WT/HK/67485 +WT/HK/67488 +WT/HK/67489 +WT/HK/67490 +WT/HK/67491 +WT/HK/67492 +WT/HK/67495 +WT/HK/67496 +WT/HK/67497 +WT/HK/67498 +WT/HK/67502 +WT/HK/67503 +WT/HK/67504 +WT/HK/67506 +WT/HK/67507 +WT/HK/67509 +WT/HK/67512 +WT/HK/67513 +WT/HK/67516 +WT/HK/67517 +WT/HK/67521 +WT/HK/67524 +WT/HK/67527 +WT/HK/67529 +WT/HK/67531 +WT/HK/67532 +WT/HK/67533 +WT/HK/67537 +WT/HK/67538 +WT/HK/67541 +WT/HK/67542 +WT/HK/67544 +WT/HK/67546 +WT/HK/67549 +WT/HK/67554 +WT/HK/67555 +WT/HK/67556 +WT/HK/67557 +WT/HK/67558 +WT/HK/67561 +WT/HK/67564 +WT/HK/67566 +WT/HK/67568 +WT/HK/67570 +WT/HK/67571 +WT/HK/67575 +WT/HK/67577 +WT/HK/67578 +WT/HK/67579 +WT/HK/67580 +WT/HK/67583 +WT/HK/67584 +WT/HK/67585 +WT/HK/67586 +WT/HK/67590 +WT/HK/67592 +WT/HK/67597 +WT/HK/67599 +WT/HK/67601 +WT/HK/67603 +WT/HK/67606 +WT/HK/67607 +WT/HK/67615 +WT/HK/67616 +WT/HK/67617 +WT/HK/67618 +WT/HK/67619 +WT/HK/67624 +WT/HK/67625 +WT/HK/67626 +WT/HK/67628 +WT/HK/67629 +WT/HK/67630 +WT/HK/67633 +WT/HK/67638 +WT/HK/67639 +WT/HK/67642 +WT/HK/67643 +WT/HK/67646 +WT/HK/67648 +WT/HK/67653 +WT/HK/67654 +WT/HK/67663 +WT/HK/67667 +WT/HK/67669 +WT/HK/67670 +WT/HK/67671 +WT/HK/67673 +WT/HK/67675 +WT/HK/67676 +WT/HK/67680 +WT/HK/67681 +WT/HK/67682 +WT/HK/67684 +WT/HK/67685 +WT/HK/67687 +WT/HK/67688 +WT/HK/67696 +WT/HK/67698 +WT/HK/67699 +WT/HK/67704 +WT/HK/67705 +WT/HK/67709 +WT/HK/67713 +WT/HK/67716 +WT/HK/67719 +WT/HK/67720 +WT/HK/67721 +WT/HK/67722 +WT/HK/67724 +WT/HK/67727 +WT/HK/67728 +WT/HK/67733 +WT/HK/67736 +WT/HK/67737 +WT/HK/67740 +WT/HK/67743 +WT/HK/67744 +WT/HK/67746 +WT/HK/67749 +WT/HK/67750 +WT/HK/67751 +WT/HK/67753 +WT/HK/67754 +WT/HK/67757 +WT/HK/67762 +WT/HK/67763 +WT/HK/67765 +WT/HK/67769 +WT/HK/67770 +WT/HK/67772 +WT/HK/67773 +WT/HK/67774 +WT/HK/67775 +WT/HK/67776 +WT/HK/67777 +WT/HK/67778 +WT/HK/67779 +WT/HK/67781 +WT/HK/67782 +WT/HK/67783 +WT/HK/67787 +WT/HK/67788 +WT/HK/67790 +WT/HK/67791 +WT/HK/67792 +WT/HK/67796 +WT/HK/67798 +WT/HK/67799 +WT/HK/67801 +WT/HK/67802 +WT/HK/67803 +WT/HK/67805 +WT/HK/67807 +WT/HK/67808 +WT/HK/67810 +WT/HK/67811 +WT/HK/67813 +WT/HK/67814 +WT/HK/67818 +WT/HK/67820 +WT/HK/67821 +WT/HK/67825 +WT/HK/67826 +WT/HK/67830 +WT/HK/67831 +WT/HK/67832 +WT/HK/67834 +WT/HK/67837 +WT/HK/67838 +WT/HK/67840 +WT/HK/67843 +WT/HK/67844 +WT/HK/67846 +WT/HK/67850 +WT/HK/67852 +WT/HK/67853 +WT/HK/67855 +WT/HK/67856 +WT/HK/67860 +WT/HK/67861 +WT/HK/67863 +WT/HK/67864 +WT/HK/67872 +WT/HK/67875 +WT/HK/67877 +WT/HK/67879 +WT/HK/67880 +WT/HK/67882 +WT/HK/67891 +WT/HK/67892 +WT/HK/67893 +WT/HK/67898 +WT/HK/67901 +WT/HK/67905 +WT/HK/67906 +WT/HK/67911 +WT/HK/67913 +WT/HK/67915 +WT/HK/67916 +WT/HK/67917 +WT/HK/67922 +WT/HK/67923 +WT/HK/67924 +WT/HK/67925 +WT/HK/67928 +WT/HK/67931 +WT/HK/67932 +WT/HK/67935 +WT/HK/67936 +WT/HK/67938 +WT/HK/67940 +WT/HK/67942 +WT/HK/67945 +WT/HK/67946 +WT/HK/67947 +WT/HK/67951 +WT/HK/67952 +WT/HK/67955 +WT/HK/67962 +WT/HK/67967 +WT/HK/67970 +WT/HK/67974 +WT/HK/67976 +WT/HK/67985 +WT/HK/67986 +WT/HK/67989 +WT/HK/67991 +WT/HK/67992 +WT/HK/67993 +WT/HK/67998 +WT/HK/67999 +WT/HK/68000 +WT/HK/68002 +WT/HK/68007 +WT/HK/68008 +WT/HK/68009 +WT/HK/68013 +WT/HK/68014 +WT/HK/68016 +WT/HK/68017 +WT/HK/68020 +WT/HK/68025 +WT/HK/68030 +WT/HK/68035 +WT/HK/68036 +WT/HK/68039 +WT/HK/68043 +WT/HK/68045 +WT/HK/68046 +WT/HK/68049 +WT/HK/68051 +WT/HK/68052 +WT/HK/68053 +WT/HK/68054 +WT/HK/68057 +WT/HK/68059 +WT/HK/68061 +WT/HK/68063 +WT/HK/68065 +WT/HK/68068 +WT/HK/68070 +WT/HK/68074 +WT/HK/68076 +WT/HK/68080 +WT/HK/68081 +WT/HK/68083 +WT/HK/68085 +WT/HK/68086 +WT/HK/68088 +WT/HK/68091 +WT/HK/68093 +WT/HK/68094 +WT/HK/68095 +WT/HK/68097 +WT/HK/68100 +WT/HK/68101 +WT/HK/68107 +WT/HK/68108 +WT/HK/68109 +WT/HK/68111 +WT/HK/68112 +WT/HK/68115 +WT/HK/68116 +WT/HK/68117 +WT/HK/68119 +WT/HK/68120 +WT/HK/68121 +WT/HK/68122 +WT/HK/68124 +WT/HK/68125 +WT/HK/68126 +WT/HK/68129 +WT/HK/68130 +WT/HK/68133 +WT/HK/68137 +WT/HK/68142 +WT/HK/68148 +WT/HK/68149 +WT/HK/68152 +WT/HK/68153 +WT/HK/68154 +WT/HK/68161 +WT/HK/68165 +WT/HK/68169 +WT/HK/68170 +WT/HK/68175 +WT/HK/68176 +WT/HK/68178 +WT/HK/68180 +WT/HK/68181 +WT/HK/68183 +WT/HK/68184 +WT/HK/68185 +WT/HK/68187 +WT/HK/68190 +WT/HK/68191 +WT/HK/68193 +WT/HK/68196 +WT/HK/68197 +WT/HK/68200 +WT/HK/68202 +WT/HK/68203 +WT/HK/68205 +WT/HK/68207 +WT/HK/68210 +WT/HK/68215 +WT/HK/68216 +WT/HK/68218 +WT/HK/68219 +WT/HK/68222 +WT/HK/68227 +WT/HK/68232 +WT/HK/68234 +WT/HK/68235 +WT/HK/68236 +WT/HK/68242 +WT/HK/68243 +WT/HK/68248 +WT/HK/68250 +WT/HK/68252 +WT/HK/68255 +WT/HK/68256 +WT/HK/68258 +WT/HK/68259 +WT/HK/68263 +WT/HK/68265 +WT/HK/68266 +WT/HK/68269 +WT/HK/68270 +WT/HK/68271 +WT/HK/68274 +WT/HK/68275 +WT/HK/68279 +WT/HK/68283 +WT/HK/68290 +WT/HK/68293 +WT/HK/68295 +WT/HK/68298 +WT/HK/68300 +WT/HK/68301 +WT/HK/68302 +WT/HK/68303 +WT/HK/68305 +WT/HK/68306 +WT/HK/68307 +WT/HK/68310 +WT/HK/68311 +WT/HK/68312 +WT/HK/68313 +WT/HK/68314 +WT/HK/68315 +WT/HK/68316 +WT/HK/68317 +WT/HK/68321 +WT/HK/68326 +WT/HK/68332 +WT/HK/68333 +WT/HK/68338 +WT/HK/68340 +WT/HK/68345 +WT/HK/68346 +WT/HK/68356 +WT/HK/68361 +WT/HK/68371 +WT/HK/68372 +WT/HK/68376 +WT/HK/68378 +WT/HK/68379 +WT/HK/68381 +WT/HK/68383 +WT/HK/68386 +WT/HK/68388 +WT/HK/68392 +WT/HK/68393 +WT/HK/68394 +WT/HK/68395 +WT/HK/68397 +WT/HK/68399 +WT/HK/68400 +WT/HK/68401 +WT/HK/68402 +WT/HK/68404 +WT/HK/68407 +WT/HK/68409 +WT/HK/68410 +WT/HK/68411 +WT/HK/68412 +WT/HK/68413 +WT/HK/68415 +WT/HK/68416 +WT/HK/68417 +WT/HK/68421 +WT/HK/68426 +WT/HK/68428 +WT/HK/68430 +WT/HK/68432 +WT/HK/68439 +WT/HK/68440 +WT/HK/68441 +WT/HK/68447 +WT/HK/68448 +WT/HK/68453 +WT/HK/68458 +WT/HK/68459 +WT/HK/68460 +WT/HK/68461 +WT/HK/68462 +WT/HK/68464 +WT/HK/68465 +WT/HK/68466 +WT/HK/68467 +WT/HK/68468 +WT/HK/68470 +WT/HK/68473 +WT/HK/68477 +WT/HK/68481 +WT/HK/68482 +WT/HK/68483 +WT/HK/68485 +WT/HK/68486 +WT/HK/68487 +WT/HK/68488 +WT/HK/68491 +WT/HK/68492 +WT/HK/68494 +WT/HK/68497 +WT/HK/68499 +WT/HK/68500 +WT/HK/68501 +WT/HK/68504 +WT/HK/68505 +WT/HK/68508 +WT/HK/68510 +WT/HK/68513 +WT/HK/68516 +WT/HK/68520 +WT/HK/68521 +WT/HK/68522 +WT/HK/68523 +WT/HK/68524 +WT/HK/68525 +WT/HK/68527 +WT/HK/68528 +WT/HK/68529 +WT/HK/68530 +WT/HK/68533 +WT/HK/68534 +WT/HK/68535 +WT/HK/68537 +WT/HK/68540 +WT/HK/68541 +WT/HK/68543 +WT/HK/68545 +WT/HK/68549 +WT/HK/68550 +WT/HK/68551 +WT/HK/68552 +WT/HK/68553 +WT/HK/68554 +WT/HK/68555 +WT/HK/68560 +WT/HK/68561 +WT/HK/68562 +WT/HK/68563 +WT/HK/68564 +WT/HK/68565 +WT/HK/68566 +WT/HK/68567 +WT/HK/68569 +WT/HK/68570 +WT/HK/68572 +WT/HK/68574 +WT/HK/68575 +WT/HK/68577 +WT/HK/68578 +WT/HK/68581 +WT/HK/68584 +WT/HK/68586 +WT/HK/68589 +WT/HK/68590 +WT/HK/68592 +WT/HK/68593 +WT/HK/68596 +WT/HK/68605 +WT/HK/68606 +WT/HK/68607 +WT/HK/68608 +WT/HK/68613 +WT/HK/68629 +WT/HK/68634 +WT/HK/68639 +WT/HK/68640 +WT/HK/68642 +WT/HK/68643 +WT/HK/68644 +WT/HK/68647 +WT/HK/68649 +WT/HK/68654 +WT/HK/68660 +WT/HK/68661 +WT/HK/68662 +WT/HK/68663 +WT/HK/68664 +WT/HK/68667 +WT/HK/68670 +WT/HK/68671 +WT/HK/68672 +WT/HK/68673 +WT/HK/68674 +WT/HK/68675 +WT/HK/68676 +WT/HK/68677 +WT/HK/68678 +WT/HK/68679 +WT/HK/68680 +WT/HK/68684 +WT/HK/68686 +WT/HK/68687 +WT/HK/68688 +WT/HK/68689 +WT/HK/68693 +WT/HK/68696 +WT/HK/68702 +WT/HK/68703 +WT/HK/68705 +WT/HK/68708 +WT/HK/68715 +WT/HK/68717 +WT/HK/68719 +WT/HK/68725 +WT/HK/68728 +WT/HK/68734 +WT/HK/68735 +WT/HK/68736 +WT/HK/68740 +WT/HK/68749 +WT/HK/68757 +WT/HK/68758 +WT/HK/68759 +WT/HK/68760 +WT/HK/68761 +WT/HK/68762 +WT/HK/68769 +WT/HK/68770 +WT/HK/68774 +WT/HK/68775 +WT/HK/68778 +WT/HK/68781 +WT/HK/68786 +WT/HK/68789 +WT/HK/68790 +WT/HK/68791 +WT/HK/68793 +WT/HK/68796 +WT/HK/68801 +WT/HK/68807 +WT/HK/68813 +WT/HK/68817 +WT/HK/68821 +WT/HK/68823 +WT/HK/68824 +WT/HK/68826 +WT/HK/68829 +WT/HK/68830 +WT/HK/68832 +WT/HK/68833 +WT/HK/68834 +WT/HK/68836 +WT/HK/68837 +WT/HK/68838 +WT/HK/68839 +WT/HK/68842 +WT/HK/68843 +WT/HK/68845 +WT/HK/68847 +WT/HK/68851 +WT/HK/68852 +WT/HK/68853 +WT/HK/68855 +WT/HK/68859 +WT/HK/68862 +WT/HK/68874 +WT/HK/68876 +WT/HK/68878 +WT/HK/68880 +WT/HK/68881 +WT/HK/68883 +WT/HK/68884 +WT/HK/68886 +WT/HK/68888 +WT/HK/68889 +WT/HK/68890 +WT/HK/68891 +WT/HK/68892 +WT/HK/68894 +WT/HK/68896 +WT/HK/68901 +WT/HK/68903 +WT/HK/68904 +WT/HK/68905 +WT/HK/68907 +WT/HK/68909 +WT/HK/68912 +WT/HK/68914 +WT/HK/68916 +WT/HK/68917 +WT/HK/68918 +WT/HK/68920 +WT/HK/68921 +WT/HK/68922 +WT/HK/68923 +WT/HK/68927 +WT/HK/68929 +WT/HK/68931 +WT/HK/68932 +WT/HK/68934 +WT/HK/68936 +WT/HK/68937 +WT/HK/68938 +WT/HK/68941 +WT/HK/68952 +WT/HK/68953 +WT/HK/68956 +WT/HK/68965 +WT/HK/68968 +WT/HK/68971 +WT/HK/68976 +WT/HK/68982 +WT/HK/68983 +WT/HK/68984 +WT/HK/68989 +WT/HK/68990 +WT/HK/68993 +WT/HK/68994 +WT/HK/68996 +WT/HK/68998 +WT/HK/69000 +WT/HK/69003 +WT/HK/69005 +WT/HK/69006 +WT/HK/69007 +WT/HK/69011 +WT/HK/69015 +WT/HK/69016 +WT/HK/69017 +WT/HK/69020 +WT/HK/69021 +WT/HK/69023 +WT/HK/69024 +WT/HK/69030 +WT/HK/69031 +WT/HK/69036 +WT/HK/69038 +WT/HK/69039 +WT/HK/69040 +WT/HK/69043 +WT/HK/69048 +WT/HK/69050 +WT/HK/69052 +WT/HK/69053 +WT/HK/69054 +WT/HK/69059 +WT/HK/69060 +WT/HK/69062 +WT/HK/69063 +WT/HK/69064 +WT/HK/69070 +WT/HK/69071 +WT/HK/69076 +WT/HK/69078 +WT/HK/69079 +WT/HK/69081 +WT/HK/69082 +WT/HK/69088 +WT/HK/69089 +WT/HK/69094 +WT/HK/69095 +WT/HK/69096 +WT/HK/69099 +WT/HK/69101 +WT/HK/69105 +WT/HK/69106 +WT/HK/69115 +WT/HK/69116 +WT/HK/69117 +WT/HK/69119 +WT/HK/69132 +WT/HK/69133 +WT/HK/69134 +WT/HK/69140 +WT/HK/69142 +WT/HK/69143 +WT/HK/69144 +WT/HK/69145 +WT/HK/69148 +WT/HK/69150 +WT/HK/69151 +WT/HK/69153 +WT/HK/69154 +WT/HK/69155 +WT/HK/69156 +WT/HK/69160 +WT/HK/69162 +WT/HK/69165 +WT/HK/69170 +WT/HK/69171 +WT/HK/69174 +WT/HK/69175 +WT/HK/69176 +WT/HK/69177 +WT/HK/69178 +WT/HK/69179 +WT/HK/69181 +WT/HK/69183 +WT/HK/69184 +WT/HK/69187 +WT/HK/69189 +WT/HK/69190 +WT/HK/69192 +WT/HK/69193 +WT/HK/69194 +WT/HK/69197 +WT/HK/69198 +WT/HK/69200 +WT/HK/69202 +WT/HK/69209 +WT/HK/69217 +WT/HK/69221 +WT/HK/69223 +WT/HK/69227 +WT/HK/69229 +WT/HK/69230 +WT/HK/69236 +WT/HK/69238 +WT/HK/69239 +WT/HK/69240 +WT/HK/69243 +WT/HK/69244 +WT/HK/69247 +WT/HK/69248 +WT/HK/69250 +WT/HK/69253 +WT/HK/69256 +WT/HK/69258 +WT/HK/69261 +WT/HK/69262 +WT/HK/69265 +WT/HK/69267 +WT/HK/69272 +WT/HK/69276 +WT/HK/69281 +WT/HK/69282 +WT/HK/69283 +WT/HK/69284 +WT/HK/69289 +WT/HK/69290 +WT/HK/69291 +WT/HK/69292 +WT/HK/69293 +WT/HK/69294 +WT/HK/69295 +WT/HK/69296 +WT/HK/69298 +WT/HK/69303 +WT/HK/69304 +WT/HK/69305 +WT/HK/69309 +WT/HK/69310 +WT/HK/69311 +WT/HK/69313 +WT/HK/69314 +WT/HK/69315 +WT/HK/69319 +WT/HK/69320 +WT/HK/69321 +WT/HK/69322 +WT/HK/69324 +WT/HK/69326 +WT/HK/69331 +WT/HK/69334 +WT/HK/69338 +WT/HK/69339 +WT/HK/69341 +WT/HK/69342 +WT/HK/69345 +WT/HK/69346 +WT/HK/69348 +WT/HK/69354 +WT/HK/69356 +WT/HK/69357 +WT/HK/69358 +WT/HK/69360 +WT/HK/69362 +WT/HK/69368 +WT/HK/69370 +WT/HK/69372 +WT/HK/69373 +WT/HK/69376 +WT/HK/69377 +WT/HK/69378 +WT/HK/69381 +WT/HK/69382 +WT/HK/69386 +WT/HK/69388 +WT/HK/69389 +WT/HK/69390 +WT/HK/69391 +WT/HK/69394 +WT/HK/69399 +WT/HK/69400 +WT/HK/69401 +WT/HK/69411 +WT/HK/69415 +WT/HK/69417 +WT/HK/69419 +WT/HK/69421 +WT/HK/69424 +WT/HK/69425 +WT/HK/69428 +WT/HK/69429 +WT/HK/69431 +WT/HK/69432 +WT/HK/69434 +WT/HK/69435 +WT/HK/69436 +WT/HK/69443 +WT/HK/69445 +WT/HK/69450 +WT/HK/69451 +WT/HK/69453 +WT/HK/69454 +WT/HK/69456 +WT/HK/69461 +WT/HK/69462 +WT/HK/69470 +WT/HK/69471 +WT/HK/69472 +WT/HK/69473 +WT/HK/69474 +WT/HK/69476 +WT/HK/69484 +WT/HK/69490 +WT/HK/69497 +WT/HK/69498 +WT/HK/69501 +WT/HK/69506 +WT/HK/69508 +WT/HK/69509 +WT/HK/69511 +WT/HK/69513 +WT/HK/69519 +WT/HK/69525 +WT/HK/69528 +WT/HK/69529 +WT/HK/69537 +WT/HK/69541 +WT/HK/69548 +WT/HK/69555 +WT/HK/69557 +WT/HK/69560 +WT/HK/69561 +WT/HK/69563 +WT/HK/69564 +WT/HK/69565 +WT/HK/69567 +WT/HK/69570 +WT/HK/69571 +WT/HK/69572 +WT/HK/69573 +WT/HK/69574 +WT/HK/69576 +WT/HK/69578 +WT/HK/69579 +WT/HK/69580 +WT/HK/69581 +WT/HK/69582 +WT/HK/69583 +WT/HK/69584 +WT/HK/69585 +WT/HK/69589 +WT/HK/69592 +WT/HK/69594 +WT/HK/69597 +WT/HK/69598 +WT/HK/69599 +WT/HK/69600 +WT/HK/69601 +WT/HK/69603 +WT/HK/69604 +WT/HK/69606 +WT/HK/69607 +WT/HK/69608 +WT/HK/69610 +WT/HK/69611 +WT/HK/69613 +WT/HK/69614 +WT/HK/69615 +WT/HK/69616 +WT/HK/69621 +WT/HK/69622 +WT/HK/69624 +WT/HK/69625 +WT/HK/69626 +WT/HK/69628 +WT/HK/69629 +WT/HK/69632 +WT/HK/69633 +WT/HK/69634 +WT/HK/69637 +WT/HK/69638 +WT/HK/69639 +WT/HK/69644 +WT/HK/69645 +WT/HK/69647 +WT/HK/69651 +WT/HK/69656 +WT/HK/69657 +WT/HK/69659 +WT/HK/69666 +WT/HK/69672 +WT/HK/69681 +WT/HK/69682 +WT/HK/69683 +WT/HK/69690 +WT/HK/69694 +WT/HK/69695 +WT/HK/69696 +WT/HK/69699 +WT/HK/69703 +WT/HK/69705 +WT/HK/69708 +WT/HK/69712 +WT/HK/69716 +WT/HK/69719 +WT/HK/69727 +WT/HK/69731 +WT/HK/69732 +WT/HK/69733 +WT/HK/69734 +WT/HK/69739 +WT/HK/69741 +WT/HK/69743 +WT/HK/69744 +WT/HK/69745 +WT/HK/69748 +WT/HK/69749 +WT/HK/69750 +WT/HK/69754 +WT/HK/69755 +WT/HK/69756 +WT/HK/69757 +WT/HK/69760 +WT/HK/69761 +WT/HK/69763 +WT/HK/69766 +WT/HK/69768 +WT/HK/69769 +WT/HK/69775 +WT/HK/69778 +WT/HK/69780 +WT/HK/69781 +WT/HK/69790 +WT/HK/69793 +WT/HK/69798 +WT/HK/69799 +WT/HK/69800 +WT/HK/69801 +WT/HK/69815 +WT/HK/69818 +WT/HK/69819 +WT/HK/69821 +WT/HK/69822 +WT/HK/69823 +WT/HK/69824 +WT/HK/69825 +WT/HK/69826 +WT/HK/69827 +WT/HK/69830 +WT/HK/69832 +WT/HK/69841 +WT/HK/69845 +WT/HK/69850 +WT/HK/69855 +WT/HK/69856 +WT/HK/69857 +WT/HK/69858 +WT/HK/69860 +WT/HK/69861 +WT/HK/69862 +WT/HK/69863 +WT/HK/69864 +WT/HK/69870 +WT/HK/69872 +WT/HK/69873 +WT/HK/69874 +WT/HK/69877 +WT/HK/69878 +WT/HK/69879 +WT/HK/69880 +WT/HK/69881 +WT/HK/69882 +WT/HK/69884 +WT/HK/69886 +WT/HK/69887 +WT/HK/69889 +WT/HK/69895 +WT/HK/69897 +WT/HK/69900 +WT/HK/69901 +WT/HK/69902 +WT/HK/69903 +WT/HK/69914 +WT/HK/69916 +WT/HK/69918 +WT/HK/69919 +WT/HK/69923 +WT/HK/69924 +WT/HK/69927 +WT/HK/69928 +WT/HK/69929 +WT/HK/69931 +WT/HK/69933 +WT/HK/69935 +WT/HK/69936 +WT/HK/69938 +WT/HK/69939 +WT/HK/69940 +WT/HK/69944 +WT/HK/69945 +WT/HK/69949 +WT/HK/69953 +WT/HK/69955 +WT/HK/69956 +WT/HK/69958 +WT/HK/69960 +WT/HK/69961 +WT/HK/69963 +WT/HK/69964 +WT/HK/69965 +WT/HK/69967 +WT/HK/69971 +WT/HK/69972 +WT/HK/69975 +WT/HK/69977 +WT/HK/69981 +WT/HK/69983 +WT/HK/69986 +WT/HK/69987 +WT/HK/69989 +WT/HK/69991 +WT/HK/69992 +WT/HK/69995 +WT/HK/69997 +WT/HK/69998 +WT/HK/69999 +WT/SG/1K3W +WT/SG/1K7W +WT/SG/1M2W +WT/SG/1M8W +WT/SG/1N5W +WT/SG/1N7W +WT/SG/1O0W +WT/SG/1O2W +WT/SG/1O5W +WT/SG/1OZW +WT/SG/1P8W +WT/SG/1Q5W +WT/SG/1Q8W +WT/SG/1T2W +WT/SG/1U7W +WT/SG/1V5W +WT/SG/1V9W +WT/SG/1W0W +WT/SG/1W2W +WT/SG/1X5W +WT/SG/1XMW +WT/SG/1XZW +WT/SG/1Y2W +WT/SG/1Y3W +WT/SG/1ZXW +WT/SG/43SW +WT/SG/44BW +WT/SG/44NW +WT/SG/44PW +WT/SG/44RW +WT/SG/44TW +WT/SG/45IW +WT/SG/45LW +WT/SG/45YW +WT/SG/46CW +WT/SG/47GW +WT/SG/47JW +WT/SG/47KW +WT/SG/48HW +WT/SG/48QW +WT/SG/49CW +WT/SG/50OW +WT/SG/50SW +WT/SG/51AW +WT/SG/51UW +WT/SG/52PW +WT/SG/53MW +WT/SG/54DW +WT/SG/54FW +WT/SG/54MW +WT/SG/54XW +WT/SG/55CW +WT/SG/55YW +WT/SG/56DW +WT/SG/56IW +WT/SG/56LW +WT/SG/56QW +WT/SG/57GW +WT/SG/57HW +WT/SG/57TW +WT/SG/57XW +WT/SG/58KW +WT/SG/58UW +WT/SG/59HW +WT/SG/59WW +WT/SG/5B5W +WT/SG/5C3W +WT/SG/5C6W +WT/SG/5D8W +WT/SG/5K3W +WT/SG/5L7W +WT/SG/5L9W +WT/SG/5O9W +WT/SG/5Q4W +WT/SG/5T9W +WT/SG/5U8W +WT/SG/5V2W +WT/SG/5W6W +WT/SG/5XAW +WT/SG/5XBW +WT/SG/5XFW +WT/SG/5XTW +WT/SG/5YDW +WT/SG/5YZ +WT/SG/5ZJW +WT/SG/5ZRW +WT/SG/8A3W +WT/SG/8B5W +WT/SG/8E8W +WT/SG/8E9W +WT/SG/8H6W +WT/SG/8I3W +WT/SG/8J9W +WT/SG/8L9W +WT/SG/8N7W +WT/SG/8P1W +WT/SG/8R7W +WT/SG/8R9W +WT/SG/8U1W +WT/SG/8W1W +WT/SG/8W3W +WT/SG/8Y2W +WT/SG/8Y5W +WT/SG/8YIW +WT/SG/8ZJW +WT/SG/92FW +WT/SG/92LW +WT/SG/92NW +WT/SG/933W +WT/SG/93VW +WT/SG/93ZW +WT/SG/94LW +WT/SG/95DW +WT/SG/95XW +WT/SG/966W +WT/SG/96KW +WT/SG/96LW +WT/SG/96WW +WT/SG/972W +WT/SG/97MW +WT/SG/97WW +WT/SG/97XW +WT/SG/98BW +WT/SG/98CW +WT/SG/98HW +WT/SG/98WW +WT/SG/99RW +WT/SG/99VW +WT/SG/9A9W +WT/SG/9AQW +WT/SG/9B2W +WT/SG/9BMW +WT/SG/9BOW +WT/SG/9BRW +WT/SG/9CPW +WT/SG/9CXW +WT/SG/9D2W +WT/SG/9D9W +WT/SG/9DDW +WT/SG/9E7W +WT/SG/9E9W +WT/SG/9ERW +WT/SG/9FCW +WT/SG/9FOW +WT/SG/9G5W +WT/SG/9GBW +WT/SG/9GDW +WT/SG/9GPW +WT/SG/9GUW +WT/SG/9H3W +WT/SG/9HGW +WT/SG/9HHW +WT/SG/9HNW +WT/SG/9I9W +WT/SG/9IMW +WT/SG/9J2W +WT/SG/9JIW +WT/SG/9JKW +WT/SG/9JPW +WT/SG/9JQW +WT/SG/9K1W +WT/SG/9KBW +WT/SG/9KEW +WT/SG/9KMW +WT/SG/9KYW +WT/SG/9L1W +WT/SG/9L2W +WT/SG/9LEW +WT/SG/9LTW +WT/SG/9MCW +WT/SG/9MRW +WT/SG/9MSW +WT/SG/9NDW +WT/SG/9NHW +WT/SG/9NJW +WT/SG/9NPW +WT/SG/9O5W +WT/SG/9OJW +WT/SG/9OQW +WT/SG/9P8W +WT/SG/9PBW +WT/SG/9PDW +WT/SG/9PGW +WT/SG/9POW +WT/SG/9PPW +WT/SG/9PVW +WT/SG/9PXW +WT/SG/9Q4W +WT/SG/9QEW +WT/SG/9R9W +WT/SG/9RAW +WT/SG/9RHW +WT/SG/9RNW +WT/SG/9RWW +WT/SG/9RZW +WT/SG/9SAW +WT/SG/9STW +WT/SG/9SWW +WT/SG/9T8W +WT/SG/9TRW +WT/SG/9U1W +WT/SG/9UGW +WT/SG/9UIW +WT/SG/9V9W +WT/SG/9VBW +WT/SG/9VHW +WT/SG/9VNW +WT/SG/9VUW +WT/SG/9W1W +WT/SG/9W2W +WT/SG/9WIW +WT/SG/9WLW +WT/SG/9WNW +WT/SG/9X9W +WT/SG/9XCW +WT/SG/9Y2W +WT/SG/9Y3W +WT/SG/9Y7W +WT/SG/9YIW +WT/SG/9YJW +WT/SG/9YVW +WT/SG/9ZIW +WT/SG/9ZXW +WT/SG/9ZYW +WT/SG/A95W +WT/SG/B00W +WT/SG/B91W +WT/SG/CUDW +WT/SG/CUEW +WT/SG/CUFW +WT/SG/CUGW +WT/SG/CUJW +WT/SG/CUKW +WT/SG/CUMW +WT/SG/CUNW +WT/SG/CUPW +WT/SG/CUQW +WT/SG/CURW +WT/SG/CUTW +WT/SG/CUUW +WT/SG/CUXW +WT/SG/CUZW +WT/SG/CVAW +WT/SG/CVBW +WT/SG/CVDW +WT/SG/CVEW +WT/SG/CVFW +WT/SG/CVGW +WT/SG/CVHW +WT/SG/CVIW +WT/SG/CVJW +WT/SG/CVKW +WT/SG/CVLW +WT/SG/CVMW +WT/SG/CVPW +WT/SG/CVRW +WT/SG/CVSW +WT/SG/CVYW +WT/SG/CWAW +WT/SG/CWDW +WT/SG/CWEW +WT/SG/CWFW +WT/SG/CWGW +WT/SG/CWHW +WT/SG/CWIW +WT/SG/CWKW +WT/SG/CWLW +WT/SG/CWMW +WT/SG/CWPW +WT/SG/CWQW +WT/SG/CWRW +WT/SG/CWUW +WT/SG/CWXW +WT/SG/CXBW +WT/SG/CXCW +WT/SG/CXDW +WT/SG/CXEW +WT/SG/CXGW +WT/SG/CXIW +WT/SG/CXJW +WT/SG/CXKW +WT/SG/CXLW +WT/SG/CXMW +WT/SG/CXPW +WT/SG/CXQW +WT/SG/CXRW +WT/SG/CXVW +WT/SG/CXXW +WT/SG/CXZW +WT/SG/CYAW +WT/SG/CYDW +WT/SG/CYEW +WT/SG/CYFW +WT/SG/CYGW +WT/SG/CYIW +WT/SG/CYJW +WT/SG/CYMW +WT/SG/CYNW +WT/SG/CYOW +WT/SG/CYPW +WT/SG/CYQW +WT/SG/CYSW +WT/SG/CYTW +WT/SG/CYZW +WT/SG/CZAW +WT/SG/CZBW +WT/SG/CZDW +WT/SG/CZEW +WT/SG/CZFW +WT/SG/CZGW +WT/SG/CZHW +WT/SG/CZIW +WT/SG/CZJW +WT/SG/CZLW +WT/SG/CZMW +WT/SG/CZNW +WT/SG/CZOW +WT/SG/CZPW +WT/SG/CZRW +WT/SG/CZSW +WT/SG/CZVW +WT/SG/CZZW +WT/SG/D00W +WT/SG/DAEW +WT/SG/DAFW +WT/SG/DAGW +WT/SG/DAIW +WT/SG/DAJW +WT/SG/DAKW +WT/SG/DAMW +WT/SG/DAOW +WT/SG/DAQW +WT/SG/DARW +WT/SG/DATW +WT/SG/DAUW +WT/SG/DAVW +WT/SG/DAYW +WT/SG/DAZW +WT/SG/DBCW +WT/SG/DBEW +WT/SG/DBIW +WT/SG/DBJW +WT/SG/DBMW +WT/SG/DBNW +WT/SG/DBPW +WT/SG/DBTW +WT/SG/DBWW +WT/SG/DBYW +WT/SG/DCDW +WT/SG/DCFW +WT/SG/DCGW +WT/SG/DCHW +WT/SG/DCKW +WT/SG/DCMW +WT/SG/DCNW +WT/SG/DCQW +WT/SG/DCUW +WT/SG/DCVW +WT/SG/DCXW +WT/SG/DCZW +WT/SG/DDBW +WT/SG/DDDW +WT/SG/DDEW +WT/SG/DDOW +WT/SG/DDPW +WT/SG/DDSW +WT/SG/DDTW +WT/SG/DDYW +WT/SG/DDZW +WT/SG/DECW +WT/SG/DEEW +WT/SG/DEFW +WT/SG/DEGW +WT/SG/DEHW +WT/SG/DELW +WT/SG/DEMW +WT/SG/DENW +WT/SG/DEOW +WT/SG/DEPW +WT/SG/DEQW +WT/SG/DETW +WT/SG/DEUW +WT/SG/DEVW +WT/SG/DEWW +WT/SG/DEXW +WT/SG/DEZW +WT/SG/DFDW +WT/SG/DFEW +WT/SG/DFIW +WT/SG/DFJW +WT/SG/DFKW +WT/SG/DFLW +WT/SG/DFMW +WT/SG/DFRW +WT/SG/DFSW +WT/SG/DFTW +WT/SG/DFUW +WT/SG/DFWW +WT/SG/DFXW +WT/SG/DFYW +WT/SG/DFZW +WT/SG/DGBW +WT/SG/DGCW +WT/SG/DGEW +WT/SG/DGGW +WT/SG/DGJW +WT/SG/DGKW +WT/SG/DGMW +WT/SG/DGNW +WT/SG/DGUW +WT/SG/DGWW +WT/SG/DGYW +WT/SG/DHAW +WT/SG/DHDW +WT/SG/DHEW +WT/SG/DHGW +WT/SG/DHHW +WT/SG/DHNW +WT/SG/DHQW +WT/SG/DHRW +WT/SG/DHSW +WT/SG/DHUW +WT/SG/DHVW +WT/SG/DHWW +WT/SG/DHXW +WT/SG/DICW +WT/SG/DIDW +WT/SG/DIFW +WT/SG/DIGW +WT/SG/DIIW +WT/SG/DIKW +WT/SG/DIMW +WT/SG/DINW +WT/SG/DIOW +WT/SG/DIPW +WT/SG/DISW +WT/SG/DITW +WT/SG/DIZW +WT/SG/DJAW +WT/SG/DJBW +WT/SG/DJCW +WT/SG/DJDW +WT/SG/DJEW +WT/SG/DJJW +WT/SG/DJKW +WT/SG/DJLW +WT/SG/DJMW +WT/SG/DJNW +WT/SG/DJOW +WT/SG/DJPW +WT/SG/DJSW +WT/SG/DJVW +WT/SG/DJYW +WT/SG/DJZW +WT/SG/DKAW +WT/SG/DKBW +WT/SG/DKCW +WT/SG/DKEW +WT/SG/DKGW +WT/SG/DKHW +WT/SG/DKKW +WT/SG/DKLW +WT/SG/DKNW +WT/SG/DKOW +WT/SG/DKPW +WT/SG/DKQW +WT/SG/DKRW +WT/SG/DKVW +WT/SG/DKZW +WT/SG/DLCW +WT/SG/DLDW +WT/SG/DLEW +WT/SG/DLFW +WT/SG/DLGW +WT/SG/DLHW +WT/SG/DLJW +WT/SG/DLKW +WT/SG/DLNW +WT/SG/DLSW +WT/SG/DLTW +WT/SG/DLVW +WT/SG/DLZW +WT/SG/DMAW +WT/SG/DMBW +WT/SG/DMEW +WT/SG/DMFW +WT/SG/DMHW +WT/SG/DMIW +WT/SG/DMJW +WT/SG/DMKW +WT/SG/DMMW +WT/SG/DMNW +WT/SG/DMRW +WT/SG/DMSW +WT/SG/DMUW +WT/SG/DMYW +WT/SG/DNAW +WT/SG/DNCW +WT/SG/DNDW +WT/SG/DNFW +WT/SG/DNGW +WT/SG/DNHW +WT/SG/DNJW +WT/SG/DNKW +WT/SG/DNLW +WT/SG/DNNW +WT/SG/DNPW +WT/SG/DNQW +WT/SG/DNSW +WT/SG/DNVW +WT/SG/DNWW +WT/SG/DNZW +WT/SG/DOCW +WT/SG/DOGW +WT/SG/DOLW +WT/SG/DOMW +WT/SG/DONW +WT/SG/DOOW +WT/SG/DOPW +WT/SG/DORW +WT/SG/DOSW +WT/SG/DOVW +WT/SG/DOWW +WT/SG/DOYW +WT/SG/DPAW +WT/SG/DPBW +WT/SG/DPDW +WT/SG/DPEW +WT/SG/DPFW +WT/SG/DPGW +WT/SG/DPHW +WT/SG/DPJW +WT/SG/DPKW +WT/SG/DPNW +WT/SG/DPPW +WT/SG/DPRW +WT/SG/DPTW +WT/SG/DPZW +WT/SG/DQAW +WT/SG/DQBW +WT/SG/DQCW +WT/SG/DQGW +WT/SG/DQHW +WT/SG/DQJW +WT/SG/DQKW +WT/SG/DQLW +WT/SG/DQRW +WT/SG/DQSW +WT/SG/DQUW +WT/SG/DQVW +WT/SG/DQWW +WT/SG/DQXW +WT/SG/DQYW +WT/SG/DQZW +WT/SG/DRAW +WT/SG/DRBW +WT/SG/DRCW +WT/SG/DRGW +WT/SG/DRHW +WT/SG/DRJW +WT/SG/DRKW +WT/SG/DRMW +WT/SG/DRNW +WT/SG/DROW +WT/SG/DRPW +WT/SG/DRQW +WT/SG/DRRW +WT/SG/DRSW +WT/SG/DRTW +WT/SG/DRVW +WT/SG/DRZW +WT/SG/DSDW +WT/SG/DSFW +WT/SG/DSJW +WT/SG/DSMW +WT/SG/DSOW +WT/SG/DSPW +WT/SG/DSQW +WT/SG/DSRW +WT/SG/DSTW +WT/SG/DSWW +WT/SG/DSXW +WT/SG/DSZW +WT/SG/DTCW +WT/SG/DTFW +WT/SG/DTHW +WT/SG/DTJW +WT/SG/DTMW +WT/SG/DTSW +WT/SG/DTXW +WT/SG/DTZW +WT/SG/DUBW +WT/SG/DUFW +WT/SG/DUGW +WT/SG/DUHW +WT/SG/DUKW +WT/SG/DULW +WT/SG/DUMW +WT/SG/DUNW +WT/SG/DUPW +WT/SG/DURW +WT/SG/DUTW +WT/SG/DUWW +WT/SG/DUXW +WT/SG/DUYW +WT/SG/DVAW +WT/SG/DVCW +WT/SG/DVFW +WT/SG/DVHW +WT/SG/DVJW +WT/SG/DVKW +WT/SG/DVLW +WT/SG/DVMW +WT/SG/DVNW +WT/SG/DVPW +WT/SG/DVRW +WT/SG/DVSW +WT/SG/DVUW +WT/SG/DVWW +WT/SG/DVXW +WT/SG/DVZW +WT/SG/DWAW +WT/SG/DWEW +WT/SG/DWFW +WT/SG/DWHW +WT/SG/DWIW +WT/SG/DWKW +WT/SG/DWMW +WT/SG/DWNW +WT/SG/DWOW +WT/SG/DWTW +WT/SG/DWYW +WT/SG/DXAW +WT/SG/DXBW +WT/SG/DXIW +WT/SG/DXJW +WT/SG/DXKW +WT/SG/DXLW +WT/SG/DXOW +WT/SG/DXQW +WT/SG/DXRW +WT/SG/DXSW +WT/SG/DXVW +WT/SG/DXZW +WT/SG/DYDW +WT/SG/DYEW +WT/SG/DYFW +WT/SG/DYGW +WT/SG/DYHW +WT/SG/DYIW +WT/SG/DYKW +WT/SG/DYLW +WT/SG/DYMW +WT/SG/DYNW +WT/SG/DYSW +WT/SG/DYTW +WT/SG/DYWW +WT/SG/DYXW +WT/SG/DYYW +WT/SG/DZAW +WT/SG/DZEW +WT/SG/DZKW +WT/SG/DZMW +WT/SG/DZNW +WT/SG/DZOW +WT/SG/DZQW +WT/SG/DZSW +WT/SG/DZTW +WT/SG/DZUW +WT/SG/DZVW +WT/SG/DZWW +WT/SG/DZZW +WT/SG/EAM +WT/SG/EAQW +WT/SG/EAVW +WT/SG/EBEW +WT/SG/EBSW +WT/SG/ECAW +WT/SG/ECJW +WT/SG/ECSW +WT/SG/ECTW +WT/SG/EDEW +WT/SG/EDHW +WT/SG/EDMW +WT/SG/EEHW +WT/SG/EEJ +WT/SG/EFBW +WT/SG/EGCW +WT/SG/EGEW +WT/SG/EHFW +WT/SG/EHMW +WT/SG/EHNW +WT/SG/EHPW +WT/SG/EHTW +WT/SG/EHUW +WT/SG/EIKW +WT/SG/EITW +WT/SG/EKPW +WT/SG/ELCW +WT/SG/ELDW +WT/SG/ELLW +WT/SG/ELQW +WT/SG/EMAW +WT/SG/EMJW +WT/SG/EMMW +WT/SG/ENJW +WT/SG/ENTW +WT/SG/EOIW +WT/SG/EONW +WT/SG/EOOW +WT/SG/EOPW +WT/SG/EOVW +WT/SG/EPCW +WT/SG/EPGW +WT/SG/EPVW +WT/SG/EQCW +WT/SG/EQJW +WT/SG/EQLW +WT/SG/ERJW +WT/SG/ESBW +WT/SG/ESFW +WT/SG/EUCW +WT/SG/EUH +WT/SG/EUPW +WT/SG/EUZW +WT/SG/EVMW +WT/SG/EVNW +WT/SG/EWOW +WT/SG/EWXW +WT/SG/EXFW +WT/SG/EXWW +WT/SG/EXXW +WT/SG/EYBW +WT/SG/EYFW +WT/SG/EYTW +WT/SG/EZUW +WT/SG/FADW +WT/SG/FBKW +WT/SG/FBPW +WT/SG/FBXW +WT/SG/FDDW +WT/SG/FDWW +WT/SG/FELW +WT/SG/FESW +WT/SG/FETW +WT/SG/FFAW +WT/SG/FFIW +WT/SG/FFPW +WT/SG/FGDW +WT/SG/FGEW +WT/SG/FGFW +WT/SG/FGIW +WT/SG/FGUW +WT/SG/FHOW +WT/SG/FHRW +WT/SG/FHTW +WT/SG/FIHW +WT/SG/FIMW +WT/SG/FIOW +WT/SG/FKBW +WT/SG/FKVW +WT/SG/FLBW +WT/SG/FLHW +WT/SG/FLLW +WT/SG/FMGW +WT/SG/FMSW +WT/SG/FMVW +WT/SG/FMXW +WT/SG/FNBW +WT/SG/FNNW +WT/SG/FNTW +WT/SG/FNVW +WT/SG/FNYW +WT/SG/FOEW +WT/SG/FOFW +WT/SG/FOQW +WT/SG/FPKW +WT/SG/FPPW +WT/SG/FQCW +WT/SG/FQPW +WT/SG/FQQW +WT/SG/FQTW +WT/SG/FRDW +WT/SG/FRGW +WT/SG/FRIW +WT/SG/FRLW +WT/SG/FSKW +WT/SG/FTAW +WT/SG/FTEW +WT/SG/FTMW +WT/SG/FTRW +WT/SG/FTUW +WT/SG/FUPW +WT/SG/FUSW +WT/SG/FUUW +WT/SG/FVBW +WT/SG/FVGW +WT/SG/FVUW +WT/SG/FWQW +WT/SG/FXEW +WT/SG/FXNW +WT/SG/FXRW +WT/SG/FYSW +WT/SG/FYZW +WT/SG/FZCW +WT/SG/FZFW +WT/SG/G19W +WT/SG/GAQW +WT/SG/GAUW +WT/SG/GCDW +WT/SG/GCLW +WT/SG/GDJW +WT/SG/GDRW +WT/SG/GDUW +WT/SG/GDVW +WT/SG/GEGW +WT/SG/GEIW +WT/SG/GFGW +WT/SG/GFYW +WT/SG/GGTW +WT/SG/GGXW +WT/SG/GHCW +WT/SG/GHWW +WT/SG/GIWW +WT/SG/GIYW +WT/SG/GJIW +WT/SG/GJXW +WT/SG/GKAW +WT/SG/GKDW +WT/SG/GKLW +WT/SG/GKPW +WT/SG/GKTW +WT/SG/GLJW +WT/SG/GMFW +WT/SG/GMKW +WT/SG/GMNW +WT/SG/GMPW +WT/SG/GODW +WT/SG/GOOW +WT/SG/GOYW +WT/SG/GPMW +WT/SG/GPSW +WT/SG/GPUW +WT/SG/GQEW +WT/SG/GQYW +WT/SG/GRCW +WT/SG/GRKW +WT/SG/GRVW +WT/SG/GSEW +WT/SG/GSJW +WT/SG/GSPW +WT/SG/GSVW +WT/SG/GTHW +WT/SG/GTRW +WT/SG/GTXW +WT/SG/GTYW +WT/SG/GUBW +WT/SG/GUDW +WT/SG/GUTW +WT/SG/GUVW +WT/SG/GVMW +WT/SG/GVPW +WT/SG/GVUW +WT/SG/GWCW +WT/SG/GWGW +WT/SG/GYMW +WT/SG/GZTW +WT/SG/HAKW +WT/SG/HAOW +WT/SG/HAUW +WT/SG/HAVW +WT/SG/HBHW +WT/SG/HBIW +WT/SG/HBWW +WT/SG/HBYW +WT/SG/HCLW +WT/SG/HCPW +WT/SG/HCTW +WT/SG/HDKW +WT/SG/HDRW +WT/SG/HDTW +WT/SG/HEFW +WT/SG/HELW +WT/SG/HEYW +WT/SG/HFFW +WT/SG/HFQW +WT/SG/HGOW +WT/SG/HGYW +WT/SG/HHHW +WT/SG/HIEW +WT/SG/HIJW +WT/SG/HIOW +WT/SG/HIPW +WT/SG/HIQW +WT/SG/HJLW +WT/SG/HJUW +WT/SG/HKCW +WT/SG/HKKW +WT/SG/HKRW +WT/SG/HLJW +WT/SG/HLKW +WT/SG/HMAW +WT/SG/HMFW +WT/SG/HMMW +WT/SG/HNVW +WT/SG/HNZW +WT/SG/HOHW +WT/SG/HOJW +WT/SG/HOUW +WT/SG/HOYW +WT/SG/HPMW +WT/SG/HPRW +WT/SG/HQCW +WT/SG/HQLW +WT/SG/HQWW +WT/SG/HQXW +WT/SG/HRIW +WT/SG/HRNW +WT/SG/HSAW +WT/SG/HSEW +WT/SG/HSJW +WT/SG/HSKW +WT/SG/HSLW +WT/SG/HSNW +WT/SG/HTQW +WT/SG/HUKW +WT/SG/HURW +WT/SG/HUTW +WT/SG/HWAW +WT/SG/HWXW +WT/SG/HYGW +WT/SG/HYNW +WT/SG/HZPW +WT/SG/HZXW +WT/SG/IABW +WT/SG/IAIW +WT/SG/IAUW +WT/SG/IBBW +WT/SG/IBRW +WT/SG/IDBW +WT/SG/IESW +WT/SG/IEYW +WT/SG/IFAW +WT/SG/IFDW +WT/SG/IFHW +WT/SG/IFKW +WT/SG/IFUW +WT/SG/IFZW +WT/SG/IGBW +WT/SG/IGYW +WT/SG/IHEW +WT/SG/IHHW +WT/SG/IHJW +WT/SG/IHSW +WT/SG/IIEW +WT/SG/IIIW +WT/SG/IIYW +WT/SG/IJEW +WT/SG/IJIW +WT/SG/IJKW +WT/SG/IJWW +WT/SG/IKAW +WT/SG/IKQW +WT/SG/ILKW +WT/SG/ILNW +WT/SG/ILRW +WT/SG/IMWW +WT/SG/INBW +WT/SG/INRW +WT/SG/IOCW +WT/SG/IOKW +WT/SG/IPAW +WT/SG/IPPW +WT/SG/IPTW +WT/SG/IPUW +WT/SG/IQEW +WT/SG/IQKW +WT/SG/IQPW +WT/SG/IQQW +WT/SG/ISFW +WT/SG/ISPW +WT/SG/ISTW +WT/SG/ISXW +WT/SG/ITEW +WT/SG/ITQW +WT/SG/ITRW +WT/SG/ITVW +WT/SG/ITXW +WT/SG/IVKW +WT/SG/IVWW +WT/SG/IWQW +WT/SG/IWWW +WT/SG/IXBW +WT/SG/IXIW +WT/SG/IXJW +WT/SG/IYBW +WT/SG/IYUW +WT/SG/IZIW +WT/SG/IZSW +WT/SG/IZTW +WT/SG/IZYW +WT/SG/JAFW +WT/SG/JBFW +WT/SG/JCDW +WT/SG/JCJW +WT/SG/JDLW +WT/SG/JEDW +WT/SG/JEFW +WT/SG/JEGW +WT/SG/JFOW +WT/SG/JFRW +WT/SG/JFSW +WT/SG/JFXW +WT/SG/JGCW +WT/SG/JGKW +WT/SG/JGQW +WT/SG/JHDW +WT/SG/JHNW +WT/SG/JHTW +WT/SG/JHXW +WT/SG/JIGW +WT/SG/JIVW +WT/SG/JIYW +WT/SG/JJGW +WT/SG/JJQW +WT/SG/JKKW +WT/SG/JLDW +WT/SG/JLFW +WT/SG/JLJW +WT/SG/JLXW +WT/SG/JMBW +WT/SG/JMFW +WT/SG/JQAW +WT/SG/JQPW +WT/SG/JQYW +WT/SG/JREW +WT/SG/JRTW +WT/SG/JSKW +WT/SG/JUIW +WT/SG/JUVW +WT/SG/JVEW +WT/SG/JVFW +WT/SG/JVKW +WT/SG/JVLW +WT/SG/JVPW +WT/SG/JVWW +WT/SG/JWAW +WT/SG/JWGW +WT/SG/JWIW +WT/SG/JWLW +WT/SG/JWNW +WT/SG/JWVW +WT/SG/JXGW +WT/SG/JXHW +WT/SG/JYOW +WT/SG/JZJW +WT/SG/JZLW +WT/SG/KAGW +WT/SG/KBDW +WT/SG/KBNW +WT/SG/KBPW +WT/SG/KBZW +WT/SG/KCFW +WT/SG/KCIW +WT/SG/KCKW +WT/SG/KCXW +WT/SG/KDNW +WT/SG/KDOW +WT/SG/KDPW +WT/SG/KEQW +WT/SG/KERW +WT/SG/KEVW +WT/SG/KEWW +WT/SG/KFCW +WT/SG/KFEW +WT/SG/KGDW +WT/SG/KGHW +WT/SG/KGIW +WT/SG/KGRW +WT/SG/KGZW +WT/SG/KHWW +WT/SG/KIHW +WT/SG/KIIW +WT/SG/KKQW +WT/SG/KLEW +WT/SG/KLGW +WT/SG/KLOW +WT/SG/KLZW +WT/SG/KMMW +WT/SG/KNXW +WT/SG/KOPW +WT/SG/KOUW +WT/SG/KQTW +WT/SG/KQXW +WT/SG/KRMW +WT/SG/KRUW +WT/SG/KRVW +WT/SG/KRWW +WT/SG/KSMW +WT/SG/KSPW +WT/SG/KSYW +WT/SG/KTEW +WT/SG/KTZW +WT/SG/KUFW +WT/SG/KUSW +WT/SG/KUTW +WT/SG/KUVW +WT/SG/KWIW +WT/SG/KWTW +WT/SG/KXNW +WT/SG/KYQW +WT/SG/KZAW +WT/SG/KZDW +WT/SG/KZVW +WT/SG/KZYW +WT/SG/LACW +WT/SG/LAIW +WT/SG/LANW +WT/SG/LAUW +WT/SG/LAXW +WT/SG/LBPW +WT/SG/LBXW +WT/SG/LCGW +WT/SG/LDGW +WT/SG/LEDW +WT/SG/LEOW +WT/SG/LGTW +WT/SG/LHLW +WT/SG/LIFW +WT/SG/LIJW +WT/SG/LIQW +WT/SG/LJGW +WT/SG/LKPW +WT/SG/LKVW +WT/SG/LKYW +WT/SG/LLJW +WT/SG/LLXW +WT/SG/LLYW +WT/SG/LMBW +WT/SG/LMKW +WT/SG/LMOW +WT/SG/LMQW +WT/SG/LMWW +WT/SG/LNQW +WT/SG/LNRW +WT/SG/LOAW +WT/SG/LOTW +WT/SG/LPPW +WT/SG/LQCW +WT/SG/LQDW +WT/SG/LQEW +WT/SG/LQRW +WT/SG/LQSW +WT/SG/LRBW +WT/SG/LRHW +WT/SG/LSTW +WT/SG/LTVW +WT/SG/LTYW +WT/SG/LVDW +WT/SG/LVEW +WT/SG/LVNW +WT/SG/LWDW +WT/SG/LWHW +WT/SG/LWZW +WT/SG/LXCW +WT/SG/LXDW +WT/SG/LYAW +WT/SG/LYNW +WT/SG/LYRW +WT/SG/LZJW +WT/SG/MACW +WT/SG/MAEW +WT/SG/MAHW +WT/SG/MAMW +WT/SG/MCFW +WT/SG/MCYW +WT/SG/MCZW +WT/SG/MDWW +WT/SG/MDXW +WT/SG/MEAW +WT/SG/MEWW +WT/SG/MFHW +WT/SG/MFVW +WT/SG/MGCW +WT/SG/MGLW +WT/SG/MGPW +WT/SG/MHFW +WT/SG/MHOW +WT/SG/MHYW +WT/SG/MJHW +WT/SG/MJJW +WT/SG/MJOW +WT/SG/MJQW +WT/SG/MKKW +WT/SG/MKQW +WT/SG/MMGW +WT/SG/MMWW +WT/SG/MNCW +WT/SG/MNHW +WT/SG/MNRW +WT/SG/MNSW +WT/SG/MOGW +WT/SG/MOWW +WT/SG/MPEW +WT/SG/MPKW +WT/SG/MPOW +WT/SG/MPQW +WT/SG/MQJW +WT/SG/MRYW +WT/SG/MSFW +WT/SG/MSKW +WT/SG/MSPW +WT/SG/MSQW +WT/SG/MTWW +WT/SG/MUKW +WT/SG/MUOW +WT/SG/MUSW +WT/SG/MVKW +WT/SG/MVLW +WT/SG/MWDW +WT/SG/MWUW +WT/SG/MXDW +WT/SG/MXOW +WT/SG/MXSW +WT/SG/MZAW +WT/SG/MZNW +WT/SG/MZZW +WT/SG/NAAW +WT/SG/NASW +WT/SG/NATW +WT/SG/NAXW +WT/SG/NBAW +WT/SG/NBDW +WT/SG/NBSW +WT/SG/NBZW +WT/SG/NCAW +WT/SG/NCMW +WT/SG/NCQW +WT/SG/NCTW +WT/SG/NCWW +WT/SG/NCYW +WT/SG/NDCW +WT/SG/NDEW +WT/SG/NDJW +WT/SG/NDRW +WT/SG/NDUW +WT/SG/NDYW +WT/SG/NEAW +WT/SG/NFCW +WT/SG/NFJ +WT/SG/NFSW +WT/SG/NFUW +WT/SG/NGAW +WT/SG/NGEW +WT/SG/NGIW +WT/SG/NGQW +WT/SG/NHHW +WT/SG/NHOW +WT/SG/NHRW +WT/SG/NIC +WT/SG/NIGW +WT/SG/NILW +WT/SG/NIXW +WT/SG/NJXW +WT/SG/NKZW +WT/SG/NLJW +WT/SG/NLPW +WT/SG/NMCW +WT/SG/NMDW +WT/SG/NMG +WT/SG/NNNW +WT/SG/NNPW +WT/SG/NNTW +WT/SG/NNWW +WT/SG/NOMW +WT/SG/NOYW +WT/SG/NPEW +WT/SG/NPKW +WT/SG/NPMW +WT/SG/NPNW +WT/SG/NPUW +WT/SG/NQEW +WT/SG/NQKW +WT/SG/NRGW +WT/SG/NRQW +WT/SG/NSCW +WT/SG/NSLW +WT/SG/NUB +WT/SG/NUGW +WT/SG/NUIW +WT/SG/NUMW +WT/SG/NUOW +WT/SG/NVAW +WT/SG/NVDW +WT/SG/NVIW +WT/SG/NVLW +WT/SG/NVTW +WT/SG/NVUW +WT/SG/NVYW +WT/SG/NWCW +WT/SG/NWDW +WT/SG/NWVW +WT/SG/NYNW +WT/SG/NZCW +WT/SG/NZTW +WT/SG/NZZW +WT/SG/OAAW +WT/SG/OAEW +WT/SG/OASW +WT/SG/OBBW +WT/SG/OCRW +WT/SG/ODAW +WT/SG/ODJW +WT/SG/ODUW +WT/SG/ODVW +WT/SG/OEEW +WT/SG/OEWW +WT/SG/OFBW +WT/SG/OGIW +WT/SG/OGNW +WT/SG/OHKW +WT/SG/OJOW +WT/SG/OJQW +WT/SG/OMQW +WT/SG/OMYW +WT/SG/ONLW +WT/SG/ONRW +WT/SG/ONUW +WT/SG/ONWW +WT/SG/OONW +WT/SG/OOPW +WT/SG/OOQW +WT/SG/OOSW +WT/SG/OOYW +WT/SG/OPAW +WT/SG/OPFW +WT/SG/OPUW +WT/SG/OSCW +WT/SG/OTFW +WT/SG/OUQW +WT/SG/OVBW +WT/SG/OVGW +WT/SG/OVJW +WT/SG/OVRW +WT/SG/OVVW +WT/SG/OVYW +WT/SG/OWIW +WT/SG/OWLW +WT/SG/OXAW +WT/SG/OXCW +WT/SG/OXIW +WT/SG/OXRW +WT/SG/OXUW +WT/SG/OYCW +WT/SG/OZDW +WT/SG/PABW +WT/SG/PAIW +WT/SG/PAMW +WT/SG/PBDW +WT/SG/PBY +WT/SG/PCSW +WT/SG/PCYW +WT/SG/PEMW +WT/SG/PFTW +WT/SG/PFWW +WT/SG/PGBW +WT/SG/PGIW +WT/SG/PHHW +WT/SG/PIGW +WT/SG/PISW +WT/SG/PJWW +WT/SG/PKGW +WT/SG/PKUW +WT/SG/PLIW +WT/SG/PMGW +WT/SG/PMOW +WT/SG/PMPW +WT/SG/PODW +WT/SG/POFW +WT/SG/PONW +WT/SG/POQW +WT/SG/POTW +WT/SG/POUW +WT/SG/PPKW +WT/SG/PPMW +WT/SG/PPPW +WT/SG/PQKW +WT/SG/PRJW +WT/SG/PRLW +WT/SG/PRZW +WT/SG/PSIW +WT/SG/PSJW +WT/SG/PUGW +WT/SG/PUHW +WT/SG/PUYW +WT/SG/PVZW +WT/SG/PWGW +WT/SG/PWRW +WT/SG/PWXW +WT/SG/PXCW +WT/SG/PXRW +WT/SG/PYCW +WT/SG/PYDW +WT/SG/PYKW +WT/SG/PYLW +WT/SG/PYXW +WT/SG/PZBW +WT/SG/PZLW +WT/SG/PZRW +WT/SG/PZWW +WT/SG/Q40W +WT/SG/Q53W +WT/SG/Q66W +WT/SG/Q73W +WT/SG/Q80W +WT/SG/Q89W +WT/SG/QABW +WT/SG/QAC +WT/SG/QAIW +WT/SG/QARW +WT/SG/QAYW +WT/SG/QBNW +WT/SG/QDAW +WT/SG/QDSW +WT/SG/QDYW +WT/SG/QECW +WT/SG/QFHW +WT/SG/QFYW +WT/SG/QGGW +WT/SG/QGWW +WT/SG/QHDW +WT/SG/QHJW +WT/SG/QHTW +WT/SG/QHWW +WT/SG/QHXW +WT/SG/QIAW +WT/SG/QIYW +WT/SG/QJDW +WT/SG/QKPW +WT/SG/QKTW +WT/SG/QMLW +WT/SG/QMPW +WT/SG/QNFW +WT/SG/QNLW +WT/SG/QOYW +WT/SG/QPCW +WT/SG/QPLW +WT/SG/QPNW +WT/SG/QPPW +WT/SG/QPSW +WT/SG/QPYW +WT/SG/QQKW +WT/SG/QQOW +WT/SG/QQQW +WT/SG/QRCW +WT/SG/QRNW +WT/SG/QRRW +WT/SG/QSTW +WT/SG/QSVW +WT/SG/QTCW +WT/SG/QTTW +WT/SG/QUQW +WT/SG/QUUW +WT/SG/QUXW +WT/SG/QVQ +WT/SG/QWBW +WT/SG/QWMW +WT/SG/QXCW +WT/SG/QXHW +WT/SG/QXPW +WT/SG/QXQW +WT/SG/QZEW +WT/SG/QZKW +WT/SG/QZTW +WT/SG/R18W +WT/SG/R28W +WT/SG/R64W +WT/SG/R75W +WT/SG/R78W +WT/SG/R85W +WT/SG/RBBW +WT/SG/RBFW +WT/SG/RBLW +WT/SG/RCCW +WT/SG/RCDW +WT/SG/RCTW +WT/SG/RDAW +WT/SG/RDCW +WT/SG/RDSW +WT/SG/RECW +WT/SG/REFW +WT/SG/REGW +WT/SG/REHW +WT/SG/RFVW +WT/SG/RGCW +WT/SG/RGIW +WT/SG/RGMW +WT/SG/RGUW +WT/SG/RGZW +WT/SG/RHBW +WT/SG/RHDW +WT/SG/RHJW +WT/SG/RIDW +WT/SG/RIVW +WT/SG/RJAW +WT/SG/RJRW +WT/SG/RKUW +WT/SG/RLGW +WT/SG/RLKW +WT/SG/RLLW +WT/SG/RLSW +WT/SG/RLTW +WT/SG/RLWW +WT/SG/RMFW +WT/SG/RMIW +WT/SG/RMLW +WT/SG/RMWW +WT/SG/RMXW +WT/SG/RNUW +WT/SG/RNXW +WT/SG/ROSW +WT/SG/RPEW +WT/SG/RQGW +WT/SG/RQMW +WT/SG/RQWW +WT/SG/RRBW +WT/SG/RRCW +WT/SG/RREW +WT/SG/RRQW +WT/SG/RSFW +WT/SG/RSQW +WT/SG/RSVW +WT/SG/RTNW +WT/SG/RUMW +WT/SG/RUZW +WT/SG/RVLW +WT/SG/RWJW +WT/SG/RXMW +WT/SG/RXN +WT/SG/RXTW +WT/SG/RXUW +WT/SG/RYNW +WT/SG/RYOW +WT/SG/RYQW +WT/SG/RYX +WT/SG/RZGW +WT/SG/SAGW +WT/SG/SARW +WT/SG/SBTW +WT/SG/SCEW +WT/SG/SDFW +WT/SG/SDWW +WT/SG/SEKW +WT/SG/SEPW +WT/SG/SFTW +WT/SG/SFWW +WT/SG/SGEW +WT/SG/SGMW +WT/SG/SGSW +WT/SG/SHKW +WT/SG/SHPW +WT/SG/SHWW +WT/SG/SIDW +WT/SG/SIMW +WT/SG/SJRW +WT/SG/SLRW +WT/SG/SLVW +WT/SG/SMIW +WT/SG/SMVW +WT/SG/SNEW +WT/SG/SNJW +WT/SG/SNSW +WT/SG/SNVW +WT/SG/SOOW +WT/SG/SOQW +WT/SG/SOUW +WT/SG/SOXW +WT/SG/SPOW +WT/SG/SPTW +WT/SG/SPXW +WT/SG/SRDW +WT/SG/SRHW +WT/SG/SRRW +WT/SG/SSC +WT/SG/SSKW +WT/SG/SSLW +WT/SG/SSPW +WT/SG/SSYW +WT/SG/STBW +WT/SG/STYW +WT/SG/SUZW +WT/SG/SVHW +WT/SG/SVZW +WT/SG/SWKW +WT/SG/SWMW +WT/SG/SWTW +WT/SG/SXDW +WT/SG/SXUW +WT/SG/SXWW +WT/SG/SYBW +WT/SG/SYEW +WT/SG/SYHW +WT/SG/SYKW +WT/SG/SYOW +WT/SG/SYSW +WT/SG/SZLW +WT/SG/SZWW +WT/SG/TAWW +WT/SG/TAYW +WT/SG/TBEW +WT/SG/TBGW +WT/SG/TBNW +WT/SG/TBPW +WT/SG/TCCW +WT/SG/TCHW +WT/SG/TCQW +WT/SG/TCXW +WT/SG/TDDW +WT/SG/TDFW +WT/SG/TDNW +WT/SG/TDPW +WT/SG/TDQ +WT/SG/TEHW +WT/SG/TEWW +WT/SG/TFAW +WT/SG/TFGW +WT/SG/TFXW +WT/SG/TGDW +WT/SG/TGHW +WT/SG/TGKW +WT/SG/TGMW +WT/SG/THBW +WT/SG/THQW +WT/SG/TIRW +WT/SG/TJNW +WT/SG/TLAW +WT/SG/TNL +WT/SG/TNUW +WT/SG/TOAW +WT/SG/TPIW +WT/SG/TPWW +WT/SG/TQQW +WT/SG/TQTW +WT/SG/TRUW +WT/SG/TSAW +WT/SG/TSGW +WT/SG/TSNW +WT/SG/TSTW +WT/SG/TSUW +WT/SG/TSXW +WT/SG/TSYW +WT/SG/TTBW +WT/SG/TTTW +WT/SG/TUAW +WT/SG/TVBW +WT/SG/TWJW +WT/SG/TWQW +WT/SG/TYFW +WT/SG/TYTW +WT/SG/UAHW +WT/SG/UAUW +WT/SG/UBAW +WT/SG/UBCW +WT/SG/UBUW +WT/SG/UBYW +WT/SG/UCCW +WT/SG/UCFW +WT/SG/UCHW +WT/SG/UCZW +WT/SG/UDOW +WT/SG/UDYW +WT/SG/UFDW +WT/SG/UFSW +WT/SG/UGNW +WT/SG/UHJW +WT/SG/UHTW +WT/SG/UIJW +WT/SG/UIOW +WT/SG/UIWW +WT/SG/UIZW +WT/SG/UJUW +WT/SG/UKMW +WT/SG/ULBW +WT/SG/ULDW +WT/SG/ULNW +WT/SG/ULQW +WT/SG/ULXW +WT/SG/UMCW +WT/SG/UMEW +WT/SG/UNBW +WT/SG/UNFW +WT/SG/UNOW +WT/SG/UOLW +WT/SG/UOOW +WT/SG/UORW +WT/SG/UPPW +WT/SG/UPRW +WT/SG/UPSW +WT/SG/UQAW +WT/SG/UQKW +WT/SG/UQOW +WT/SG/UQQW +WT/SG/UQTW +WT/SG/URI +WT/SG/UROW +WT/SG/USAW +WT/SG/USBW +WT/SG/USDW +WT/SG/USFW +WT/SG/USGW +WT/SG/USHW +WT/SG/USJW +WT/SG/USKW +WT/SG/USMW +WT/SG/USPW +WT/SG/USQW +WT/SG/USRW +WT/SG/USTW +WT/SG/USUW +WT/SG/USWW +WT/SG/USXW +WT/SG/USYW +WT/SG/USZW +WT/SG/UTNW +WT/SG/UTOW +WT/SG/UUIW +WT/SG/UURW +WT/SG/UUZW +WT/SG/UVHW +WT/SG/UVTW +WT/SG/UVYW +WT/SG/UWHW +WT/SG/UY7W +WT/SG/UYEW +WT/SG/UYIW +WT/SG/UYNW +WT/SG/UZGW +WT/SG/UZHW +WT/SG/UZMW +WT/SG/V0QW +WT/SG/V1LW +WT/SG/V1XW +WT/SG/V2BW +WT/SG/V2IW +WT/SG/V2UW +WT/SG/V3XW +WT/SG/V4JW +WT/SG/V5PW +WT/SG/V5TW +WT/SG/V6GW +WT/SG/V6JW +WT/SG/V6QW +WT/SG/V7SW +WT/SG/V8QW +WT/SG/V8TW +WT/SG/V8ZW +WT/SG/V9JW +WT/SG/V9TW +WT/SG/V9UW +WT/SG/V9WW +WT/SG/VA2W +WT/SG/VA5W +WT/SG/VAHW +WT/SG/VAOW +WT/SG/VBDW +WT/SG/VBEW +WT/SG/VBFW +WT/SG/VBTW +WT/SG/VC7W +WT/SG/VCFW +WT/SG/VCMW +WT/SG/VCSW +WT/SG/VCZW +WT/SG/VD6W +WT/SG/VDPW +WT/SG/VDRW +WT/SG/VEVW +WT/SG/VFNW +WT/SG/VH8W +WT/SG/VHCW +WT/SG/VHGW +WT/SG/VHXW +WT/SG/VI8W +WT/SG/VID +WT/SG/VIQW +WT/SG/VJ6W +WT/SG/VJ7W +WT/SG/VJAW +WT/SG/VJKW +WT/SG/VJLW +WT/SG/VJWW +WT/SG/VJXW +WT/SG/VK1W +WT/SG/VKFW +WT/SG/VKIW +WT/SG/VKJW +WT/SG/VLDW +WT/SG/VLLW +WT/SG/VLMW +WT/SG/VLSW +WT/SG/VLUW +WT/SG/VLVW +WT/SG/VMGW +WT/SG/VMHW +WT/SG/VMPW +WT/SG/VMZW +WT/SG/VNBW +WT/SG/VNOW +WT/SG/VODW +WT/SG/VOQW +WT/SG/VP1W +WT/SG/VPBW +WT/SG/VPCW +WT/SG/VPDW +WT/SG/VPXW +WT/SG/VPYW +WT/SG/VQ3W +WT/SG/VQBW +WT/SG/VR2W +WT/SG/VR9W +WT/SG/VSHW +WT/SG/VSQW +WT/SG/VT6W +WT/SG/VTMW +WT/SG/VTOW +WT/SG/VTTW +WT/SG/VTVW +WT/SG/VU5W +WT/SG/VU8W +WT/SG/VUBW +WT/SG/VUOW +WT/SG/VUQW +WT/SG/VVBW +WT/SG/VWFW +WT/SG/VWKW +WT/SG/VXJW +WT/SG/VXRW +WT/SG/VY1W +WT/SG/VY2W +WT/SG/VY9W +WT/SG/VYUW +WT/SG/VZLW +WT/SG/VZVW +WT/SG/W1AW +WT/SG/W2VW +WT/SG/W3MW +WT/SG/W3QW +WT/SG/W3VW +WT/SG/W4SW +WT/SG/W4UW +WT/SG/W5BW +WT/SG/W5RW +WT/SG/W5SW +WT/SG/W6HW +WT/SG/W6LW +WT/SG/W7MW +WT/SG/W7QW +WT/SG/W7WW +WT/SG/W7XW +WT/SG/W8OW +WT/SG/W8PW +WT/SG/W8TW +WT/SG/W9AW +WT/SG/W9KW +WT/SG/W9QW +WT/SG/WA9W +WT/SG/WASW +WT/SG/WB3W +WT/SG/WBAW +WT/SG/WBQW +WT/SG/WBTW +WT/SG/WBWW +WT/SG/WC5W +WT/SG/WCLW +WT/SG/WCQW +WT/SG/WCTW +WT/SG/WD1W +WT/SG/WD6W +WT/SG/WDHW +WT/SG/WDTW +WT/SG/WDWW +WT/SG/WDYW +WT/SG/WE2W +WT/SG/WEBW +WT/SG/WF0W +WT/SG/WFUW +WT/SG/WG4W +WT/SG/WGFW +WT/SG/WGQW +WT/SG/WGX +WT/SG/WH8W +WT/SG/WHCW +WT/SG/WHHW +WT/SG/WI4W +WT/SG/WIAW +WT/SG/WIBW +WT/SG/WIEW +WT/SG/WIIW +WT/SG/WJBW +WT/SG/WJDW +WT/SG/WJGW +WT/SG/WJTW +WT/SG/WK6W +WT/SG/WKDW +WT/SG/WKUW +WT/SG/WL2W +WT/SG/WL3W +WT/SG/WL5W +WT/SG/WL9W +WT/SG/WLWW +WT/SG/WLXW +WT/SG/WM8 +WT/SG/WMDW +WT/SG/WMGW +WT/SG/WMWW +WT/SG/WMYW +WT/SG/WNDW +WT/SG/WNLW +WT/SG/WNNW +WT/SG/WNTW +WT/SG/WO4W +WT/SG/WOJW +WT/SG/WPBW +WT/SG/WPWW +WT/SG/WQBW +WT/SG/WQPW +WT/SG/WRNW +WT/SG/WRYW +WT/SG/WTNW +WT/SG/WTUW +WT/SG/WTXW +WT/SG/WTZW +WT/SG/WUL +WT/SG/WV5W +WT/SG/WVNW +WT/SG/WW2W +WT/SG/WWHW +WT/SG/WWRW +WT/SG/WWZW +WT/SG/WXGW +WT/SG/WXPW +WT/SG/WY3W +WT/SG/WYBW +WT/SG/WYHW +WT/SG/WYMW +WT/SG/WYQW +WT/SG/WYRW +WT/SG/WZOW +WT/SG/X0TW +WT/SG/X1HW +WT/SG/X1MW +WT/SG/X1RW +WT/SG/X1TW +WT/SG/X2DW +WT/SG/X2PW +WT/SG/X2YW +WT/SG/X3FW +WT/SG/X5HW +WT/SG/X5RW +WT/SG/X6CW +WT/SG/X6HW +WT/SG/X6UW +WT/SG/X7GW +WT/SG/X7IW +WT/SG/X7NW +WT/SG/X7XW +WT/SG/X8AW +WT/SG/X8IW +WT/SG/X8JW +WT/SG/X8YW +WT/SG/X9LW +WT/SG/XAHW +WT/SG/XAPW +WT/SG/XAVW +WT/SG/XB3W +WT/SG/XB4W +WT/SG/XBFW +WT/SG/XBJW +WT/SG/XBNW +WT/SG/XC2W +WT/SG/XCVW +WT/SG/XDBW +WT/SG/XDLW +WT/SG/XDTW +WT/SG/XEFW +WT/SG/XEGW +WT/SG/XEPW +WT/SG/XEQW +WT/SG/XEWW +WT/SG/XEYW +WT/SG/XFAW +WT/SG/XFEW +WT/SG/XFHW +WT/SG/XFPW +WT/SG/XG5W +WT/SG/XGFW +WT/SG/XGLW +WT/SG/XGZW +WT/SG/XH2W +WT/SG/XH8W +WT/SG/XHHW +WT/SG/XHMW +WT/SG/XIBW +WT/SG/XIRW +WT/SG/XJIW +WT/SG/XJRW +WT/SG/XK5W +WT/SG/XKBW +WT/SG/XKIW +WT/SG/XKJW +WT/SG/XLHW +WT/SG/XLQW +WT/SG/XM4W +WT/SG/XMDW +WT/SG/XMFW +WT/SG/XMHW +WT/SG/XMKW +WT/SG/XMUW +WT/SG/XN7W +WT/SG/XNEW +WT/SG/XNFW +WT/SG/XNOW +WT/SG/XOHW +WT/SG/XONW +WT/SG/XOXW +WT/SG/XOZW +WT/SG/XP0W +WT/SG/XP5W +WT/SG/XP7W +WT/SG/XPAW +WT/SG/XPCW +WT/SG/XPJW +WT/SG/XPKW +WT/SG/XQ0W +WT/SG/XQSW +WT/SG/XR6W +WT/SG/XRFW +WT/SG/XRXW +WT/SG/XSDW +WT/SG/XSVW +WT/SG/XT4W +WT/SG/XTJW +WT/SG/XUNW +WT/SG/XV4W +WT/SG/XVYW +WT/SG/XW6W +WT/SG/XWBW +WT/SG/XWEW +WT/SG/XWPW +WT/SG/XWYW +WT/SG/XX1W +WT/SG/XX5W +WT/SG/XX8W +WT/SG/XXIW +WT/SG/XXRW +WT/SG/XXSW +WT/SG/XY0W +WT/SG/XY5W +WT/SG/XYUW +WT/SG/XYWW +WT/SG/XYYW +WT/SG/XZIW +WT/SG/Y0ZW +WT/SG/Y1CW +WT/SG/Y1NW +WT/SG/Y1WW +WT/SG/Y2FW +WT/SG/Y3KW +WT/SG/Y3RW +WT/SG/Y4GW +WT/SG/Y5AW +WT/SG/Y5E +WT/SG/Y5FW +WT/SG/Y6QW +WT/SG/Y7VW +WT/SG/Y8OW +WT/SG/Y8RW +WT/SG/Y9AW +WT/SG/Y9GW +WT/SG/Y9SW +WT/SG/Y9UW +WT/SG/YACW +WT/SG/YAL +WT/SG/YB2W +WT/SG/YB4W +WT/SG/YB5W +WT/SG/YC5W +WT/SG/YCJW +WT/SG/YCNW +WT/SG/YCPW +WT/SG/YCQW +WT/SG/YCRW +WT/SG/YD5W +WT/SG/YDAW +WT/SG/YDKW +WT/SG/YEMW +WT/SG/YF2W +WT/SG/YF5W +WT/SG/YFQW +WT/SG/YFWW +WT/SG/YHSW +WT/SG/YI1W +WT/SG/YI9W +WT/SG/YIHW +WT/SG/YIQW +WT/SG/YIYW +WT/SG/YJ4W +WT/SG/YJ7W +WT/SG/YJXW +WT/SG/YJZW +WT/SG/YK1W +WT/SG/YK7W +WT/SG/YKDW +WT/SG/YKEW +WT/SG/YKHW +WT/SG/YKNW +WT/SG/YKVW +WT/SG/YL1W +WT/SG/YL4W +WT/SG/YL5W +WT/SG/YM4W +WT/SG/YMAW +WT/SG/YMCW +WT/SG/YMSW +WT/SG/YMWW +WT/SG/YN4W +WT/SG/YNDW +WT/SG/YNHW +WT/SG/YNVW +WT/SG/YO8W +WT/SG/YODW +WT/SG/YOQW +WT/SG/YPCW +WT/SG/YPLW +WT/SG/YPMW +WT/SG/YQAW +WT/SG/YR3W +WT/SG/YR6W +WT/SG/YRCW +WT/SG/YRKW +WT/SG/YRSW +WT/SG/YS5W +WT/SG/YS6W +WT/SG/YSHW +WT/SG/YT2W +WT/SG/YT4W +WT/SG/YTMW +WT/SG/YTTW +WT/SG/YUEW +WT/SG/YUIW +WT/SG/YUYW +WT/SG/YVAW +WT/SG/YVBW +WT/SG/YVEW +WT/SG/YVJW +WT/SG/YVRW +WT/SG/YVZW +WT/SG/YW4W +WT/SG/YW5W +WT/SG/YW6W +WT/SG/YWFW +WT/SG/YWQW +WT/SG/YWVW +WT/SG/YXMW +WT/SG/YYQW +WT/SG/YYZW +WT/SG/YZ5W +WT/SG/YZEW +WT/SG/YZJW +WT/SG/YZMW +WT/SG/Z0SW +WT/SG/Z1DW +WT/SG/Z2PW +WT/SG/Z2RW +WT/SG/Z3IW +WT/SG/Z3LW +WT/SG/Z3RW +WT/SG/Z3SW +WT/SG/Z4LW +WT/SG/Z4TW +WT/SG/Z4WW +WT/SG/Z4XW +WT/SG/Z5FW +WT/SG/Z5MW +WT/SG/Z5TW +WT/SG/Z5WW +WT/SG/Z5ZW +WT/SG/Z7CW +WT/SG/Z7MW +WT/SG/Z8PW +WT/SG/Z8QW +WT/SG/Z8TW +WT/SG/Z9UW +WT/SG/ZA7W +WT/SG/ZAJW +WT/SG/ZAXW +WT/SG/ZB2W +WT/SG/ZBLW +WT/SG/ZBTW +WT/SG/ZC8W +WT/SG/ZCAW +WT/SG/ZCIW +WT/SG/ZCLW +WT/SG/ZDBW +WT/SG/ZE9W +WT/SG/ZFIW +WT/SG/ZFSW +WT/SG/ZG7W +WT/SG/ZHXW +WT/SG/ZL1W +WT/SG/ZLBW +WT/SG/ZLNW +WT/SG/ZLYW +WT/SG/ZM2W +WT/SG/ZNBW +WT/SG/ZNPW +WT/SG/ZOGW +WT/SG/ZOHW +WT/SG/ZOPW +WT/SG/ZP4W +WT/SG/ZP6W +WT/SG/ZP7W +WT/SG/ZPGW +WT/SG/ZQ5W +WT/SG/ZRFW +WT/SG/ZRVW +WT/SG/ZRWW +WT/SG/ZRYW +WT/SG/ZS6W +WT/SG/ZSAW +WT/SG/ZSEW +WT/SG/ZSHW +WT/SG/ZSVW +WT/SG/ZSYW +WT/SG/ZSZW +WT/SG/ZTQW +WT/SG/ZTZW +WT/SG/ZU5W +WT/SG/ZU7W +WT/SG/ZVNW +WT/SG/ZVUW +WT/SG/ZWAW +WT/SG/ZWGW +WT/SG/ZWLW +WT/SG/ZWUW +WT/SG/ZY4W +WT/SG/ZYBW +WT/SG/ZYGW +WT/SG/ZYLW +WT/SG/ZYOW +WT/SG/ZYPW diff --git a/rust/src/utils/counter.rs b/rust/src/utils/counter.rs index fd40c9a0c..220e2a473 100644 --- a/rust/src/utils/counter.rs +++ b/rust/src/utils/counter.rs @@ -1,35 +1,70 @@ +//! Symbol ↔ counter_id conversion utilities. +//! +//! A `counter_id` is the internal instrument identifier used by the +//! Longbridge backend, e.g. `ST/US/TSLA`, `ETF/US/SPY`, `IX/HK/HSI`, +//! `WT/HK/10005`. These helpers convert between user-facing symbols +//! (e.g. `TSLA.US`, `700.HK`, `.DJI.US`) and counter IDs, using an +//! embedded ETF + index + warrant directory to pick the right prefix. + use std::{collections::HashSet, sync::OnceLock}; -static US_ETF_SET: OnceLock> = OnceLock::new(); +static SPECIAL_COUNTER_IDS: OnceLock> = OnceLock::new(); -fn us_etf_set() -> &'static HashSet<&'static str> { - US_ETF_SET.get_or_init(|| { - include_str!("US-ETF.csv") - .lines() - .map(str::trim) - .filter(|s| !s.is_empty()) - .collect() +fn special_counter_ids() -> &'static HashSet<&'static str> { + SPECIAL_COUNTER_IDS.get_or_init(|| { + [ + include_str!("US-ETF.csv"), + include_str!("US-IX.csv"), + include_str!("US-WT.csv"), + ] + .iter() + .flat_map(|s| s.lines()) + .map(str::trim) + .filter(|s| !s.is_empty()) + .collect() }) } -/// Convert a symbol (e.g. `TSLA.US`) to a counter_id (e.g. `ST/US/TSLA`). -/// US ETFs are detected via embedded list. -pub(crate) fn symbol_to_counter_id(symbol: &str) -> String { +/// Convert a user-supplied symbol (e.g. `TSLA.US`, `700.HK`, `.DJI.US`, +/// `HSI.HK`) to a counter_id (e.g. `ST/US/TSLA`, `ST/HK/700`, `IX/US/.DJI`, +/// `IX/HK/HSI`). +/// +/// Leading-dot symbols (e.g. `.DJI.US`) are US market indexes and always map +/// to `IX/`. All other symbols are checked against the embedded +/// ETF + index + warrant set; a matching entry is returned as-is. Unmatched +/// symbols default to `ST/`. +pub fn symbol_to_counter_id(symbol: &str) -> String { if let Some((code, market)) = symbol.rsplit_once('.') { let market = market.to_uppercase(); - let etf_candidate = format!("ETF/{market}/{code}"); - if us_etf_set().contains(etf_candidate.as_str()) { - etf_candidate + // Leading-dot symbols are US market indexes; the dot is part of the + // counter_id (e.g. `.DJI.US` → `IX/US/.DJI`) + if code.starts_with('.') { + return format!("IX/{market}/{code}"); + } + // Strip leading zeros from numeric HK codes (e.g. `00700` → `700`). + // Other markets keep their codes verbatim (A-share codes such as + // `000001.SZ` have significant leading zeros). + let code = if market == "HK" && code.chars().all(|c| c.is_ascii_digit()) { + code.trim_start_matches('0') } else { - format!("ST/{market}/{code}") + code + }; + // Check special counter_ids set (ETF, IX, and WT entries) + for prefix in &["ETF", "IX", "WT"] { + let candidate = format!("{prefix}/{market}/{code}"); + if special_counter_ids().contains(candidate.as_str()) { + return candidate; + } } + format!("ST/{market}/{code}") } else { symbol.to_string() } } -/// Convert an index symbol (e.g. `HSI.HK`) to counter_id (e.g. `IX/HK/HSI`). -pub(crate) fn index_symbol_to_counter_id(symbol: &str) -> String { +/// Convert an index symbol (e.g. `HSI.HK`) to counter_id (e.g. `IX/HK/HSI`), +/// always using the `IX/` prefix. +pub fn index_symbol_to_counter_id(symbol: &str) -> String { if let Some((code, market)) = symbol.rsplit_once('.') { format!("IX/{}/{code}", market.to_uppercase()) } else { @@ -37,8 +72,13 @@ pub(crate) fn index_symbol_to_counter_id(symbol: &str) -> String { } } -/// Convert a counter_id (e.g. `ST/US/TSLA`) back to a symbol (e.g. `TSLA.US`). -pub(crate) fn counter_id_to_symbol(counter_id: &str) -> String { +/// Convert a counter_id (e.g. `ST/US/TSLA`, `ETF/US/SPY`, `IX/US/.DJI`, +/// `ST/HK/700`) back to a display symbol (e.g. `TSLA.US`, `SPY.US`, +/// `.DJI.US`, `700.HK`). +/// +/// US index counter IDs (`IX/US/...`) preserve the leading dot in the code +/// part (e.g. `IX/US/.DJI` → `.DJI.US`). +pub fn counter_id_to_symbol(counter_id: &str) -> String { let parts: Vec<&str> = counter_id.splitn(3, '/').collect(); if parts.len() == 3 { format!("{}.{}", parts[2], parts[1]) @@ -47,6 +87,15 @@ pub(crate) fn counter_id_to_symbol(counter_id: &str) -> String { } } +/// Whether a user-supplied symbol resolves to an ETF (e.g. `QQQ.US`, +/// `SPY.US`). +/// +/// Determined by checking the embedded special counter_id set: a symbol is an +/// ETF when [`symbol_to_counter_id`] maps it to an `ETF/...` counter_id. +pub fn is_etf(symbol: &str) -> bool { + symbol_to_counter_id(symbol).starts_with("ETF/") +} + /// serde deserializer: reads a `counter_id` string and converts it to a symbol. pub(crate) fn deserialize_counter_id_as_symbol<'de, D>(d: D) -> Result where @@ -72,15 +121,104 @@ mod tests { } #[test] - fn etf_us() { + fn stock_hk_leading_zeros() { + assert_eq!(symbol_to_counter_id("00700.HK"), "ST/HK/700"); + } + + #[test] + fn stock_hk_leading_zeros_short() { + assert_eq!(symbol_to_counter_id("09988.HK"), "ST/HK/9988"); + } + + #[test] + fn stock_sz_keeps_leading_zeros() { + assert_eq!(symbol_to_counter_id("000001.SZ"), "ST/SZ/000001"); + } + + #[test] + fn etf_us_spy() { assert_eq!(symbol_to_counter_id("SPY.US"), "ETF/US/SPY"); } + #[test] + fn etf_us_qqq() { + assert_eq!(symbol_to_counter_id("QQQ.US"), "ETF/US/QQQ"); + } + + #[test] + fn etf_us_dram() { + assert_eq!(symbol_to_counter_id("DRAM.US"), "ETF/US/DRAM"); + } + + #[test] + fn market_suffix_lowercase_normalised() { + assert_eq!(symbol_to_counter_id("SPY.us"), "ETF/US/SPY"); + } + + #[test] + fn no_dot_passthrough() { + assert_eq!(symbol_to_counter_id("NODOT"), "NODOT"); + } + + #[test] + fn ix_us_dji() { + assert_eq!(symbol_to_counter_id(".DJI.US"), "IX/US/.DJI"); + } + + #[test] + fn ix_us_vix() { + assert_eq!(symbol_to_counter_id(".VIX.US"), "IX/US/.VIX"); + } + + #[test] + fn ix_us_ixic() { + assert_eq!(symbol_to_counter_id(".IXIC.US"), "IX/US/.IXIC"); + } + + #[test] + fn ix_us_spx() { + assert_eq!(symbol_to_counter_id(".SPX.US"), "IX/US/.SPX"); + } + + #[test] + fn ix_hk_hsi_via_set() { + assert_eq!(symbol_to_counter_id("HSI.HK"), "IX/HK/HSI"); + } + + #[test] + fn wt_hk_via_set() { + assert_eq!(symbol_to_counter_id("10005.HK"), "WT/HK/10005"); + } + + #[test] + fn is_etf_us() { + assert!(is_etf("QQQ.US")); + assert!(is_etf("SPY.US")); + assert!(is_etf("DRAM.US")); + } + + #[test] + fn is_etf_non_etf() { + assert!(!is_etf("TSLA.US")); + assert!(!is_etf("HSI.HK")); + assert!(!is_etf("700.HK")); + } + #[test] fn index() { assert_eq!(index_symbol_to_counter_id("HSI.HK"), "IX/HK/HSI"); } + #[test] + fn counter_id_ix_us_to_symbol() { + assert_eq!(counter_id_to_symbol("IX/US/.DJI"), ".DJI.US"); + } + + #[test] + fn counter_id_ix_hk_to_symbol() { + assert_eq!(counter_id_to_symbol("IX/HK/HSI"), "HSI.HK"); + } + #[test] fn roundtrip() { let cid = symbol_to_counter_id("TSLA.US"); diff --git a/rust/src/utils/mod.rs b/rust/src/utils/mod.rs index 7b636b688..a33a516c4 100644 --- a/rust/src/utils/mod.rs +++ b/rust/src/utils/mod.rs @@ -1 +1 @@ -pub(crate) mod counter; +pub mod counter; From c30a1c482cf8b9a7d444d4d7e1aaafc90a73be15 Mon Sep 17 00:00:00 2001 From: Jason Lee Date: Thu, 4 Jun 2026 16:47:00 +0800 Subject: [PATCH 20/26] feat(quote): symbol_to_counter_ids API with cached local-first resolution (#538) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary - **`QuoteContext::symbol_to_counter_ids(symbols)`** — batch symbol → counter_id conversion via the new `POST /v1/quote/symbol-to-counter-ids` endpoint (request `{ticker_regions: [\"TSLA.US\", \"700.HK\"]}`, response `{list: {symbol: counter_id}}`; unrecognized symbols are omitted) - **`QuoteContext::resolve_counter_ids(symbols)`** — local-first resolution: embedded ETF/IX/WT directory + resolved-cache hits are answered without network; remaining symbols are resolved in one batch remotely, persisted to **`~/.longbridge/cache/counter-ids.csv`** (one counter_id per line, same format as the embedded directory files; directory overridable via `LONGBRIDGE_CACHE_DIR`), and answered from cache afterwards. Backend-unrecognized symbols fall back to the default `ST/` conversion (and are not cached) - The cache is a counter_id set; lookups match `ETF/IX/WT/ST` prefix candidates against it — backend-confirmed `ST/` entries are cached too, so repeat resolutions of plain stocks also skip the network - `counter` module gains `lookup_counter_id` / `cache_counter_ids`; `symbol_to_counter_id` now also consults the resolved cache — so newly listed instruments missing from the embedded directory (the DRAM.US class of problem) resolve correctly after the first remote query - Blocking wrappers on `QuoteContextSync`; Rust only for now (bindings to follow as needed) ## Verification - `cargo test -p longbridge --lib utils::counter`: 24 passed (incl. CSV cache roundtrip + local lookup tests) - `cargo clippy --all --all-features`: clean - Live against staging: `resolve_counter_ids([\"DRAM.US\", \"TSLA.US\", \"QQQ.US\", \"NEWFAKE.US\"])` → DRAM/QQQ resolved locally, TSLA resolved remotely **and persisted to the cache file**, NEWFAKE fell back to `ST/US/NEWFAKE` without being cached 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 4.8 (1M context) --- CHANGELOG.md | 1 + rust/src/blocking/quote.rs | 19 ++++ rust/src/quote/context.rs | 76 ++++++++++++++++ rust/src/utils/counter.rs | 175 +++++++++++++++++++++++++++++++++---- 4 files changed, 256 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7715d3a56..9ed526f5d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - **All languages:** `FundamentalContext` gains `etf_asset_allocation(symbol)` — queries `GET /v1/quote/etf-asset-allocation` for ETF asset allocation grouped by element type (`Holdings` / `Regional` / `AssetClass` / `Industry`); returns `AssetAllocationResponse` with report date, position ratios, localized names, and per-holding detail - **Rust:** new public `longbridge::counter` module — `symbol_to_counter_id`, `index_symbol_to_counter_id`, `counter_id_to_symbol`, and `is_etf`, backed by the embedded ETF + index + warrant directory, so downstream consumers (CLI / MCP) no longer need their own copies +- **Rust:** `QuoteContext` gains `symbol_to_counter_ids(symbols)` (batch conversion via `POST /v1/quote/symbol-to-counter-ids`) and `resolve_counter_ids(symbols)` (local-first resolution with remote fallback) — remotely resolved entries are persisted to `~/.longbridge/cache/counter-ids.csv` (one counter_id per line, override the directory with `LONGBRIDGE_CACHE_DIR`) and consulted by subsequent `counter` lookups, so symbols missing from the embedded directory (e.g. newly listed ETFs) resolve correctly after the first query ### Changed diff --git a/rust/src/blocking/quote.rs b/rust/src/blocking/quote.rs index fbba09273..a18cfd217 100644 --- a/rust/src/blocking/quote.rs +++ b/rust/src/blocking/quote.rs @@ -1213,4 +1213,23 @@ impl QuoteContextSync { self.rt .call(move |ctx| async move { ctx.short_trades(symbol, count).await }) } + + /// Batch convert symbols to counter IDs via the remote API + pub fn symbol_to_counter_ids( + &self, + symbols: Vec, + ) -> Result> { + self.rt + .call(move |ctx| async move { ctx.symbol_to_counter_ids(symbols).await }) + } + + /// Resolve counter IDs for symbols, local-first with remote fallback and + /// local caching + pub fn resolve_counter_ids( + &self, + symbols: Vec, + ) -> Result> { + self.rt + .call(move |ctx| async move { ctx.resolve_counter_ids(symbols).await }) + } } diff --git a/rust/src/quote/context.rs b/rust/src/quote/context.rs index 168525c95..663142c2f 100644 --- a/rust/src/quote/context.rs +++ b/rust/src/quote/context.rs @@ -1,4 +1,5 @@ use std::{ + collections::HashMap, sync::{Arc, RwLock}, time::Duration, }; @@ -2198,6 +2199,81 @@ impl QuoteContext { Ok(()) } + + // ── symbol_to_counter_ids ───────────────────────────────────── + + /// Batch convert symbols to counter IDs via the remote API. + /// + /// Returns a map of `symbol → counter_id` (e.g. `DRAM.US` → + /// `ETF/US/DRAM`). Symbols the backend does not recognize are omitted + /// from the result. + /// + /// Path: `POST /v1/quote/symbol-to-counter-ids` + pub async fn symbol_to_counter_ids( + &self, + symbols: Vec, + ) -> Result> { + #[derive(Debug, Serialize)] + struct Request { + ticker_regions: Vec, + } + #[derive(Debug, Deserialize)] + struct Response { + #[serde(default)] + list: HashMap, + } + + let resp = self + .0 + .http_cli + .request(Method::POST, "/v1/quote/symbol-to-counter-ids") + .body(Json(Request { + ticker_regions: symbols, + })) + .response::>() + .send() + .with_subscriber(self.0.log_subscriber.clone()) + .await?; + Ok(resp.0.list) + } + + /// Resolve counter IDs for symbols, local-first with remote fallback. + /// + /// Symbols found in the embedded ETF / index / warrant directory (or in + /// the local cache of previous remote resolutions) are resolved without + /// network access. The remaining symbols are resolved in one batch via + /// [`symbol_to_counter_ids`](Self::symbol_to_counter_ids) and the results + /// are persisted to the local cache for subsequent lookups. Symbols the + /// backend does not recognize fall back to the default `ST/` conversion. + pub async fn resolve_counter_ids( + &self, + symbols: Vec, + ) -> Result> { + use crate::utils::counter; + + let mut result = HashMap::with_capacity(symbols.len()); + let mut unknown = Vec::new(); + for symbol in symbols { + match counter::lookup_counter_id(&symbol) { + Some(counter_id) => { + result.insert(symbol, counter_id); + } + None => unknown.push(symbol), + } + } + if !unknown.is_empty() { + let resolved = self.symbol_to_counter_ids(unknown.clone()).await?; + counter::cache_counter_ids(resolved.values().map(String::as_str)); + for symbol in unknown { + let counter_id = resolved + .get(&symbol) + .cloned() + .unwrap_or_else(|| counter::symbol_to_counter_id(&symbol)); + result.insert(symbol, counter_id); + } + } + Ok(result) + } } fn normalize_symbol(symbol: &str) -> &str { diff --git a/rust/src/utils/counter.rs b/rust/src/utils/counter.rs index 220e2a473..beacec3e0 100644 --- a/rust/src/utils/counter.rs +++ b/rust/src/utils/counter.rs @@ -5,8 +5,16 @@ //! `WT/HK/10005`. These helpers convert between user-facing symbols //! (e.g. `TSLA.US`, `700.HK`, `.DJI.US`) and counter IDs, using an //! embedded ETF + index + warrant directory to pick the right prefix. +//! +//! The embedded directory may lag behind newly listed instruments. Entries +//! resolved remotely (see `QuoteContext::resolve_counter_ids`) are persisted +//! to a local cache file and consulted on subsequent lookups. -use std::{collections::HashSet, sync::OnceLock}; +use std::{ + collections::HashSet, + path::PathBuf, + sync::{OnceLock, RwLock}, +}; static SPECIAL_COUNTER_IDS: OnceLock> = OnceLock::new(); @@ -25,22 +33,128 @@ fn special_counter_ids() -> &'static HashSet<&'static str> { }) } +// ── remote-resolved counter_id cache ────────────────────────────── + +static CACHED_COUNTER_IDS: OnceLock>> = OnceLock::new(); + +#[cfg(test)] +static TEST_CACHE_DIR: OnceLock = OnceLock::new(); + +/// Cache file path: `$LONGBRIDGE_CACHE_DIR/counter-ids.csv`, defaulting to +/// `~/.longbridge/cache/counter-ids.csv` (one counter_id per line, same +/// format as the embedded directory files). +fn cache_file_path() -> Option { + #[cfg(test)] + if let Some(dir) = TEST_CACHE_DIR.get() { + return Some(dir.join("counter-ids.csv")); + } + let dir = match std::env::var_os("LONGBRIDGE_CACHE_DIR") { + Some(dir) => PathBuf::from(dir), + None => { + #[cfg(windows)] + let home = std::env::var_os("USERPROFILE")?; + #[cfg(not(windows))] + let home = std::env::var_os("HOME")?; + PathBuf::from(home).join(".longbridge").join("cache") + } + }; + Some(dir.join("counter-ids.csv")) +} + +fn cached_counter_ids() -> &'static RwLock> { + CACHED_COUNTER_IDS.get_or_init(|| { + let set = cache_file_path() + .and_then(|path| std::fs::read_to_string(path).ok()) + .map(|s| { + s.lines() + .map(str::trim) + .filter(|line| !line.is_empty()) + .map(ToString::to_string) + .collect() + }) + .unwrap_or_default(); + RwLock::new(set) + }) +} + +/// Merge remotely resolved counter IDs into the local cache (in memory and +/// on disk), so subsequent [`symbol_to_counter_id`] / [`lookup_counter_id`] +/// calls resolve them without another network round trip. +pub fn cache_counter_ids<'a>(counter_ids: impl IntoIterator) { + let mut set = match cached_counter_ids().write() { + Ok(guard) => guard, + Err(poisoned) => poisoned.into_inner(), + }; + let before = set.len(); + set.extend( + counter_ids + .into_iter() + .map(str::trim) + .filter(|id| !id.is_empty()) + .map(ToString::to_string), + ); + if set.len() == before { + return; + } + if let Some(path) = cache_file_path() { + if let Some(parent) = path.parent() { + let _ = std::fs::create_dir_all(parent); + } + let mut lines: Vec<&str> = set.iter().map(String::as_str).collect(); + lines.sort_unstable(); + let _ = std::fs::write(path, lines.join("\n") + "\n"); + } +} + +/// Look up a symbol in the local directory only (embedded special set, the +/// remote-resolved cache, and leading-dot index notation). Returns `None` +/// when the symbol is unknown locally — i.e. [`symbol_to_counter_id`] would +/// fall back to the default `ST/` prefix, which may be wrong for newly +/// listed ETFs / indexes / warrants. +pub fn lookup_counter_id(symbol: &str) -> Option { + let (code, market) = symbol.rsplit_once('.')?; + let market = market.to_uppercase(); + if code.starts_with('.') { + return Some(format!("IX/{market}/{code}")); + } + let code = if market == "HK" && code.chars().all(|c| c.is_ascii_digit()) { + code.trim_start_matches('0') + } else { + code + }; + for prefix in &["ETF", "IX", "WT"] { + let candidate = format!("{prefix}/{market}/{code}"); + if special_counter_ids().contains(candidate.as_str()) { + return Some(candidate); + } + } + let cached = match cached_counter_ids().read() { + Ok(guard) => guard, + Err(poisoned) => poisoned.into_inner(), + }; + for prefix in &["ETF", "IX", "WT", "ST"] { + let candidate = format!("{prefix}/{market}/{code}"); + if cached.contains(candidate.as_str()) { + return Some(candidate); + } + } + None +} + /// Convert a user-supplied symbol (e.g. `TSLA.US`, `700.HK`, `.DJI.US`, /// `HSI.HK`) to a counter_id (e.g. `ST/US/TSLA`, `ST/HK/700`, `IX/US/.DJI`, /// `IX/HK/HSI`). /// /// Leading-dot symbols (e.g. `.DJI.US`) are US market indexes and always map /// to `IX/`. All other symbols are checked against the embedded -/// ETF + index + warrant set; a matching entry is returned as-is. Unmatched -/// symbols default to `ST/`. +/// ETF + index + warrant set and the remote-resolved cache; a matching entry +/// is returned as-is. Unmatched symbols default to `ST/`. pub fn symbol_to_counter_id(symbol: &str) -> String { if let Some((code, market)) = symbol.rsplit_once('.') { - let market = market.to_uppercase(); - // Leading-dot symbols are US market indexes; the dot is part of the - // counter_id (e.g. `.DJI.US` → `IX/US/.DJI`) - if code.starts_with('.') { - return format!("IX/{market}/{code}"); + if let Some(counter_id) = lookup_counter_id(symbol) { + return counter_id; } + let market = market.to_uppercase(); // Strip leading zeros from numeric HK codes (e.g. `00700` → `700`). // Other markets keep their codes verbatim (A-share codes such as // `000001.SZ` have significant leading zeros). @@ -49,13 +163,6 @@ pub fn symbol_to_counter_id(symbol: &str) -> String { } else { code }; - // Check special counter_ids set (ETF, IX, and WT entries) - for prefix in &["ETF", "IX", "WT"] { - let candidate = format!("{prefix}/{market}/{code}"); - if special_counter_ids().contains(candidate.as_str()) { - return candidate; - } - } format!("ST/{market}/{code}") } else { symbol.to_string() @@ -224,4 +331,42 @@ mod tests { let cid = symbol_to_counter_id("TSLA.US"); assert_eq!(counter_id_to_symbol(&cid), "TSLA.US"); } + + #[test] + fn cached_counter_ids_roundtrip() { + let dir = std::env::temp_dir().join("lb-counter-cache-test"); + // Redirect the cache file away from the real user cache directory. + let dir = TEST_CACHE_DIR.get_or_init(|| dir).clone(); + + // Unknown symbol falls back to ST/ before caching + assert_eq!(lookup_counter_id("FAKE9.US"), None); + assert_eq!(symbol_to_counter_id("FAKE9.US"), "ST/US/FAKE9"); + + // After caching remote-resolved entries, lookups return them — + // including backend-confirmed ST/ entries + cache_counter_ids(["ETF/US/FAKE9", "ST/US/FAKE8"]); + assert_eq!( + lookup_counter_id("FAKE9.US").as_deref(), + Some("ETF/US/FAKE9") + ); + assert_eq!(symbol_to_counter_id("FAKE9.US"), "ETF/US/FAKE9"); + assert_eq!( + lookup_counter_id("FAKE8.US").as_deref(), + Some("ST/US/FAKE8") + ); + + // Persisted to disk as one counter_id per line + let saved = std::fs::read_to_string(dir.join("counter-ids.csv")).unwrap(); + assert_eq!(saved, "ETF/US/FAKE9\nST/US/FAKE8\n"); + let _ = std::fs::remove_dir_all(&dir); + } + + #[test] + fn lookup_known_special() { + assert_eq!(lookup_counter_id("QQQ.US").as_deref(), Some("ETF/US/QQQ")); + assert_eq!(lookup_counter_id("HSI.HK").as_deref(), Some("IX/HK/HSI")); + assert_eq!(lookup_counter_id(".DJI.US").as_deref(), Some("IX/US/.DJI")); + assert_eq!(lookup_counter_id("TSLA.US"), None); + assert_eq!(lookup_counter_id("NODOT"), None); + } } From 573846945971adf7586376292c318dc389b16552 Mon Sep 17 00:00:00 2001 From: Hogan Date: Thu, 4 Jun 2026 17:29:57 +0800 Subject: [PATCH 21/26] chore: release 4.3.0 (#539) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Bump version to `4.3.0` and promote `[Unreleased]` CHANGELOG to `[4.3.0]`. ## Changes in 4.3.0 ### Added - **All languages:** `FundamentalContext` gains `etf_asset_allocation(symbol)` — queries `GET /v1/quote/etf-asset-allocation` for ETF asset allocation grouped by element type (`Holdings` / `Regional` / `AssetClass` / `Industry`) - **Rust:** new public `longbridge::counter` module — `symbol_to_counter_id`, `index_symbol_to_counter_id`, `counter_id_to_symbol`, and `is_etf` - **Rust:** `QuoteContext` gains `symbol_to_counter_ids(symbols)` and `resolve_counter_ids(symbols)` ### Changed - `symbol_to_counter_id` now also consults the embedded index and warrant directories ### Fixed - Refreshed the embedded US ETF list (4574 → 7250 entries) and added index (648) + warrant (17693) directories --- CHANGELOG.md | 2 +- Cargo.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ed526f5d..707c9ed47 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [Unreleased] +## [4.3.0] ### Added diff --git a/Cargo.toml b/Cargo.toml index 932f6f842..815991451 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ resolver = "3" members = ["rust", "python", "nodejs", "java", "c"] [workspace.package] -version = "4.2.2" +version = "4.3.0" edition = "2024" [profile.release] From 4300207614964356b337fd4267e5ac87e8247a35 Mon Sep 17 00:00:00 2001 From: Hogan Date: Wed, 10 Jun 2026 19:25:13 +0800 Subject: [PATCH 22/26] fix(ci): replace msbuild longbridge.sln with cmake --build for Windows (#541) ## Problem `windows-latest` runner was upgraded to VS2026 (MSBuild 18.6.3), which generates a different `.sln` filename than VS2022. The Makefile.toml had `longbridge.sln` hardcoded, causing: ``` MSBUILD : error MSB1009: Project file does not exist. Switch: longbridge.sln ``` ## Fix Replace `msbuild longbridge.sln` with `cmake --build .` in `c/Makefile.toml` and `cpp/Makefile.toml`. `cmake --build` delegates to the underlying build system and doesn't depend on the `.sln` filename. **Before:** ```toml [tasks.c.windows] command = "msbuild" args = ["longbridge.sln", "-p:Configuration=Debug", "/t:cargo-build_longbridge_c"] ``` **After:** ```toml [tasks.c.windows] command = "cmake" args = ["--build", ".", "--config", "Debug", "--target", "cargo-build_longbridge_c"] ``` This change is backward-compatible with VS2022 and works with any cmake generator. --------- Co-authored-by: Claude Sonnet 4.6 (1M context) --- .github/workflows/ci.yml | 4 +++- .github/workflows/release.yml | 8 ++++++-- c/Makefile.toml | 12 ++++++------ cpp/Makefile.toml | 12 ++++++------ 4 files changed, 21 insertions(+), 15 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2250a1ea3..3b8264c60 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -302,7 +302,9 @@ jobs: uses: lukka/get-cmake@latest - name: Install cargo make - run: cargo install cargo-make + uses: taiki-e/install-action@v2 + with: + tool: cargo-make - name: Check with clippy run: cargo clippy -p longbridge-c --all-features diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d7dc64c16..c4e9be667 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -264,7 +264,9 @@ jobs: uses: lukka/get-cmake@latest - name: Install cargo make - run: cargo install cargo-make + uses: taiki-e/install-action@v2 + with: + tool: cargo-make - name: Build if: ${{ matrix.settings.target != 'aarch64-apple-darwin' }} @@ -348,7 +350,9 @@ jobs: uses: lukka/get-cmake@latest - name: Install cargo make - run: cargo install cargo-make + uses: taiki-e/install-action@v2 + with: + tool: cargo-make - name: Build if: ${{ matrix.settings.target != 'aarch64-apple-darwin' }} diff --git a/c/Makefile.toml b/c/Makefile.toml index ec14d1571..f2243ec09 100644 --- a/c/Makefile.toml +++ b/c/Makefile.toml @@ -9,13 +9,13 @@ args = ["cargo-build_longbridge_c"] cwd = "cmake.build" [tasks.c.windows] -command = "msbuild" -args = ["longbridge.sln", "-p:Configuration=Debug", "/t:cargo-build_longbridge_c"] +command = "cmake" +args = ["--build", ".", "--config", "Debug", "--target", "cargo-build_longbridge_c"] cwd = "cmake.build" [tasks.c-release.windows] -command = "msbuild" -args = ["longbridge.sln", "-p:Configuration=Release", "/t:cargo-build_longbridge_c"] +command = "cmake" +args = ["--build", ".", "--config", "Release", "--target", "cargo-build_longbridge_c"] cwd = "cmake.build" [tasks.c-test] @@ -24,6 +24,6 @@ args = ["test-c"] cwd = "cmake.build" [tasks.c-test.windows] -command = "msbuild" -args = ["longbridge.sln", "-p:Configuration=Debug", "/t:test-c"] +command = "cmake" +args = ["--build", ".", "--config", "Debug", "--target", "test-c"] cwd = "cmake.build" diff --git a/cpp/Makefile.toml b/cpp/Makefile.toml index 907f3dad4..f0d0f4cda 100644 --- a/cpp/Makefile.toml +++ b/cpp/Makefile.toml @@ -9,13 +9,13 @@ args = ["longbridge_cpp"] cwd = "cmake.build" [tasks.cpp.windows] -command = "msbuild" -args = ["longbridge.sln", "-p:Configuration=Debug", "/t:longbridge_cpp"] +command = "cmake" +args = ["--build", ".", "--config", "Debug", "--target", "longbridge_cpp"] cwd = "cmake.build" [tasks.cpp-release.windows] -command = "msbuild" -args = ["longbridge.sln", "-p:Configuration=Release", "/t:longbridge_cpp"] +command = "cmake" +args = ["--build", ".", "--config", "Release", "--target", "longbridge_cpp"] cwd = "cmake.build" [tasks.cpp-test] @@ -24,6 +24,6 @@ args = ["test-cpp"] cwd = "cmake.build" [tasks.cpp-test.windows] -command = "msbuild" -args = ["longbridge.sln", "-p:Configuration=Debug", "/t:test-cpp"] +command = "cmake" +args = ["--build", ".", "--config", "Debug", "--target", "test-cpp"] cwd = "cmake.build" From 534dfe0a1c6a5a553e49ad921fa1f8b76e1fe59a Mon Sep 17 00:00:00 2001 From: Hogan Date: Thu, 11 Jun 2026 17:29:30 +0800 Subject: [PATCH 23/26] feat(fundamental): add macroeconomic_indicators and macroeconomic methods (#540) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Two new methods on `FundamentalContext` across all language SDKs (Rust, Python, Node.js, Java): - `macroeconomic_indicators(country, offset, limit)` — `GET /v1/quote/macrodata` — list macroeconomic indicators; filter by country; response includes `count` (total matching) - `macroeconomic(indicator_code, start_date, end_date, offset, limit)` — `GET /v1/quote/macrodata/{indicator_code}` — historical data for a specific indicator; `start_date` / `end_date` accept `"YYYY-MM-DD"` strings; response includes `count` (total data points) ## New Types | Type | Description | |------|-------------| | `MultiLanguageText` | Localized text (English / Simplified Chinese / Traditional Chinese) | | `MacroeconomicCountry` | Country filter enum: `HongKong` / `China` / `UnitedStates` / `EuroZone` / `Japan` / `Singapore` (SDK accepts short codes, converts to full names for API) | | `MacroeconomicImportance` | Importance level: `Low=1` / `Medium=2` / `High=3` | | `MacroeconomicIndicator` | Indicator metadata (code, country, category, periodicity, importance, etc.) | | `MacroeconomicIndicatorListResponse` | `data: Vec` + `count: i32` | | `Macroeconomic` | One historical data point (period, actual/previous/forecast/revised values, release timestamps, unit) | | `MacroeconomicResponse` | `info: MacroeconomicIndicator` + `data: Vec` + `count: i32` | ## Fixes - `MacroeconomicIndicator.describe` / `name` / `MacroeconomicResponse.info`: handle `null` API responses without deserializing error ## Related - Go SDK: longbridge/openapi-go#99 --------- Co-authored-by: Claude Sonnet 4.6 (1M context) --- CHANGELOG.md | 12 ++ Cargo.toml | 2 +- .../main/java/com/longbridge/SdkNative.java | 8 + .../fundamental/FundamentalContext.java | 20 +++ .../longbridge/fundamental/Macroeconomic.java | 15 ++ .../fundamental/MacroeconomicIndicator.java | 19 +++ .../MacroeconomicIndicatorListResponse.java | 8 + .../fundamental/MacroeconomicResponse.java | 9 + .../fundamental/MultiLanguageText.java | 8 + java/src/fundamental_context.rs | 66 ++++++++ java/src/types/classes.rs | 60 +++++++ nodejs/index.d.ts | 70 ++++++++ nodejs/index.js | 1 + nodejs/src/fundamental/context.rs | 34 ++++ nodejs/src/fundamental/types.rs | 155 +++++++++++++++++ python/pysrc/longbridge/openapi.pyi | 86 ++++++++++ python/src/fundamental/context.rs | 30 ++++ python/src/fundamental/context_async.rs | 40 +++++ python/src/fundamental/mod.rs | 6 + python/src/fundamental/types.rs | 146 ++++++++++++++++ rust/src/blocking/fundamental.rs | 27 +++ rust/src/fundamental/context.rs | 89 ++++++++++ rust/src/fundamental/types.rs | 157 ++++++++++++++++++ rust/src/serde_utils.rs | 9 + 24 files changed, 1076 insertions(+), 1 deletion(-) create mode 100644 java/javasrc/src/main/java/com/longbridge/fundamental/Macroeconomic.java create mode 100644 java/javasrc/src/main/java/com/longbridge/fundamental/MacroeconomicIndicator.java create mode 100644 java/javasrc/src/main/java/com/longbridge/fundamental/MacroeconomicIndicatorListResponse.java create mode 100644 java/javasrc/src/main/java/com/longbridge/fundamental/MacroeconomicResponse.java create mode 100644 java/javasrc/src/main/java/com/longbridge/fundamental/MultiLanguageText.java diff --git a/CHANGELOG.md b/CHANGELOG.md index 707c9ed47..a1329525e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,18 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [4.3.1] - 2026-06-12 + +### Added + +- **All languages:** `FundamentalContext` gains `macroeconomic_indicators(country, offset, limit)` — list macroeconomic indicators via `GET /v1/quote/macrodata`; filter by country (`MacroeconomicCountry::HongKong / China / UnitedStates / EuroZone / Japan / Singapore`); response includes `count` (total matching) +- **All languages:** `FundamentalContext` gains `macroeconomic(indicator_code, start_date, end_date, offset, limit)` — historical data for a specific indicator via `GET /v1/quote/macrodata/{indicator_code}`; `start_date` / `end_date` accept `"YYYY-MM-DD"` strings; response includes `count` (total data points) +- New types: `MultiLanguageText`, `MacroeconomicCountry`, `MacroeconomicImportance`, `MacroeconomicIndicator`, `MacroeconomicIndicatorListResponse`, `Macroeconomic`, `MacroeconomicResponse` + +### Fixed + +- `MacroeconomicIndicator.describe` / `name` / `MacroeconomicResponse.info`: handle `null` responses from API without deserializing error + ## [4.3.0] ### Added diff --git a/Cargo.toml b/Cargo.toml index 815991451..b21cdf2dc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ resolver = "3" members = ["rust", "python", "nodejs", "java", "c"] [workspace.package] -version = "4.3.0" +version = "4.3.1" edition = "2024" [profile.release] diff --git a/java/javasrc/src/main/java/com/longbridge/SdkNative.java b/java/javasrc/src/main/java/com/longbridge/SdkNative.java index 4ed90791a..dadca70c6 100644 --- a/java/javasrc/src/main/java/com/longbridge/SdkNative.java +++ b/java/javasrc/src/main/java/com/longbridge/SdkNative.java @@ -451,6 +451,14 @@ public static native void fundamentalContextGetFinancialReportSnapshot(long cont Object opts, AsyncCallback callback); + public static native void fundamentalContextMacroeconomicIndicators(long context, + Object country, Object offset, Object limit, + AsyncCallback callback); + + public static native void fundamentalContextMacroeconomic(long context, + Object indicatorCode, Object startTime, Object endTime, Object offset, Object limit, + AsyncCallback callback); + public static native void portfolioContextProfitAnalysisFlows(long context, Object opts, AsyncCallback callback); diff --git a/java/javasrc/src/main/java/com/longbridge/fundamental/FundamentalContext.java b/java/javasrc/src/main/java/com/longbridge/fundamental/FundamentalContext.java index 8c0a7299a..4c22e256a 100644 --- a/java/javasrc/src/main/java/com/longbridge/fundamental/FundamentalContext.java +++ b/java/javasrc/src/main/java/com/longbridge/fundamental/FundamentalContext.java @@ -334,4 +334,24 @@ public CompletableFuture getValuationComparison(Val SdkNative.fundamentalContextValuationComparison(raw, opts, callback); }); } + + /** + * List macroeconomic indicators. + * country: ISO country code string (e.g. "US", "CN", "EU"); pass null for all countries. + */ + public CompletableFuture getMacroeconomicIndicators(String country, Integer offset, Integer limit) throws OpenApiException { + return AsyncCallback.executeTask((callback) -> { + SdkNative.fundamentalContextMacroeconomicIndicators(raw, country, offset, limit, callback); + }); + } + + /** + * Get historical data for a macroeconomic indicator. + * startDate and endDate are date strings in "YYYY-MM-DD" format. + */ + public CompletableFuture getMacroeconomic(String indicatorCode, String startDate, String endDate, Integer offset, Integer limit) throws OpenApiException { + return AsyncCallback.executeTask((callback) -> { + SdkNative.fundamentalContextMacroeconomic(raw, indicatorCode, startDate, endDate, offset, limit, callback); + }); + } } diff --git a/java/javasrc/src/main/java/com/longbridge/fundamental/Macroeconomic.java b/java/javasrc/src/main/java/com/longbridge/fundamental/Macroeconomic.java new file mode 100644 index 000000000..caca0ccda --- /dev/null +++ b/java/javasrc/src/main/java/com/longbridge/fundamental/Macroeconomic.java @@ -0,0 +1,15 @@ +package com.longbridge.fundamental; + +/** One historical data point for a macroeconomic indicator. */ +public class Macroeconomic { + /** Statistical period (e.g. 2024-Q1, 2024-03). */ + public String period; + public String releaseAt; + public String actualValue; + public String previousValue; + public String forecastValue; + public String revisedValue; + public String nextReleaseAt; + public MultiLanguageText unit; + public MultiLanguageText unitPrefix; +} diff --git a/java/javasrc/src/main/java/com/longbridge/fundamental/MacroeconomicIndicator.java b/java/javasrc/src/main/java/com/longbridge/fundamental/MacroeconomicIndicator.java new file mode 100644 index 000000000..c83d4fd5a --- /dev/null +++ b/java/javasrc/src/main/java/com/longbridge/fundamental/MacroeconomicIndicator.java @@ -0,0 +1,19 @@ +package com.longbridge.fundamental; + +/** Metadata for one macroeconomic indicator. */ +public class MacroeconomicIndicator { + /** External vendor code (input to getEconomicIndicator). */ + public String indicatorCode; + public String sourceOrg; + public String country; + public MultiLanguageText name; + public String adjustmentFactor; + /** Release periodicity (e.g. monthly / quarterly). */ + public String periodicity; + public String category; + public MultiLanguageText describe; + /** Importance — higher is more important. */ + public int importance; + /** Start date of data coverage (unix timestamp string). */ + public String startDate; +} diff --git a/java/javasrc/src/main/java/com/longbridge/fundamental/MacroeconomicIndicatorListResponse.java b/java/javasrc/src/main/java/com/longbridge/fundamental/MacroeconomicIndicatorListResponse.java new file mode 100644 index 000000000..b62e637c6 --- /dev/null +++ b/java/javasrc/src/main/java/com/longbridge/fundamental/MacroeconomicIndicatorListResponse.java @@ -0,0 +1,8 @@ +package com.longbridge.fundamental; + +/** Response for {@link FundamentalContext#getMacroeconomicIndicators}. */ +public class MacroeconomicIndicatorListResponse { + public MacroeconomicIndicator[] data; + /** Total number of indicators matching the query. */ + public int count; +} diff --git a/java/javasrc/src/main/java/com/longbridge/fundamental/MacroeconomicResponse.java b/java/javasrc/src/main/java/com/longbridge/fundamental/MacroeconomicResponse.java new file mode 100644 index 000000000..e84c46569 --- /dev/null +++ b/java/javasrc/src/main/java/com/longbridge/fundamental/MacroeconomicResponse.java @@ -0,0 +1,9 @@ +package com.longbridge.fundamental; + +/** Response for {@link FundamentalContext#getMacroeconomic}. */ +public class MacroeconomicResponse { + public MacroeconomicIndicator info; + public Macroeconomic[] data; + /** Total number of historical data points. */ + public int count; +} diff --git a/java/javasrc/src/main/java/com/longbridge/fundamental/MultiLanguageText.java b/java/javasrc/src/main/java/com/longbridge/fundamental/MultiLanguageText.java new file mode 100644 index 000000000..2bb9bf361 --- /dev/null +++ b/java/javasrc/src/main/java/com/longbridge/fundamental/MultiLanguageText.java @@ -0,0 +1,8 @@ +package com.longbridge.fundamental; + +/** Localized text in simplified Chinese, traditional Chinese, and English. */ +public class MultiLanguageText { + public String english; + public String simplifiedChinese; + public String traditionalChinese; +} diff --git a/java/src/fundamental_context.rs b/java/src/fundamental_context.rs index 95c39a995..163b2fd45 100644 --- a/java/src/fundamental_context.rs +++ b/java/src/fundamental_context.rs @@ -262,3 +262,69 @@ pub unsafe extern "system" fn Java_com_longbridge_SdkNative_fundamentalContextVa Ok(()) }) } + +#[unsafe(no_mangle)] +pub unsafe extern "system" fn Java_com_longbridge_SdkNative_fundamentalContextMacroeconomicIndicators( + mut env: JNIEnv, + _class: JClass, + context: i64, + country: JObject, + offset: JObject, + limit: JObject, + callback: JObject, +) { + jni_result(&mut env, (), |env| { + let context = &*(context as *const ContextObj); + let country: Option = FromJValue::from_jvalue(env, country.into())?; + let country = country.and_then(|s| { + use longbridge::fundamental::MacroeconomicCountry::*; + match s.as_str() { + "HK" | "Hong Kong SAR China" => Some(HongKong), + "CN" | "China (Mainland)" => Some(China), + "US" | "United States" => Some(UnitedStates), + "EU" | "Euro Zone" => Some(EuroZone), + "JP" | "Japan" => Some(Japan), + "SG" | "Singapore" => Some(Singapore), + _ => None, + } + }); + let offset: Option = FromJValue::from_jvalue(env, offset.into())?; + let limit: Option = FromJValue::from_jvalue(env, limit.into())?; + async_util::execute(env, callback, async move { + Ok(context + .ctx + .macroeconomic_indicators(country, offset, limit) + .await?) + })?; + Ok(()) + }) +} + +#[unsafe(no_mangle)] +pub unsafe extern "system" fn Java_com_longbridge_SdkNative_fundamentalContextMacroeconomic( + mut env: JNIEnv, + _class: JClass, + context: i64, + indicator_code: JObject, + start_time: JObject, + end_time: JObject, + offset: JObject, + limit: JObject, + callback: JObject, +) { + jni_result(&mut env, (), |env| { + let context = &*(context as *const ContextObj); + let indicator_code: String = FromJValue::from_jvalue(env, indicator_code.into())?; + let start_date: Option = FromJValue::from_jvalue(env, start_time.into())?; + let end_date: Option = FromJValue::from_jvalue(env, end_time.into())?; + let offset: Option = FromJValue::from_jvalue(env, offset.into())?; + let limit: Option = FromJValue::from_jvalue(env, limit.into())?; + async_util::execute(env, callback, async move { + Ok(context + .ctx + .macroeconomic(indicator_code, start_date, end_date, offset, limit) + .await?) + })?; + Ok(()) + }) +} diff --git a/java/src/types/classes.rs b/java/src/types/classes.rs index 141d5f839..285f3611c 100644 --- a/java/src/types/classes.rs +++ b/java/src/types/classes.rs @@ -2698,6 +2698,66 @@ impl_java_class!( ] ); +impl_java_class!( + "com/longbridge/fundamental/MultiLanguageText", + longbridge::fundamental::MultiLanguageText, + [english, simplified_chinese, traditional_chinese] +); + +impl_java_class!( + "com/longbridge/fundamental/MacroeconomicIndicator", + longbridge::fundamental::MacroeconomicIndicator, + [ + indicator_code, + source_org, + country, + name, + adjustment_factor, + periodicity, + category, + describe, + importance, + start_date + ] +); + +impl_java_class!( + "com/longbridge/fundamental/Macroeconomic", + longbridge::fundamental::Macroeconomic, + [ + period, + release_at, + actual_value, + previous_value, + forecast_value, + revised_value, + next_release_at, + unit, + unit_prefix + ] +); + +impl_java_class!( + "com/longbridge/fundamental/MacroeconomicIndicatorListResponse", + longbridge::fundamental::MacroeconomicIndicatorListResponse, + [ + #[java(objarray)] + data, + count + ] +); + +impl_java_class!( + "com/longbridge/fundamental/MacroeconomicResponse", + longbridge::fundamental::MacroeconomicResponse, + [ + info, + #[java(objarray)] + data, + count + ] +); + // ── MarketContext: top movers / rank ────────────────────────────── impl_java_class!( diff --git a/nodejs/index.d.ts b/nodejs/index.d.ts index c7f7b1eb4..56b157e18 100644 --- a/nodejs/index.d.ts +++ b/nodejs/index.d.ts @@ -618,6 +618,10 @@ export declare class FundamentalContext { * industry) */ etfAssetAllocation(symbol: string): Promise + /** List macroeconomic indicators */ + macroeconomicIndicators(country?: MacroeconomicCountry | undefined | null, offset?: number | undefined | null, limit?: number | undefined | null): Promise + /** Get historical data for a macroeconomic indicator */ + macroeconomic(indicatorCode: string, startDate?: string | undefined | null, endDate?: string | undefined | null, offset?: number | undefined | null, limit?: number | undefined | null): Promise } /** Fund position */ @@ -4473,6 +4477,65 @@ export declare const enum Language { EN = 2 } +/** One historical data point for a macroeconomic indicator */ +export interface Macroeconomic { + period: string + /** Release datetime (unix timestamp in seconds; null if unset) */ + releaseAt?: number + actualValue: string + previousValue: string + forecastValue: string + revisedValue: string + /** Next release datetime (unix timestamp in seconds; null if unset) */ + nextReleaseAt?: number + unit: MultiLanguageText + unitPrefix: MultiLanguageText +} + +/** Country code for filtering macroeconomic indicators */ +export declare const enum MacroeconomicCountry { + /** Hong Kong SAR China */ + HongKong = 0, + /** China (Mainland) */ + China = 1, + /** United States */ + UnitedStates = 2, + /** Euro Zone */ + EuroZone = 3, + /** Japan */ + Japan = 4, + /** Singapore */ + Singapore = 5 +} + +/** Metadata for one macroeconomic indicator */ +export interface MacroeconomicIndicator { + indicatorCode: string + sourceOrg: string + country: string + name: MultiLanguageText + adjustmentFactor: string + periodicity: string + category: string + describe: MultiLanguageText + importance: number + /** Start date of data coverage (unix timestamp in seconds; null if unset) */ + startDate?: number +} + +/** Response for macroeconomic_indicators */ +export interface MacroeconomicIndicatorListResponse { + data: Array + count: number +} + +/** Response for macroeconomic */ +export interface MacroeconomicResponse { + info: MacroeconomicIndicator + data: Array + count: number +} + export declare const enum Market { /** Unknown */ Unknown = 0, @@ -4515,6 +4578,13 @@ export interface MarketTimeItem { delaySubStatus: number } +/** Localized text in simplified Chinese, traditional Chinese, and English */ +export interface MultiLanguageText { + english: string + simplifiedChinese: string + traditionalChinese: string +} + /** Options for listing topics created by the current authenticated user */ export interface MyTopicsRequest { /** Page number (default 1) */ diff --git a/nodejs/index.js b/nodejs/index.js index a8cb5ec7a..fa943da93 100644 --- a/nodejs/index.js +++ b/nodejs/index.js @@ -689,6 +689,7 @@ module.exports.FlowDirection = nativeBinding.FlowDirection module.exports.Granularity = nativeBinding.Granularity module.exports.InstitutionRecommend = nativeBinding.InstitutionRecommend module.exports.Language = nativeBinding.Language +module.exports.MacrodataCountry = nativeBinding.MacrodataCountry module.exports.Market = nativeBinding.Market module.exports.OptionDirection = nativeBinding.OptionDirection module.exports.OptionType = nativeBinding.OptionType diff --git a/nodejs/src/fundamental/context.rs b/nodejs/src/fundamental/context.rs index ca1cc3528..3fdc33587 100644 --- a/nodejs/src/fundamental/context.rs +++ b/nodejs/src/fundamental/context.rs @@ -287,4 +287,38 @@ impl FundamentalContext { .map_err(ErrorNewType)? .into()) } + + /// List macroeconomic indicators + #[napi] + pub async fn macroeconomic_indicators( + &self, + country: Option, + offset: Option, + limit: Option, + ) -> Result { + Ok(self + .ctx + .macroeconomic_indicators(country.map(Into::into), offset, limit) + .await + .map_err(ErrorNewType)? + .into()) + } + + /// Get historical data for a macroeconomic indicator + #[napi] + pub async fn macroeconomic( + &self, + indicator_code: String, + start_date: Option, + end_date: Option, + offset: Option, + limit: Option, + ) -> Result { + Ok(self + .ctx + .macroeconomic(indicator_code, start_date, end_date, offset, limit) + .await + .map_err(ErrorNewType)? + .into()) + } } diff --git a/nodejs/src/fundamental/types.rs b/nodejs/src/fundamental/types.rs index 37664aba5..e66916ff5 100644 --- a/nodejs/src/fundamental/types.rs +++ b/nodejs/src/fundamental/types.rs @@ -1902,3 +1902,158 @@ impl From for AssetAllocationResponse { } } } + +// ── economic_indicator ───────────────────────────────────────────────────── + +/// Localized text in simplified Chinese, traditional Chinese, and English +#[napi_derive::napi(object)] +#[derive(Debug, Clone, Default)] +pub struct MultiLanguageText { + pub english: String, + pub simplified_chinese: String, + pub traditional_chinese: String, +} + +impl From for MultiLanguageText { + fn from(v: lb::MultiLanguageText) -> Self { + Self { + english: v.english, + simplified_chinese: v.simplified_chinese, + traditional_chinese: v.traditional_chinese, + } + } +} + +/// Country code for filtering macroeconomic indicators +#[napi_derive::napi] +#[derive(Debug, Copy, Clone)] +pub enum MacroeconomicCountry { + /// Hong Kong SAR China + HongKong, + /// China (Mainland) + China, + /// United States + UnitedStates, + /// Euro Zone + EuroZone, + /// Japan + Japan, + /// Singapore + Singapore, +} + +impl From for lb::MacroeconomicCountry { + fn from(v: MacroeconomicCountry) -> Self { + match v { + MacroeconomicCountry::HongKong => lb::MacroeconomicCountry::HongKong, + MacroeconomicCountry::China => lb::MacroeconomicCountry::China, + MacroeconomicCountry::UnitedStates => lb::MacroeconomicCountry::UnitedStates, + MacroeconomicCountry::EuroZone => lb::MacroeconomicCountry::EuroZone, + MacroeconomicCountry::Japan => lb::MacroeconomicCountry::Japan, + MacroeconomicCountry::Singapore => lb::MacroeconomicCountry::Singapore, + } + } +} + +/// Response for macroeconomic_indicators +#[napi_derive::napi(object)] +#[derive(Debug, Clone)] +pub struct MacroeconomicIndicatorListResponse { + pub data: Vec, + pub count: i32, +} + +impl From for MacroeconomicIndicatorListResponse { + fn from(v: lb::MacroeconomicIndicatorListResponse) -> Self { + Self { + data: v.data.into_iter().map(Into::into).collect(), + count: v.count, + } + } +} + +/// Metadata for one macroeconomic indicator +#[napi_derive::napi(object)] +#[derive(Debug, Clone)] +pub struct MacroeconomicIndicator { + pub indicator_code: String, + pub source_org: String, + pub country: String, + pub name: MultiLanguageText, + pub adjustment_factor: String, + pub periodicity: String, + pub category: String, + pub describe: MultiLanguageText, + pub importance: i32, + /// Start date of data coverage (unix timestamp in seconds; null if unset) + pub start_date: Option, +} + +impl From for MacroeconomicIndicator { + fn from(v: lb::MacroeconomicIndicator) -> Self { + Self { + indicator_code: v.indicator_code, + source_org: v.source_org, + country: v.country, + name: v.name.into(), + adjustment_factor: v.adjustment_factor, + periodicity: v.periodicity, + category: v.category, + describe: v.describe.into(), + importance: v.importance, + start_date: v.start_date.map(|dt| dt.unix_timestamp()), + } + } +} + +/// One historical data point for a macroeconomic indicator +#[napi_derive::napi(object)] +#[derive(Debug, Clone)] +pub struct Macroeconomic { + pub period: String, + /// Release datetime (unix timestamp in seconds; null if unset) + pub release_at: Option, + pub actual_value: String, + pub previous_value: String, + pub forecast_value: String, + pub revised_value: String, + /// Next release datetime (unix timestamp in seconds; null if unset) + pub next_release_at: Option, + pub unit: MultiLanguageText, + pub unit_prefix: MultiLanguageText, +} + +impl From for Macroeconomic { + fn from(v: lb::Macroeconomic) -> Self { + Self { + period: v.period, + release_at: v.release_at.map(|dt| dt.unix_timestamp()), + actual_value: v.actual_value, + previous_value: v.previous_value, + forecast_value: v.forecast_value, + revised_value: v.revised_value, + next_release_at: v.next_release_at.map(|dt| dt.unix_timestamp()), + unit: v.unit.into(), + unit_prefix: v.unit_prefix.into(), + } + } +} + +/// Response for macroeconomic +#[napi_derive::napi(object)] +#[derive(Debug, Clone)] +pub struct MacroeconomicResponse { + pub info: MacroeconomicIndicator, + pub data: Vec, + pub count: i32, +} + +impl From for MacroeconomicResponse { + fn from(v: lb::MacroeconomicResponse) -> Self { + Self { + info: v.info.into(), + data: v.data.into_iter().map(Into::into).collect(), + count: v.count, + } + } +} diff --git a/python/pysrc/longbridge/openapi.pyi b/python/pysrc/longbridge/openapi.pyi index 90bc788e3..8186b1c8f 100644 --- a/python/pysrc/longbridge/openapi.pyi +++ b/python/pysrc/longbridge/openapi.pyi @@ -9922,6 +9922,44 @@ class FundamentalContext: """ ... + def macroeconomic_indicators( + self, + offset: int | None = None, + limit: int | None = None, + ) -> list["MacroeconomicIndicator"]: + """ + List macroeconomic indicators. + + Args: + offset: Pagination offset (default 0) + limit: Page size (default 100, max 1000) + + Returns: + List of :class:`MacroeconomicIndicator` + """ + ... + + def macroeconomic( + self, + indicator_code: str, + start_date: str | None = None, + end_date: str | None = None, + limit: int | None = None, + ) -> "MacroeconomicResponse": + """ + Get historical data for a macroeconomic indicator. + + Args: + indicator_code: External vendor code from ``macroeconomic_indicators`` + start_date: Start date in ``"YYYY-MM-DD"`` format (optional) + end_date: End date in ``"YYYY-MM-DD"`` format (optional) + limit: Max records to return (default 100, max 100) + + Returns: + :class:`MacroeconomicResponse` + """ + ... + # ── FundamentalContext new response types ───────────────────────── @@ -10065,6 +10103,54 @@ class AssetAllocationResponse: """Asset allocation groups""" +class MultiLanguageText: + """Localized text in simplified Chinese, traditional Chinese, and English.""" + + english: str + simplified_chinese: str + traditional_chinese: str + + +class MacroeconomicIndicator: + """Metadata for one macroeconomic indicator.""" + + indicator_code: str + """External vendor code (input to macroeconomic)""" + source_org: str + country: str + name: MultiLanguageText + adjustment_factor: str + periodicity: str + """Release periodicity (e.g. monthly / quarterly)""" + category: str + describe: MultiLanguageText + importance: int + start_date: datetime | None + """Start date of data coverage""" + + +class Macroeconomic: + """One historical data point for a macroeconomic indicator.""" + + period: str + """Statistical period (e.g. 2024-Q1, 2024-03)""" + release_at: datetime | None + actual_value: str + previous_value: str + forecast_value: str + revised_value: str + next_release_at: datetime | None + unit: MultiLanguageText + unit_prefix: MultiLanguageText + + +class MacroeconomicResponse: + """Response for macroeconomic.""" + + info: MacroeconomicIndicator + data: list[Macroeconomic] + + # ── MarketContext ───────────────────────────────────────────────── class MarketTimeItem: diff --git a/python/src/fundamental/context.rs b/python/src/fundamental/context.rs index e65d93fd2..5d4dd8639 100644 --- a/python/src/fundamental/context.rs +++ b/python/src/fundamental/context.rs @@ -208,4 +208,34 @@ impl FundamentalContext { .map_err(ErrorNewType)? .into()) } + + /// List macroeconomic indicators. + fn macroeconomic_indicators( + &self, + country: Option, + offset: Option, + limit: Option, + ) -> PyResult { + Ok(self + .ctx + .macroeconomic_indicators(country.map(Into::into), offset, limit) + .map_err(ErrorNewType)? + .into()) + } + + /// Get historical data for a macroeconomic indicator. + fn macroeconomic( + &self, + indicator_code: String, + start_date: Option, + end_date: Option, + offset: Option, + limit: Option, + ) -> PyResult { + Ok(self + .ctx + .macroeconomic(indicator_code, start_date, end_date, offset, limit) + .map_err(ErrorNewType)? + .into()) + } } diff --git a/python/src/fundamental/context_async.rs b/python/src/fundamental/context_async.rs index eed4d6142..1fe4f9d5c 100644 --- a/python/src/fundamental/context_async.rs +++ b/python/src/fundamental/context_async.rs @@ -317,4 +317,44 @@ impl AsyncFundamentalContext { }) .map(|b| b.unbind()) } + + /// List macroeconomic indicators. Returns awaitable. + fn macroeconomic_indicators( + &self, + py: Python<'_>, + country: Option, + offset: Option, + limit: Option, + ) -> PyResult> { + let ctx = self.ctx.clone(); + pyo3_async_runtimes::tokio::future_into_py(py, async move { + Ok(MacroeconomicIndicatorListResponse::from( + ctx.macroeconomic_indicators(country.map(Into::into), offset, limit) + .await + .map_err(ErrorNewType)?, + )) + }) + .map(|b| b.unbind()) + } + + /// Get historical data for a macroeconomic indicator. Returns awaitable. + fn macroeconomic( + &self, + py: Python<'_>, + indicator_code: String, + start_date: Option, + end_date: Option, + offset: Option, + limit: Option, + ) -> PyResult> { + let ctx = self.ctx.clone(); + pyo3_async_runtimes::tokio::future_into_py(py, async move { + Ok(MacroeconomicResponse::from( + ctx.macroeconomic(indicator_code, start_date, end_date, offset, limit) + .await + .map_err(ErrorNewType)?, + )) + }) + .map(|b| b.unbind()) + } } diff --git a/python/src/fundamental/mod.rs b/python/src/fundamental/mod.rs index a788e712e..810101751 100644 --- a/python/src/fundamental/mod.rs +++ b/python/src/fundamental/mod.rs @@ -74,6 +74,12 @@ pub(crate) fn register_types(parent: &Bound) -> PyResult<()> { parent.add_class::()?; parent.add_class::()?; parent.add_class::()?; + parent.add_class::()?; + parent.add_class::()?; + parent.add_class::()?; + parent.add_class::()?; + parent.add_class::()?; + parent.add_class::()?; parent.add_class::()?; parent.add_class::()?; Ok(()) diff --git a/python/src/fundamental/types.rs b/python/src/fundamental/types.rs index 3a8f6ed59..c541cb7c9 100644 --- a/python/src/fundamental/types.rs +++ b/python/src/fundamental/types.rs @@ -1965,3 +1965,149 @@ impl From for AssetAllocationResponse { } } } + +// ── economic_indicator ───────────────────────────────────────────────────── + +/// Localized text in simplified Chinese, traditional Chinese, and English +#[pyclass(get_all, skip_from_py_object)] +#[derive(Debug, Clone, Default)] +pub(crate) struct MultiLanguageText { + pub english: String, + pub simplified_chinese: String, + pub traditional_chinese: String, +} + +impl From for MultiLanguageText { + fn from(v: lb::MultiLanguageText) -> Self { + Self { + english: v.english, + simplified_chinese: v.simplified_chinese, + traditional_chinese: v.traditional_chinese, + } + } +} + +/// Country code for filtering macroeconomic indicators +#[pyclass] +#[derive(Debug, Copy, Clone)] +pub(crate) enum MacroeconomicCountry { + HongKong, + China, + UnitedStates, + EuroZone, + Japan, + Singapore, +} + +impl From for lb::MacroeconomicCountry { + fn from(v: MacroeconomicCountry) -> Self { + match v { + MacroeconomicCountry::HongKong => lb::MacroeconomicCountry::HongKong, + MacroeconomicCountry::China => lb::MacroeconomicCountry::China, + MacroeconomicCountry::UnitedStates => lb::MacroeconomicCountry::UnitedStates, + MacroeconomicCountry::EuroZone => lb::MacroeconomicCountry::EuroZone, + MacroeconomicCountry::Japan => lb::MacroeconomicCountry::Japan, + MacroeconomicCountry::Singapore => lb::MacroeconomicCountry::Singapore, + } + } +} + +/// Response for macroeconomic_indicators +#[pyclass(get_all, skip_from_py_object)] +#[derive(Debug, Clone)] +pub(crate) struct MacroeconomicIndicatorListResponse { + pub data: Vec, + pub count: i32, +} + +impl From for MacroeconomicIndicatorListResponse { + fn from(v: lb::MacroeconomicIndicatorListResponse) -> Self { + Self { + data: v.data.into_iter().map(Into::into).collect(), + count: v.count, + } + } +} + +/// Metadata for one macroeconomic indicator +#[pyclass(get_all, skip_from_py_object)] +#[derive(Debug, Clone)] +pub(crate) struct MacroeconomicIndicator { + pub indicator_code: String, + pub source_org: String, + pub country: String, + pub name: MultiLanguageText, + pub adjustment_factor: String, + pub periodicity: String, + pub category: String, + pub describe: MultiLanguageText, + pub importance: i32, + pub start_date: Option, +} + +impl From for MacroeconomicIndicator { + fn from(v: lb::MacroeconomicIndicator) -> Self { + Self { + indicator_code: v.indicator_code, + source_org: v.source_org, + country: v.country, + name: v.name.into(), + adjustment_factor: v.adjustment_factor, + periodicity: v.periodicity, + category: v.category, + describe: v.describe.into(), + importance: v.importance, + start_date: v.start_date.map(crate::time::PyOffsetDateTimeWrapper), + } + } +} + +/// One historical data point for a macroeconomic indicator +#[pyclass(get_all, skip_from_py_object)] +#[derive(Debug, Clone)] +pub(crate) struct Macroeconomic { + pub period: String, + pub release_at: Option, + pub actual_value: String, + pub previous_value: String, + pub forecast_value: String, + pub revised_value: String, + pub next_release_at: Option, + pub unit: MultiLanguageText, + pub unit_prefix: MultiLanguageText, +} + +impl From for Macroeconomic { + fn from(v: lb::Macroeconomic) -> Self { + Self { + period: v.period, + release_at: v.release_at.map(crate::time::PyOffsetDateTimeWrapper), + actual_value: v.actual_value, + previous_value: v.previous_value, + forecast_value: v.forecast_value, + revised_value: v.revised_value, + next_release_at: v.next_release_at.map(crate::time::PyOffsetDateTimeWrapper), + unit: v.unit.into(), + unit_prefix: v.unit_prefix.into(), + } + } +} + +/// Response for macroeconomic +#[pyclass(get_all, skip_from_py_object)] +#[derive(Debug, Clone)] +pub(crate) struct MacroeconomicResponse { + pub info: MacroeconomicIndicator, + pub data: Vec, + pub count: i32, +} + +impl From for MacroeconomicResponse { + fn from(v: lb::MacroeconomicResponse) -> Self { + Self { + info: v.info.into(), + data: v.data.into_iter().map(Into::into).collect(), + count: v.count, + } + } +} diff --git a/rust/src/blocking/fundamental.rs b/rust/src/blocking/fundamental.rs index e2fb48d04..d580a0484 100644 --- a/rust/src/blocking/fundamental.rs +++ b/rust/src/blocking/fundamental.rs @@ -290,4 +290,31 @@ impl FundamentalContextSync { self.rt .call(move |ctx| async move { ctx.etf_asset_allocation(symbol).await }) } + + /// List macroeconomic indicators + pub fn macroeconomic_indicators( + &self, + country: Option, + offset: Option, + limit: Option, + ) -> Result { + self.rt.call(move |ctx| async move { + ctx.macroeconomic_indicators(country, offset, limit).await + }) + } + + /// Get historical data for a macroeconomic indicator + pub fn macroeconomic( + &self, + indicator_code: impl Into + Send + 'static, + start_date: Option + Send + 'static>, + end_date: Option + Send + 'static>, + offset: Option, + limit: Option, + ) -> Result { + self.rt.call(move |ctx| async move { + ctx.macroeconomic(indicator_code, start_date, end_date, offset, limit) + .await + }) + } } diff --git a/rust/src/fundamental/context.rs b/rust/src/fundamental/context.rs index a5d9e64b5..be0212c9c 100644 --- a/rust/src/fundamental/context.rs +++ b/rust/src/fundamental/context.rs @@ -829,4 +829,93 @@ impl FundamentalContext { ) .await } + + // ── macroeconomic ──────────────────────────────────────────────── + + /// List macroeconomic indicators. + /// + /// Pass `country` to filter by country code (e.g. + /// `MacroeconomicCountry::UnitedStates`). + /// + /// Path: `GET /v1/quote/macrodata` + pub async fn macroeconomic_indicators( + &self, + country: Option, + offset: Option, + limit: Option, + ) -> Result { + #[derive(Serialize)] + struct Query { + #[serde(skip_serializing_if = "Option::is_none")] + country: Option, + #[serde(skip_serializing_if = "Option::is_none")] + offset: Option, + #[serde(skip_serializing_if = "Option::is_none")] + limit: Option, + } + let country_str = country.map(|c| { + match c { + MacroeconomicCountry::HongKong => "Hong Kong SAR China", + MacroeconomicCountry::China => "China (Mainland)", + MacroeconomicCountry::UnitedStates => "United States", + MacroeconomicCountry::EuroZone => "Euro Zone", + MacroeconomicCountry::Japan => "Japan", + MacroeconomicCountry::Singapore => "Singapore", + } + .to_string() + }); + self.get( + "/v1/quote/macrodata", + Query { + country: country_str, + offset, + limit, + }, + ) + .await + } + + /// Get historical data for a macroeconomic indicator. + /// + /// `start_date` and `end_date` are date strings in `"YYYY-MM-DD"` format. + /// `start_date` is sent as `YYYY-MM-DDT00:00:00Z`; `end_date` is sent as + /// `YYYY-MM-DDT23:59:59Z`. + /// + /// Path: `GET /v1/quote/macrodata/{indicator_code}` + pub async fn macroeconomic( + &self, + indicator_code: impl Into, + start_date: Option>, + end_date: Option>, + offset: Option, + limit: Option, + ) -> Result { + #[derive(Serialize)] + struct Query { + #[serde(skip_serializing_if = "Option::is_none")] + start_time: Option, + #[serde(skip_serializing_if = "Option::is_none")] + end_time: Option, + #[serde(skip_serializing_if = "Option::is_none")] + offset: Option, + #[serde(skip_serializing_if = "Option::is_none")] + limit: Option, + } + let path = format!("/v1/quote/macrodata/{}", indicator_code.into()); + Ok(self + .0 + .http_cli + .request(Method::GET, path) + .query_params(Query { + start_time: start_date.map(|d| format!("{}T00:00:00Z", d.into())), + end_time: end_date.map(|d| format!("{}T23:59:59Z", d.into())), + offset, + limit, + }) + .response::>() + .send() + .with_subscriber(self.0.log_subscriber.clone()) + .await? + .0) + } } diff --git a/rust/src/fundamental/types.rs b/rust/src/fundamental/types.rs index 929f8ce98..9bee91e22 100644 --- a/rust/src/fundamental/types.rs +++ b/rust/src/fundamental/types.rs @@ -1562,3 +1562,160 @@ pub struct AssetAllocationResponse { #[serde(default)] pub info: Vec, } + +// ── macroeconomic ───────────────────────────────────────────────────── + +/// Country for filtering macroeconomic indicators +#[derive(Debug, Copy, Clone, Eq, PartialEq, Serialize, Deserialize)] +pub enum MacroeconomicCountry { + /// Hong Kong SAR China + #[serde(rename = "Hong Kong SAR China")] + HongKong, + /// China (Mainland) + #[serde(rename = "China (Mainland)")] + China, + /// United States + #[serde(rename = "United States")] + UnitedStates, + /// Euro Zone + #[serde(rename = "Euro Zone")] + EuroZone, + /// Japan + #[serde(rename = "Japan")] + Japan, + /// Singapore + #[serde(rename = "Singapore")] + Singapore, +} + +/// Importance level of a macroeconomic indicator +#[derive(Debug, Copy, Clone, Eq, PartialEq)] +pub enum MacroeconomicImportance { + /// Low importance + Low = 1, + /// Medium importance + Medium = 2, + /// High importance + High = 3, +} + +impl MacroeconomicImportance { + /// Convert from raw API integer value + pub fn from_i32(v: i32) -> Option { + match v { + 1 => Some(Self::Low), + 2 => Some(Self::Medium), + 3 => Some(Self::High), + _ => None, + } + } +} + +/// Localized text in simplified Chinese, traditional Chinese, and English +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +pub struct MultiLanguageText { + /// English + #[serde(default)] + pub english: String, + /// Simplified Chinese + #[serde(default)] + pub simplified_chinese: String, + /// Traditional Chinese + #[serde(default)] + pub traditional_chinese: String, +} + +/// Metadata for one macroeconomic indicator +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +pub struct MacroeconomicIndicator { + /// External vendor code (used as input to `macroeconomic`) + pub indicator_code: String, + /// Publishing organisation + #[serde(default)] + pub source_org: String, + /// Country + #[serde(default)] + pub country: String, + /// Indicator name (multilingual) + #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")] + pub name: MultiLanguageText, + /// Adjustment factor + #[serde(default)] + pub adjustment_factor: String, + /// Release periodicity (e.g. `monthly` / `quarterly`) + #[serde(default)] + pub periodicity: String, + /// Indicator category + #[serde(default)] + pub category: String, + /// Description (multilingual) + #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")] + pub describe: MultiLanguageText, + /// Importance — higher is more important + #[serde(default)] + pub importance: i32, + /// Start date of data coverage + #[serde( + default, + with = "crate::serde_utils::rfc3339_opt", + rename = "start_date" + )] + pub start_date: Option, +} + +/// Response for [`crate::FundamentalContext::macroeconomic_indicators`] +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct MacroeconomicIndicatorListResponse { + /// Indicator list + #[serde(default, rename = "list")] + pub data: Vec, + /// Total number of indicators matching the query + #[serde(default)] + pub count: i32, +} + +/// One historical data point for a macroeconomic indicator +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +pub struct Macroeconomic { + /// Statistical period (e.g. `2024-Q1`, `2024-03`) + #[serde(default)] + pub period: String, + /// Release datetime + #[serde(default, with = "crate::serde_utils::rfc3339_opt")] + pub release_at: Option, + /// Actual value + #[serde(default)] + pub actual_value: String, + /// Previous value + #[serde(default)] + pub previous_value: String, + /// Forecast value (market consensus) + #[serde(default)] + pub forecast_value: String, + /// Revised value + #[serde(default)] + pub revised_value: String, + /// Next release datetime + #[serde(default, with = "crate::serde_utils::rfc3339_opt")] + pub next_release_at: Option, + /// Unit (multilingual) + #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")] + pub unit: MultiLanguageText, + /// Unit prefix / data scale (multilingual, e.g. millions / billions) + #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")] + pub unit_prefix: MultiLanguageText, +} + +/// Response for [`crate::FundamentalContext::macroeconomic`] +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct MacroeconomicResponse { + /// Indicator metadata + #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")] + pub info: MacroeconomicIndicator, + /// Historical data points + #[serde(default)] + pub data: Vec, + /// Total number of historical data points + #[serde(default)] + pub count: i32, +} diff --git a/rust/src/serde_utils.rs b/rust/src/serde_utils.rs index 85858134b..21512bf95 100644 --- a/rust/src/serde_utils.rs +++ b/rust/src/serde_utils.rs @@ -462,3 +462,12 @@ where StringOrInt::String(s) => s.parse::().map_err(serde::de::Error::custom), } } + +/// Deserializer that maps a JSON `null` to the type's `Default` value. +pub(crate) fn null_as_default<'de, D, T>(d: D) -> Result +where + D: Deserializer<'de>, + T: Deserialize<'de> + Default, +{ + Ok(Option::::deserialize(d)?.unwrap_or_default()) +} From ff567d0932fc93710222277e65d0bd87276c432e Mon Sep 17 00:00:00 2001 From: Hogan Date: Sat, 13 Jun 2026 10:40:28 +0800 Subject: [PATCH 24/26] feat(fundamental): add macroeconomic_indicators_v2 and macroeconomic_v2 methods (v2 endpoints) (#543) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary Switches the macroeconomic indicator APIs to v2 endpoints while keeping existing method signatures and output types unchanged. All language SDKs updated. ## Changes ### Existing methods (unchanged signatures, route to v2 internally) - `macroeconomic_indicators(country, offset, limit)` → delegates to `macroeconomic_indicators_v2` - `macroeconomic(indicator_code, start_date, end_date, offset, limit)` → delegates to `macroeconomic_v2` ### New v2 methods - `macroeconomic_indicators_v2(country, keyword, offset, limit)` → `GET /v2/quote/macrodata` - `keyword`: optional fuzzy filter on indicator name - `country` None defaults to market=`ALL` - `offset`/`limit` passed through for pagination; response `count` uses API `total` - `macroeconomic_v2(indicator_code, start_date, end_date, offset, limit, sort)` → `GET /v2/quote/macrodata/{indicator_id}` - `sort`: `"asc"` or `"desc"` - Response maps single `indicator` object to existing `MacroeconomicResponse` ### v2 response → existing type mapping | v2 field | SDK field | |----------|-----------| | `indicator_id` (int32) | `indicator_code` (string) | | `indicator_name` | `name.english` | | `observation_date` | `Macroeconomic.period` | | `published_time` | `Macroeconomic.release_at` | | `actual_data` | `Macroeconomic.actual_value` | | `total` | `count` (for pagination) | ## Languages updated Rust, Python, Node.js, Java (all bindings add `_v2` variants with extra params) ## Related - Go SDK: longbridge/openapi-go#feat/macroeconomic-v2 --------- Co-authored-by: Claude Sonnet 4.6 (1M context) --- CHANGELOG.md | 12 ++ Cargo.toml | 2 +- .../main/java/com/longbridge/SdkNative.java | 2 +- .../fundamental/FundamentalContext.java | 10 +- .../longbridge/fundamental/Macroeconomic.java | 4 +- .../fundamental/MacroeconomicIndicator.java | 4 +- java/src/fundamental_context.rs | 4 +- nodejs/index.d.ts | 12 +- nodejs/index.js | 2 +- nodejs/src/fundamental/context.rs | 3 +- nodejs/src/fundamental/types.rs | 16 +- python/pysrc/longbridge/openapi.pyi | 8 +- python/src/fundamental/context.rs | 3 +- python/src/fundamental/context_async.rs | 3 +- python/src/fundamental/types.rs | 16 +- rust/src/blocking/fundamental.rs | 34 +++- rust/src/fundamental/context.rs | 183 ++++++++++++++---- rust/src/fundamental/types.rs | 98 ++++++++-- 18 files changed, 330 insertions(+), 86 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a1329525e..9d74445a8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,18 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [4.3.2] - 2026-06-13 + +### Added + +- **All languages:** `macroeconomic_indicators` gains `keyword` parameter for fuzzy name filtering +- **All languages:** `macroeconomic` switches to `GET /v2/quote/macrodata/{id}`, defaults to `sort=desc` + +### Changed + +- `MacroeconomicIndicator.name` / `.describe`: `MultiLanguageText` → `string` +- `Macroeconomic.unit` / `.unit_prefix`: `MultiLanguageText` → `string` + ## [4.3.1] - 2026-06-12 ### Added diff --git a/Cargo.toml b/Cargo.toml index b21cdf2dc..8606b5cb6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ resolver = "3" members = ["rust", "python", "nodejs", "java", "c"] [workspace.package] -version = "4.3.1" +version = "4.3.2" edition = "2024" [profile.release] diff --git a/java/javasrc/src/main/java/com/longbridge/SdkNative.java b/java/javasrc/src/main/java/com/longbridge/SdkNative.java index dadca70c6..7beea04c5 100644 --- a/java/javasrc/src/main/java/com/longbridge/SdkNative.java +++ b/java/javasrc/src/main/java/com/longbridge/SdkNative.java @@ -452,7 +452,7 @@ public static native void fundamentalContextGetFinancialReportSnapshot(long cont AsyncCallback callback); public static native void fundamentalContextMacroeconomicIndicators(long context, - Object country, Object offset, Object limit, + Object country, Object keyword, Object offset, Object limit, AsyncCallback callback); public static native void fundamentalContextMacroeconomic(long context, diff --git a/java/javasrc/src/main/java/com/longbridge/fundamental/FundamentalContext.java b/java/javasrc/src/main/java/com/longbridge/fundamental/FundamentalContext.java index 4c22e256a..a3a224656 100644 --- a/java/javasrc/src/main/java/com/longbridge/fundamental/FundamentalContext.java +++ b/java/javasrc/src/main/java/com/longbridge/fundamental/FundamentalContext.java @@ -339,9 +339,9 @@ public CompletableFuture getValuationComparison(Val * List macroeconomic indicators. * country: ISO country code string (e.g. "US", "CN", "EU"); pass null for all countries. */ - public CompletableFuture getMacroeconomicIndicators(String country, Integer offset, Integer limit) throws OpenApiException { + public CompletableFuture getMacroeconomicIndicators(String country, String keyword, Integer offset, Integer limit) throws OpenApiException { return AsyncCallback.executeTask((callback) -> { - SdkNative.fundamentalContextMacroeconomicIndicators(raw, country, offset, limit, callback); + SdkNative.fundamentalContextMacroeconomicIndicators(raw, country, keyword, offset, limit, callback); }); } @@ -354,4 +354,10 @@ public CompletableFuture getMacroeconomic(String indicato SdkNative.fundamentalContextMacroeconomic(raw, indicatorCode, startDate, endDate, offset, limit, callback); }); } + + /** + * List macroeconomic indicators (v2) with optional keyword filter. + * country: "HK","CN","US","EU","JP","SG" or null for ALL. + * keyword: optional fuzzy filter on indicator name. + */ } diff --git a/java/javasrc/src/main/java/com/longbridge/fundamental/Macroeconomic.java b/java/javasrc/src/main/java/com/longbridge/fundamental/Macroeconomic.java index caca0ccda..c817f54b5 100644 --- a/java/javasrc/src/main/java/com/longbridge/fundamental/Macroeconomic.java +++ b/java/javasrc/src/main/java/com/longbridge/fundamental/Macroeconomic.java @@ -10,6 +10,6 @@ public class Macroeconomic { public String forecastValue; public String revisedValue; public String nextReleaseAt; - public MultiLanguageText unit; - public MultiLanguageText unitPrefix; + public String unit; + public String unitPrefix; } diff --git a/java/javasrc/src/main/java/com/longbridge/fundamental/MacroeconomicIndicator.java b/java/javasrc/src/main/java/com/longbridge/fundamental/MacroeconomicIndicator.java index c83d4fd5a..d46e9e072 100644 --- a/java/javasrc/src/main/java/com/longbridge/fundamental/MacroeconomicIndicator.java +++ b/java/javasrc/src/main/java/com/longbridge/fundamental/MacroeconomicIndicator.java @@ -6,12 +6,12 @@ public class MacroeconomicIndicator { public String indicatorCode; public String sourceOrg; public String country; - public MultiLanguageText name; + public String name; public String adjustmentFactor; /** Release periodicity (e.g. monthly / quarterly). */ public String periodicity; public String category; - public MultiLanguageText describe; + public String describe; /** Importance — higher is more important. */ public int importance; /** Start date of data coverage (unix timestamp string). */ diff --git a/java/src/fundamental_context.rs b/java/src/fundamental_context.rs index 163b2fd45..bfd2d8b37 100644 --- a/java/src/fundamental_context.rs +++ b/java/src/fundamental_context.rs @@ -269,6 +269,7 @@ pub unsafe extern "system" fn Java_com_longbridge_SdkNative_fundamentalContextMa _class: JClass, context: i64, country: JObject, + keyword: JObject, offset: JObject, limit: JObject, callback: JObject, @@ -288,12 +289,13 @@ pub unsafe extern "system" fn Java_com_longbridge_SdkNative_fundamentalContextMa _ => None, } }); + let keyword: Option = FromJValue::from_jvalue(env, keyword.into())?; let offset: Option = FromJValue::from_jvalue(env, offset.into())?; let limit: Option = FromJValue::from_jvalue(env, limit.into())?; async_util::execute(env, callback, async move { Ok(context .ctx - .macroeconomic_indicators(country, offset, limit) + .macroeconomic_indicators(country, keyword, offset, limit) .await?) })?; Ok(()) diff --git a/nodejs/index.d.ts b/nodejs/index.d.ts index 56b157e18..d564d1d5f 100644 --- a/nodejs/index.d.ts +++ b/nodejs/index.d.ts @@ -622,6 +622,10 @@ export declare class FundamentalContext { macroeconomicIndicators(country?: MacroeconomicCountry | undefined | null, offset?: number | undefined | null, limit?: number | undefined | null): Promise /** Get historical data for a macroeconomic indicator */ macroeconomic(indicatorCode: string, startDate?: string | undefined | null, endDate?: string | undefined | null, offset?: number | undefined | null, limit?: number | undefined | null): Promise + /** List macroeconomic indicators (v2) with optional keyword filter */ + macroeconomicIndicatorsV2(country?: MacroeconomicCountry | undefined | null, keyword?: string | undefined | null, offset?: number | undefined | null, limit?: number | undefined | null): Promise + /** Get historical data for a macroeconomic indicator (v2) with sort support */ + macroeconomicV2(indicatorCode: string, startDate?: string | undefined | null, endDate?: string | undefined | null, offset?: number | undefined | null, limit?: number | undefined | null, sort?: string | undefined | null): Promise } /** Fund position */ @@ -4488,8 +4492,8 @@ export interface Macroeconomic { revisedValue: string /** Next release datetime (unix timestamp in seconds; null if unset) */ nextReleaseAt?: number - unit: MultiLanguageText - unitPrefix: MultiLanguageText + unit: string + unitPrefix: string } /** Country code for filtering macroeconomic indicators */ @@ -4513,11 +4517,11 @@ export interface MacroeconomicIndicator { indicatorCode: string sourceOrg: string country: string - name: MultiLanguageText + name: string adjustmentFactor: string periodicity: string category: string - describe: MultiLanguageText + describe: string importance: number /** Start date of data coverage (unix timestamp in seconds; null if unset) */ startDate?: number diff --git a/nodejs/index.js b/nodejs/index.js index fa943da93..25721d294 100644 --- a/nodejs/index.js +++ b/nodejs/index.js @@ -689,7 +689,7 @@ module.exports.FlowDirection = nativeBinding.FlowDirection module.exports.Granularity = nativeBinding.Granularity module.exports.InstitutionRecommend = nativeBinding.InstitutionRecommend module.exports.Language = nativeBinding.Language -module.exports.MacrodataCountry = nativeBinding.MacrodataCountry +module.exports.MacroeconomicCountry = nativeBinding.MacroeconomicCountry module.exports.Market = nativeBinding.Market module.exports.OptionDirection = nativeBinding.OptionDirection module.exports.OptionType = nativeBinding.OptionType diff --git a/nodejs/src/fundamental/context.rs b/nodejs/src/fundamental/context.rs index 3fdc33587..78ae9285f 100644 --- a/nodejs/src/fundamental/context.rs +++ b/nodejs/src/fundamental/context.rs @@ -293,12 +293,13 @@ impl FundamentalContext { pub async fn macroeconomic_indicators( &self, country: Option, + keyword: Option, offset: Option, limit: Option, ) -> Result { Ok(self .ctx - .macroeconomic_indicators(country.map(Into::into), offset, limit) + .macroeconomic_indicators(country.map(Into::into), keyword, offset, limit) .await .map_err(ErrorNewType)? .into()) diff --git a/nodejs/src/fundamental/types.rs b/nodejs/src/fundamental/types.rs index e66916ff5..0e8526c87 100644 --- a/nodejs/src/fundamental/types.rs +++ b/nodejs/src/fundamental/types.rs @@ -1979,11 +1979,11 @@ pub struct MacroeconomicIndicator { pub indicator_code: String, pub source_org: String, pub country: String, - pub name: MultiLanguageText, + pub name: String, pub adjustment_factor: String, pub periodicity: String, pub category: String, - pub describe: MultiLanguageText, + pub describe: String, pub importance: i32, /// Start date of data coverage (unix timestamp in seconds; null if unset) pub start_date: Option, @@ -1995,11 +1995,11 @@ impl From for MacroeconomicIndicator { indicator_code: v.indicator_code, source_org: v.source_org, country: v.country, - name: v.name.into(), + name: v.name, adjustment_factor: v.adjustment_factor, periodicity: v.periodicity, category: v.category, - describe: v.describe.into(), + describe: v.describe, importance: v.importance, start_date: v.start_date.map(|dt| dt.unix_timestamp()), } @@ -2019,8 +2019,8 @@ pub struct Macroeconomic { pub revised_value: String, /// Next release datetime (unix timestamp in seconds; null if unset) pub next_release_at: Option, - pub unit: MultiLanguageText, - pub unit_prefix: MultiLanguageText, + pub unit: String, + pub unit_prefix: String, } impl From for Macroeconomic { @@ -2033,8 +2033,8 @@ impl From for Macroeconomic { forecast_value: v.forecast_value, revised_value: v.revised_value, next_release_at: v.next_release_at.map(|dt| dt.unix_timestamp()), - unit: v.unit.into(), - unit_prefix: v.unit_prefix.into(), + unit: v.unit, + unit_prefix: v.unit_prefix, } } } diff --git a/python/pysrc/longbridge/openapi.pyi b/python/pysrc/longbridge/openapi.pyi index 8186b1c8f..bef3ba940 100644 --- a/python/pysrc/longbridge/openapi.pyi +++ b/python/pysrc/longbridge/openapi.pyi @@ -10118,12 +10118,12 @@ class MacroeconomicIndicator: """External vendor code (input to macroeconomic)""" source_org: str country: str - name: MultiLanguageText + name: str adjustment_factor: str periodicity: str """Release periodicity (e.g. monthly / quarterly)""" category: str - describe: MultiLanguageText + describe: str importance: int start_date: datetime | None """Start date of data coverage""" @@ -10140,8 +10140,8 @@ class Macroeconomic: forecast_value: str revised_value: str next_release_at: datetime | None - unit: MultiLanguageText - unit_prefix: MultiLanguageText + unit: str + unit_prefix: str class MacroeconomicResponse: diff --git a/python/src/fundamental/context.rs b/python/src/fundamental/context.rs index 5d4dd8639..1804b1919 100644 --- a/python/src/fundamental/context.rs +++ b/python/src/fundamental/context.rs @@ -213,12 +213,13 @@ impl FundamentalContext { fn macroeconomic_indicators( &self, country: Option, + keyword: Option, offset: Option, limit: Option, ) -> PyResult { Ok(self .ctx - .macroeconomic_indicators(country.map(Into::into), offset, limit) + .macroeconomic_indicators(country.map(Into::into), keyword, offset, limit) .map_err(ErrorNewType)? .into()) } diff --git a/python/src/fundamental/context_async.rs b/python/src/fundamental/context_async.rs index 1fe4f9d5c..d0ef8151a 100644 --- a/python/src/fundamental/context_async.rs +++ b/python/src/fundamental/context_async.rs @@ -323,13 +323,14 @@ impl AsyncFundamentalContext { &self, py: Python<'_>, country: Option, + keyword: Option, offset: Option, limit: Option, ) -> PyResult> { let ctx = self.ctx.clone(); pyo3_async_runtimes::tokio::future_into_py(py, async move { Ok(MacroeconomicIndicatorListResponse::from( - ctx.macroeconomic_indicators(country.map(Into::into), offset, limit) + ctx.macroeconomic_indicators(country.map(Into::into), keyword, offset, limit) .await .map_err(ErrorNewType)?, )) diff --git a/python/src/fundamental/types.rs b/python/src/fundamental/types.rs index c541cb7c9..ea842a54b 100644 --- a/python/src/fundamental/types.rs +++ b/python/src/fundamental/types.rs @@ -2036,11 +2036,11 @@ pub(crate) struct MacroeconomicIndicator { pub indicator_code: String, pub source_org: String, pub country: String, - pub name: MultiLanguageText, + pub name: String, pub adjustment_factor: String, pub periodicity: String, pub category: String, - pub describe: MultiLanguageText, + pub describe: String, pub importance: i32, pub start_date: Option, } @@ -2051,11 +2051,11 @@ impl From for MacroeconomicIndicator { indicator_code: v.indicator_code, source_org: v.source_org, country: v.country, - name: v.name.into(), + name: v.name, adjustment_factor: v.adjustment_factor, periodicity: v.periodicity, category: v.category, - describe: v.describe.into(), + describe: v.describe, importance: v.importance, start_date: v.start_date.map(crate::time::PyOffsetDateTimeWrapper), } @@ -2073,8 +2073,8 @@ pub(crate) struct Macroeconomic { pub forecast_value: String, pub revised_value: String, pub next_release_at: Option, - pub unit: MultiLanguageText, - pub unit_prefix: MultiLanguageText, + pub unit: String, + pub unit_prefix: String, } impl From for Macroeconomic { @@ -2087,8 +2087,8 @@ impl From for Macroeconomic { forecast_value: v.forecast_value, revised_value: v.revised_value, next_release_at: v.next_release_at.map(crate::time::PyOffsetDateTimeWrapper), - unit: v.unit.into(), - unit_prefix: v.unit_prefix.into(), + unit: v.unit, + unit_prefix: v.unit_prefix, } } } diff --git a/rust/src/blocking/fundamental.rs b/rust/src/blocking/fundamental.rs index d580a0484..532c09bc1 100644 --- a/rust/src/blocking/fundamental.rs +++ b/rust/src/blocking/fundamental.rs @@ -295,11 +295,13 @@ impl FundamentalContextSync { pub fn macroeconomic_indicators( &self, country: Option, + keyword: Option + Send + 'static>, offset: Option, limit: Option, ) -> Result { self.rt.call(move |ctx| async move { - ctx.macroeconomic_indicators(country, offset, limit).await + ctx.macroeconomic_indicators(country, keyword, offset, limit) + .await }) } @@ -317,4 +319,34 @@ impl FundamentalContextSync { .await }) } + + /// List macroeconomic indicators (v2) with optional keyword filter + pub(crate) fn macroeconomic_indicators_v2( + &self, + country: Option, + keyword: Option + Send + 'static>, + offset: Option, + limit: Option, + ) -> Result { + self.rt.call(move |ctx| async move { + ctx.macroeconomic_indicators_v2(country, keyword, offset, limit) + .await + }) + } + + /// Get historical data for a macroeconomic indicator (v2) with sort support + pub(crate) fn macroeconomic_v2( + &self, + indicator_code: impl Into + Send + 'static, + start_date: Option + Send + 'static>, + end_date: Option + Send + 'static>, + offset: Option, + limit: Option, + sort: Option + Send + 'static>, + ) -> Result { + self.rt.call(move |ctx| async move { + ctx.macroeconomic_v2(indicator_code, start_date, end_date, offset, limit, sort) + .await + }) + } } diff --git a/rust/src/fundamental/context.rs b/rust/src/fundamental/context.rs index be0212c9c..450848147 100644 --- a/rust/src/fundamental/context.rs +++ b/rust/src/fundamental/context.rs @@ -834,54 +834,92 @@ impl FundamentalContext { /// List macroeconomic indicators. /// - /// Pass `country` to filter by country code (e.g. - /// `MacroeconomicCountry::UnitedStates`). + /// `country` accepts a market code string (e.g. `"US"`, `"HK"`, `"ALL"`). + /// `keyword` optionally filters indicators by name (fuzzy, + /// case-insensitive). `offset` and `limit` are kept for backward + /// compatibility but ignored by v2. /// - /// Path: `GET /v1/quote/macrodata` + /// Path: `GET /v2/quote/macrodata` pub async fn macroeconomic_indicators( &self, country: Option, + keyword: Option>, + offset: Option, + limit: Option, + ) -> Result { + self.macroeconomic_indicators_v2(country, keyword, offset, limit) + .await + } + + /// List macroeconomic indicators (v2) with optional keyword filter. + /// + /// Path: `GET /v2/quote/macrodata` + pub(crate) async fn macroeconomic_indicators_v2( + &self, + country: Option, + keyword: Option>, offset: Option, limit: Option, ) -> Result { #[derive(Serialize)] struct Query { + market: String, #[serde(skip_serializing_if = "Option::is_none")] - country: Option, + keyword: Option, #[serde(skip_serializing_if = "Option::is_none")] offset: Option, #[serde(skip_serializing_if = "Option::is_none")] limit: Option, } - let country_str = country.map(|c| { - match c { - MacroeconomicCountry::HongKong => "Hong Kong SAR China", - MacroeconomicCountry::China => "China (Mainland)", - MacroeconomicCountry::UnitedStates => "United States", - MacroeconomicCountry::EuroZone => "Euro Zone", - MacroeconomicCountry::Japan => "Japan", - MacroeconomicCountry::Singapore => "Singapore", - } - .to_string() - }); - self.get( - "/v1/quote/macrodata", - Query { - country: country_str, - offset, - limit, - }, - ) - .await + let market = country + .map(|c| match c { + MacroeconomicCountry::HongKong => "HK", + MacroeconomicCountry::China => "CN", + MacroeconomicCountry::UnitedStates => "US", + MacroeconomicCountry::EuroZone => "EU", + MacroeconomicCountry::Japan => "JP", + MacroeconomicCountry::Singapore => "SG", + }) + .unwrap_or("ALL") + .to_string(); + + let raw: V2MacroIndicatorListResponse = self + .get( + "/v2/quote/macrodata", + Query { + market, + keyword: keyword.map(|k| k.into()), + offset, + limit, + }, + ) + .await?; + + let total = raw.total; + let data = raw + .indicator_list + .into_iter() + .map(|ind| MacroeconomicIndicator { + indicator_code: ind.indicator_id.to_string(), + country: ind.market, + name: ind.indicator_name, + periodicity: ind.frequence, + describe: ind.description, + importance: ind.importance, + ..Default::default() + }) + .collect::>(); + let count = if total > 0 { total } else { data.len() as i32 }; + Ok(MacroeconomicIndicatorListResponse { data, count }) } /// Get historical data for a macroeconomic indicator. /// - /// `start_date` and `end_date` are date strings in `"YYYY-MM-DD"` format. - /// `start_date` is sent as `YYYY-MM-DDT00:00:00Z`; `end_date` is sent as - /// `YYYY-MM-DDT23:59:59Z`. + /// `indicator_code` is the indicator ID (integer as string in v2). + /// `start_date` and `end_date` are `"YYYY-MM-DD"` format. + /// `sort` can be `"asc"` or `"desc"` (new in v2). /// - /// Path: `GET /v1/quote/macrodata/{indicator_code}` + /// Path: `GET /v2/quote/macrodata/{indicator_id}` pub async fn macroeconomic( &self, indicator_code: impl Into, @@ -889,33 +927,106 @@ impl FundamentalContext { end_date: Option>, offset: Option, limit: Option, + ) -> Result { + self.macroeconomic_v2( + indicator_code, + start_date, + end_date, + offset, + limit, + None::, + ) + .await + } + + /// Get historical data for a macroeconomic indicator (v2) with sort + /// support. + /// + /// Path: `GET /v2/quote/macrodata/{indicator_id}` + pub(crate) async fn macroeconomic_v2( + &self, + indicator_code: impl Into, + start_date: Option>, + end_date: Option>, + offset: Option, + limit: Option, + sort: Option>, ) -> Result { #[derive(Serialize)] struct Query { #[serde(skip_serializing_if = "Option::is_none")] - start_time: Option, + start_date: Option, #[serde(skip_serializing_if = "Option::is_none")] - end_time: Option, + end_date: Option, #[serde(skip_serializing_if = "Option::is_none")] offset: Option, #[serde(skip_serializing_if = "Option::is_none")] limit: Option, + #[serde(skip_serializing_if = "Option::is_none")] + sort: Option, } - let path = format!("/v1/quote/macrodata/{}", indicator_code.into()); - Ok(self + let path = format!("/v2/quote/macrodata/{}", indicator_code.into()); + let raw: V2MacroIndicatorDataResponse = self .0 .http_cli .request(Method::GET, path) .query_params(Query { - start_time: start_date.map(|d| format!("{}T00:00:00Z", d.into())), - end_time: end_date.map(|d| format!("{}T23:59:59Z", d.into())), + start_date: start_date.map(|d| d.into()), + end_date: end_date.map(|d| d.into()), offset, limit, + sort: Some(sort.map(|s| s.into()).unwrap_or_else(|| "desc".to_string())), }) - .response::>() + .response::>() .send() .with_subscriber(self.0.log_subscriber.clone()) .await? - .0) + .0; + + let total = raw.total; + let detail = raw.indicator; + let unit_english = detail.unit.clone(); + let count = detail.indicator_data.len() as i32; + + let info = MacroeconomicIndicator { + indicator_code: detail.indicator_id.to_string(), + country: detail.market, + name: detail.indicator_name, + describe: detail.description, + ..Default::default() + }; + + let data = detail + .indicator_data + .into_iter() + .map(|d| { + use time::format_description::well_known::Rfc3339; + let release_at = time::OffsetDateTime::parse(&d.published_time, &Rfc3339) + .ok() + .or_else(|| { + // Try without timezone suffix + time::PrimitiveDateTime::parse( + &d.published_time, + &time::macros::format_description!( + "[year]-[month]-[day]T[hour]:[minute]:[second]" + ), + ) + .ok() + .map(|dt| dt.assume_utc()) + }); + Macroeconomic { + period: d.observation_date, + release_at, + actual_value: d.actual_data, + previous_value: d.previous_data, + forecast_value: d.estimated_data, + unit: unit_english.clone(), + ..Default::default() + } + }) + .collect(); + + let count = if total > 0 { total } else { count }; + Ok(MacroeconomicResponse { info, data, count }) } } diff --git a/rust/src/fundamental/types.rs b/rust/src/fundamental/types.rs index 9bee91e22..fa127e9c4 100644 --- a/rust/src/fundamental/types.rs +++ b/rust/src/fundamental/types.rs @@ -1636,9 +1636,9 @@ pub struct MacroeconomicIndicator { /// Country #[serde(default)] pub country: String, - /// Indicator name (multilingual) - #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")] - pub name: MultiLanguageText, + /// Indicator name + #[serde(default)] + pub name: String, /// Adjustment factor #[serde(default)] pub adjustment_factor: String, @@ -1648,9 +1648,9 @@ pub struct MacroeconomicIndicator { /// Indicator category #[serde(default)] pub category: String, - /// Description (multilingual) - #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")] - pub describe: MultiLanguageText, + /// Description + #[serde(default)] + pub describe: String, /// Importance — higher is more important #[serde(default)] pub importance: i32, @@ -1698,12 +1698,12 @@ pub struct Macroeconomic { /// Next release datetime #[serde(default, with = "crate::serde_utils::rfc3339_opt")] pub next_release_at: Option, - /// Unit (multilingual) - #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")] - pub unit: MultiLanguageText, - /// Unit prefix / data scale (multilingual, e.g. millions / billions) - #[serde(default, deserialize_with = "crate::serde_utils::null_as_default")] - pub unit_prefix: MultiLanguageText, + /// Unit + #[serde(default)] + pub unit: String, + /// Unit prefix / data scale (e.g. millions / billions) + #[serde(default)] + pub unit_prefix: String, } /// Response for [`crate::FundamentalContext::macroeconomic`] @@ -1719,3 +1719,77 @@ pub struct MacroeconomicResponse { #[serde(default)] pub count: i32, } + +// ── v2 wire types (internal, used for mapping to existing public types) ────── + +/// v2 wire: one indicator from GET /v2/quote/macrodata +#[derive(Debug, Clone, Serialize, Deserialize)] +pub(crate) struct V2MacroIndicator { + #[serde(default)] + pub indicator_id: i32, + #[serde(default)] + pub indicator_name: String, + #[serde(default)] + pub market: String, + #[serde(default)] + pub importance: i32, + #[serde(default)] + pub description: String, + /// Update frequency: day/week/month/quarter/half_year/year + #[serde(default)] + pub frequence: String, +} + +/// v2 wire: response from GET /v2/quote/macrodata +#[derive(Debug, Clone, Serialize, Deserialize)] +pub(crate) struct V2MacroIndicatorListResponse { + #[serde(default)] + pub indicator_list: Vec, + /// Total count for pagination + #[serde(default)] + pub total: i32, +} + +/// v2 wire: one data point from GET /v2/quote/macrodata/:id +#[derive(Debug, Clone, Serialize, Deserialize)] +pub(crate) struct V2IndicatorDataDetail { + #[serde(default)] + pub actual_data: String, + #[serde(default)] + pub previous_data: String, + #[serde(default)] + pub estimated_data: String, + #[serde(default)] + pub published_time: String, + #[serde(default)] + pub observation_date: String, +} + +/// v2 wire: one indicator with data from GET /v2/quote/macrodata/:id +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +pub(crate) struct V2MacroIndicatorDetail { + #[serde(default)] + pub indicator_id: i32, + #[serde(default)] + pub indicator_name: String, + #[serde(default)] + pub unit: String, + #[serde(default)] + pub description: String, + #[serde(default)] + pub market: String, + #[serde(default)] + pub indicator_data: Vec, +} + +/// v2 wire: response from GET /v2/quote/macrodata/:id +/// (GetMacroIndicatorHistoryResp) +#[derive(Debug, Clone, Default, Serialize, Deserialize)] +pub(crate) struct V2MacroIndicatorDataResponse { + /// Single indicator with paginated data points + #[serde(default)] + pub indicator: V2MacroIndicatorDetail, + /// Total data points matching the query (for pagination) + #[serde(default)] + pub total: i32, +} From 1dac7937395386b5ea7dee24bfed933e48840aa5 Mon Sep 17 00:00:00 2001 From: Jason Lee Date: Tue, 16 Jun 2026 16:14:59 +0800 Subject: [PATCH 25/26] feat(market): add trade status enum (#546) ## Summary - Add `longbridge::market::TradeStatus` for market status codes with engine-compatible variants, normalization, labels, and names. - Type `/v1/quote/market-status` Rust fields as `TradeStatus` while preserving integer values for C, Java, Node.js, and Python wrappers. - Add the serde_repr workspace dependency and changelog entry. ## Test Plan - `cargo +nightly fmt --all` - `cargo test -p longbridge market_trade_status` - `cargo check --workspace` - `cargo clippy --all --all-features` - `git diff --check` Co-authored-by: Codex --- CHANGELOG.md | 5 + Cargo.toml | 1 + c/src/market_context/types.rs | 4 +- java/src/types/primary_types.rs | 13 ++ nodejs/src/market/types.rs | 4 +- python/src/market/types.rs | 4 +- rust/Cargo.toml | 1 + rust/src/market/types.rs | 368 +++++++++++++++++++++++++++++++- 8 files changed, 389 insertions(+), 11 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9d74445a8..498b0dbdc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [Unreleased] + +### Added + +- **Rust:** `market::TradeStatus` models `/v1/quote/market-status` trade status codes, including engine-compatible normalization and display helpers. ## [4.3.2] - 2026-06-13 ### Added diff --git a/Cargo.toml b/Cargo.toml index 8606b5cb6..bc0d4a438 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,6 +33,7 @@ strum = "0.27.2" strum_macros = "0.27.2" serde = "1.0.219" serde_json = "1.0.142" +serde_repr = "0.1" dotenv = "0.15.0" http = "1.3.1" comfy-table = "7.1.4" diff --git a/c/src/market_context/types.rs b/c/src/market_context/types.rs index db010ff8c..15e36dbf2 100644 --- a/c/src/market_context/types.rs +++ b/c/src/market_context/types.rs @@ -46,9 +46,9 @@ impl From for CMarketTimeItemOwned { fn from(v: MarketTimeItem) -> Self { Self { market: v.market.into(), - trade_status: v.trade_status, + trade_status: v.trade_status.code(), timestamp: v.timestamp.into(), - delay_trade_status: v.delay_trade_status, + delay_trade_status: v.delay_trade_status.code(), delay_timestamp: v.delay_timestamp.into(), sub_status: v.sub_status, delay_sub_status: v.delay_sub_status, diff --git a/java/src/types/primary_types.rs b/java/src/types/primary_types.rs index 1b7ff8fad..c503fbfaf 100644 --- a/java/src/types/primary_types.rs +++ b/java/src/types/primary_types.rs @@ -27,6 +27,19 @@ impl IntoJValue for i32 { } } +impl JSignature for longbridge::market::TradeStatus { + fn signature() -> Cow<'static, str> { + i32::signature() + } +} + +impl IntoJValue for longbridge::market::TradeStatus { + #[inline] + fn into_jvalue<'a>(self, env: &mut JNIEnv<'a>) -> Result> { + self.code().into_jvalue(env) + } +} + impl JSignature for i64 { fn signature() -> Cow<'static, str> { "J".into() diff --git a/nodejs/src/market/types.rs b/nodejs/src/market/types.rs index 3d81fc259..e0036cf98 100644 --- a/nodejs/src/market/types.rs +++ b/nodejs/src/market/types.rs @@ -41,9 +41,9 @@ impl From for MarketTimeItem { fn from(v: lb::MarketTimeItem) -> Self { Self { market: v.market.into(), - trade_status: v.trade_status, + trade_status: v.trade_status.code(), timestamp: v.timestamp, - delay_trade_status: v.delay_trade_status, + delay_trade_status: v.delay_trade_status.code(), delay_timestamp: v.delay_timestamp, sub_status: v.sub_status, delay_sub_status: v.delay_sub_status, diff --git a/python/src/market/types.rs b/python/src/market/types.rs index 4ba37f306..a13473c0c 100644 --- a/python/src/market/types.rs +++ b/python/src/market/types.rs @@ -235,9 +235,9 @@ impl From for MarketTimeItem { fn from(v: lb::MarketTimeItem) -> Self { Self { market: v.market.into(), - trade_status: v.trade_status, + trade_status: v.trade_status.code(), timestamp: v.timestamp, - delay_trade_status: v.delay_trade_status, + delay_trade_status: v.delay_trade_status.code(), delay_timestamp: v.delay_timestamp, sub_status: v.sub_status, delay_sub_status: v.delay_sub_status, diff --git a/rust/Cargo.toml b/rust/Cargo.toml index 4dcdec1ce..a83c5e1fc 100644 --- a/rust/Cargo.toml +++ b/rust/Cargo.toml @@ -41,6 +41,7 @@ strum.workspace = true strum_macros.workspace = true serde = { workspace = true, features = ["derive"] } serde_json.workspace = true +serde_repr.workspace = true dotenv.workspace = true http.workspace = true comfy-table.workspace = true diff --git a/rust/src/market/types.rs b/rust/src/market/types.rs index 8f62cdd4c..dfcc86fe2 100644 --- a/rust/src/market/types.rs +++ b/rust/src/market/types.rs @@ -2,12 +2,280 @@ use rust_decimal::Decimal; use serde::{Deserialize, Serialize}; +use serde_repr::{Deserialize_repr, Serialize_repr}; +use strum_macros::{FromRepr, IntoStaticStr}; use time::OffsetDateTime; use crate::{types::Market, utils::counter::deserialize_counter_id_as_symbol}; // ── market_status ───────────────────────────────────────────────── +/// Market trading status code. +#[allow(non_camel_case_types)] +#[derive( + Debug, + Clone, + Copy, + Default, + Hash, + PartialOrd, + Ord, + PartialEq, + Eq, + FromRepr, + IntoStaticStr, + Serialize_repr, + Deserialize_repr, +)] +#[repr(i32)] +pub enum TradeStatus { + /// Unknown status + #[default] + #[serde(other)] + UNKNOWN = -1, + /// Quote is not registered + NO_REGISTER_QUOTE = 0, + /// Clearing + CLEAN = 101, + /// Opening auction + OPEN_BID = 102, + /// Morning break, currently used by VIX indexes + MORNING_CLOSING = 103, + /// Trading + TRADING = 105, + /// Midday break + NOON_CLOSING = 106, + /// Closing auction + CLOSE_BID = 107, + /// Closed + CLOSING = 108, + /// Dark pool waiting to open + DARK_WAIT = 110, + /// Dark pool trading + DARK_TRADING = 111, + /// Dark pool closed + DARK_CLOSING = 112, + /// After-hours fixed-price trading + AFTER_FIX = 120, + /// Half-day market closed + HALF_CLOSING = 121, + /// Not opened + NOT_OPENED = 122, + /// Realtime quotes + REALTIME_QUOTE = 123, + /// US pre-market + US_PREV = 201, + /// US regular trading + US_TRADING = 202, + /// US post-market + US_AFTER = 203, + /// US closed + US_CLOSING = 204, + /// US halted + US_STOP = 205, + /// US clearing before pre-market + US_CLEAN = 206, + /// US overnight trading + US_NIGHT = 207, + /// US pre-market clearing + US_PREV_MARKET_CLEAN = 209, + /// US post-market clearing + US_AFTER_MARKET_CLEAN = 210, + /// Stock refresh + REFRESH = 1000, + /// Delisted + DELIST = 1001, + /// Preparing to list + PREPARE = 1002, + /// Code changed + CODE_CHANGE = 1003, + /// Halted + STOP = 1004, + /// Waiting to open + WILL_OPEN = 1005, + /// Split or merge suspended + COMMON_SUSPEND = 1006, + /// Expired + EXPIRE = 1007, + /// No quote + NO_QUOTE = 1008, + /// Not listed + UNITED = 1009, + /// Trading halted + TRADING_HALT = 1010, + /// Waiting to list + WAIT_LISTING = 1011, +} + +impl From for TradeStatus { + fn from(value: i32) -> Self { + Self::from_repr(value).unwrap_or_default() + } +} + +impl TradeStatus { + /// Converts an isize value to a market trading status. + pub fn from_isize(value: isize) -> TradeStatus { + (value as i32).into() + } + + /// Returns the raw numeric status code. + pub fn code(self) -> i32 { + self as i32 + } + + /// Returns the static enum variant name. + pub fn as_static(self) -> &'static str { + self.into() + } + + /// Returns a simplified label for key display states. + pub fn label(self) -> &'static str { + let status = self.normalize(); + match status { + TradeStatus::US_PREV + | TradeStatus::US_TRADING + | TradeStatus::US_AFTER + | TradeStatus::US_NIGHT + | TradeStatus::US_CLOSING + | TradeStatus::TRADING + | TradeStatus::CLOSING => status.name(), + _ => "", + } + } + + /// Returns the full English status name. + pub fn name(self) -> &'static str { + match self.normalize() { + TradeStatus::UNKNOWN | TradeStatus::NO_REGISTER_QUOTE => "Unknown", + TradeStatus::OPEN_BID => "Open Bid", + TradeStatus::MORNING_CLOSING => "Morning Break", + TradeStatus::TRADING | TradeStatus::US_TRADING | TradeStatus::US_AFTER_MARKET_CLEAN => { + "Trading" + } + TradeStatus::NOON_CLOSING => "Mid-Day Break", + TradeStatus::CLOSE_BID => "Close Bid", + TradeStatus::CLOSING + | TradeStatus::CLEAN + | TradeStatus::HALF_CLOSING + | TradeStatus::US_CLOSING + | TradeStatus::US_PREV_MARKET_CLEAN => "Closed", + TradeStatus::DARK_WAIT => "Dark Wait", + TradeStatus::DARK_TRADING => "Dark Trading", + TradeStatus::DARK_CLOSING => "Closing", + TradeStatus::AFTER_FIX => "After Fix", + TradeStatus::NOT_OPENED => "Not Open", + TradeStatus::REALTIME_QUOTE => "Realtime Quotes", + TradeStatus::US_PREV | TradeStatus::US_CLEAN => "Pre-Market", + TradeStatus::US_AFTER => "Post-Market", + TradeStatus::US_STOP | TradeStatus::STOP => "Stop", + TradeStatus::US_NIGHT => "Overnight", + TradeStatus::REFRESH => "Refresh", + TradeStatus::DELIST => "Delist", + TradeStatus::PREPARE => "Prepare", + TradeStatus::CODE_CHANGE => "Code Change", + TradeStatus::WILL_OPEN => "Will Open", + TradeStatus::COMMON_SUSPEND => "Common Suspend", + TradeStatus::EXPIRE => "Expire", + TradeStatus::NO_QUOTE => "No Quote", + TradeStatus::UNITED => "United", + TradeStatus::TRADING_HALT => "Trading Halt", + TradeStatus::WAIT_LISTING => "Wait Listing", + } + } + + /// Returns whether this is a US market status. + pub fn is_us_market(self) -> bool { + self.code() >= 200 && self.code() < 300 + } + + /// Returns whether this is a US pre/post-market status. + pub fn is_us_pre_post(self) -> bool { + self.is_us_prev() || self.is_us_after() + } + + /// Returns whether this is a US overnight status. + pub fn is_us_night(self) -> bool { + matches!(self, TradeStatus::US_NIGHT) + } + + /// Returns whether this is a US closed status. + pub fn is_us_closing(self) -> bool { + matches!( + self, + TradeStatus::US_CLOSING | TradeStatus::US_PREV_MARKET_CLEAN + ) + } + + /// Returns whether this is a closed status. + pub fn is_closing(self) -> bool { + matches!( + self, + TradeStatus::US_CLOSING + | TradeStatus::US_PREV_MARKET_CLEAN + | TradeStatus::CLOSING + | TradeStatus::HALF_CLOSING + ) + } + + /// Returns whether this is a US pre-market status. + pub fn is_us_prev(self) -> bool { + matches!(self, TradeStatus::US_PREV | TradeStatus::US_CLEAN) + } + + /// Returns whether this is a US post-market status. + pub fn is_us_after(self) -> bool { + matches!(self, TradeStatus::US_AFTER) + } + + /// Returns whether this is a trading status. + pub fn is_trading(self) -> bool { + matches!( + self, + TradeStatus::TRADING | TradeStatus::US_TRADING | TradeStatus::US_AFTER_MARKET_CLEAN + ) + } + + /// Returns whether this is a dark-pool status. + pub fn is_dark(self) -> bool { + matches!( + self, + TradeStatus::DARK_WAIT | TradeStatus::DARK_TRADING | TradeStatus::DARK_CLOSING + ) + } + + /// Returns whether this status allows trading. + pub fn allow_trading(self) -> bool { + matches!( + self, + TradeStatus::OPEN_BID + | TradeStatus::TRADING + | TradeStatus::CLOSE_BID + | TradeStatus::NOT_OPENED + | TradeStatus::NOON_CLOSING + | TradeStatus::US_TRADING + | TradeStatus::US_AFTER_MARKET_CLEAN + ) + } + + /// Normalizes clearing aliases to their display-equivalent status. + #[must_use] + pub fn normalize(self) -> Self { + match self { + TradeStatus::CLEAN => TradeStatus::CLOSING, + TradeStatus::US_PREV_MARKET_CLEAN => TradeStatus::US_CLOSING, + TradeStatus::US_CLEAN => TradeStatus::US_PREV, + TradeStatus::US_AFTER_MARKET_CLEAN => TradeStatus::US_TRADING, + _ => self, + } + } + + /// Returns whether this is a special non-regular status. + pub fn is_special(self) -> bool { + self.code() < 100 || self == Self::US_STOP || self.code() >= 1000 + } +} + /// Response for [`crate::MarketContext::market_status`] #[derive(Debug, Clone, Serialize, Deserialize)] pub struct MarketStatusResponse { @@ -20,13 +288,12 @@ pub struct MarketStatusResponse { pub struct MarketTimeItem { /// Market code pub market: Market, - /// Raw trade status code (101=PreOpen, 102/103/105=Trading, 104=LunchBreak, - /// 106=PostTrading, 108=Closed, 201=PreMarket, 204=PostMarket) - pub trade_status: i32, + /// Trade status + pub trade_status: TradeStatus, /// Current market time (unix timestamp string) pub timestamp: String, - /// Delayed-quote trade status code - pub delay_trade_status: i32, + /// Delayed-quote trade status + pub delay_trade_status: TradeStatus, /// Delayed-quote market time (unix timestamp string) pub delay_timestamp: String, /// Sub-status code @@ -35,6 +302,97 @@ pub struct MarketTimeItem { pub delay_sub_status: i32, } +#[cfg(test)] +mod tests { + use crate::market::TradeStatus; + + #[test] + fn market_trade_status_deserializes_numeric_codes() { + assert_eq!( + serde_json::from_str::("202") + .expect("202 should deserialize as market trade status"), + TradeStatus::US_TRADING + ); + assert_eq!( + serde_json::from_str::("456") + .expect("unknown numeric status should deserialize"), + TradeStatus::UNKNOWN + ); + } + + #[test] + fn market_trade_status_serializes_as_numeric_code() { + let value = serde_json::to_string(&TradeStatus::US_CLEAN) + .expect("market trade status should serialize"); + assert_eq!(value, "206"); + } + + #[test] + fn market_trade_status_normalizes_engine_aliases() { + assert_eq!(TradeStatus::CLEAN.normalize(), TradeStatus::CLOSING); + assert_eq!(TradeStatus::US_CLEAN.normalize(), TradeStatus::US_PREV); + assert_eq!( + TradeStatus::US_PREV_MARKET_CLEAN.normalize(), + TradeStatus::US_CLOSING + ); + assert_eq!( + TradeStatus::US_AFTER_MARKET_CLEAN.normalize(), + TradeStatus::US_TRADING + ); + } + + #[test] + fn market_trade_status_label_matches_engine_simplified_display() { + assert_eq!(TradeStatus::US_PREV.label(), "Pre-Market"); + assert_eq!(TradeStatus::US_CLEAN.label(), "Pre-Market"); + assert_eq!(TradeStatus::US_AFTER.label(), "Post-Market"); + assert_eq!(TradeStatus::US_CLOSING.label(), "Closed"); + assert_eq!(TradeStatus::US_AFTER_MARKET_CLEAN.label(), "Trading"); + assert_eq!(TradeStatus::US_TRADING.label(), "Trading"); + assert_eq!(TradeStatus::TRADING.label(), "Trading"); + assert_eq!(TradeStatus::CLEAN.label(), "Closed"); + assert_eq!(TradeStatus::OPEN_BID.label(), ""); + assert_eq!(TradeStatus::NOON_CLOSING.label(), ""); + } + + #[test] + fn market_trade_status_name_covers_full_status_set() { + let cases = [ + (TradeStatus::MORNING_CLOSING, "Morning Break"), + (TradeStatus::NOON_CLOSING, "Mid-Day Break"), + (TradeStatus::REALTIME_QUOTE, "Realtime Quotes"), + (TradeStatus::US_STOP, "Stop"), + (TradeStatus::TRADING_HALT, "Trading Halt"), + (TradeStatus::WAIT_LISTING, "Wait Listing"), + (TradeStatus::UNKNOWN, "Unknown"), + (TradeStatus::NO_REGISTER_QUOTE, "Unknown"), + ]; + + for (status, expected) in cases { + assert_eq!(status.name(), expected, "status {status:?}"); + } + } + + #[test] + fn market_time_item_uses_market_trade_status_type() { + let item = serde_json::from_str::( + r#"{ + "market": "US", + "trade_status": 202, + "timestamp": "1717200000", + "delay_trade_status": 204, + "delay_timestamp": "1717200000", + "sub_status": 0, + "delay_sub_status": 0 + }"#, + ) + .expect("market time item should deserialize"); + + assert_eq!(item.trade_status, TradeStatus::US_TRADING); + assert_eq!(item.delay_trade_status, TradeStatus::US_CLOSING); + } +} + // ── broker_holding ──────────────────────────────────────────────── /// Response for [`crate::MarketContext::broker_holding`] From 3c995f576e245c5b3235a88f1aad5d4c2343a6c2 Mon Sep 17 00:00:00 2001 From: Jason Lee Date: Tue, 16 Jun 2026 17:16:37 +0800 Subject: [PATCH 26/26] fix: align market trade status codes (#547) ## Summary - Align Rust market TradeStatus codes with the phase/status definition, including code 2001. - Correct display names for status codes 123, 1009, and 1010 while keeping existing Rust variant names compatible. - Refresh SDK comments/generated bindings for market trade status fields. ## Test Plan - cargo +nightly fmt --all -- --check - cargo test -p longbridge market_trade_status_ --lib - RUSTC_WRAPPER= cargo clippy --all --all-features - PATH=/opt/homebrew/bin:/usr/local/bin:$PATH RUSTC_WRAPPER= npm run build:debug - RUSTC_WRAPPER= cargo build -p longbridge-c Co-authored-by: Codex --- CHANGELOG.md | 5 + c/csrc/include/longbridge.h | 5 +- c/src/market_context/types.rs | 5 +- .../com/longbridge/market/MarketTimeItem.java | 9 +- nodejs/index.d.ts | 12 +- nodejs/src/market/types.rs | 6 +- python/pysrc/longbridge/openapi.pyi | 4 +- python/src/market/types.rs | 5 +- rust/src/market/types.rs | 123 ++++++++++++------ 9 files changed, 108 insertions(+), 66 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 498b0dbdc..bb862e3bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,11 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - **Rust:** `market::TradeStatus` models `/v1/quote/market-status` trade status codes, including engine-compatible normalization and display helpers. + +### Fixed + +- **All languages:** corrected market trade status documentation and aligned `market::TradeStatus` with the status definition table, including code `2001` and the `123`/`1009`/`1010` display names. + ## [4.3.2] - 2026-06-13 ### Added diff --git a/c/csrc/include/longbridge.h b/c/csrc/include/longbridge.h index 35ff1563c..1b2fdc031 100644 --- a/c/csrc/include/longbridge.h +++ b/c/csrc/include/longbridge.h @@ -4575,7 +4575,8 @@ typedef struct lb_market_time_item_t { */ enum lb_market_t market; /** - * Current trade status code for the market. + * Current market trade status code. See the market status definition for + * the complete code table. */ int32_t trade_status; /** @@ -4583,7 +4584,7 @@ typedef struct lb_market_time_item_t { */ const char *timestamp; /** - * Delayed trade status code for the market. + * Delayed market trade status code. */ int32_t delay_trade_status; /** diff --git a/c/src/market_context/types.rs b/c/src/market_context/types.rs index 15e36dbf2..c083ffaaa 100644 --- a/c/src/market_context/types.rs +++ b/c/src/market_context/types.rs @@ -18,11 +18,12 @@ use crate::types::{CMarket, CString, CVec, ToFFI}; pub struct CMarketTimeItem { /// Market identifier. pub market: CMarket, - /// Current trade status code for the market. + /// Current market trade status code. See the market status definition for + /// the complete code table. pub trade_status: i32, /// Timestamp of the current trade status as an ISO-8601 string. pub timestamp: *const c_char, - /// Delayed trade status code for the market. + /// Delayed market trade status code. pub delay_trade_status: i32, /// Timestamp of the delayed trade status as an ISO-8601 string. pub delay_timestamp: *const c_char, diff --git a/java/javasrc/src/main/java/com/longbridge/market/MarketTimeItem.java b/java/javasrc/src/main/java/com/longbridge/market/MarketTimeItem.java index 7f1480b92..fc30da51b 100644 --- a/java/javasrc/src/main/java/com/longbridge/market/MarketTimeItem.java +++ b/java/javasrc/src/main/java/com/longbridge/market/MarketTimeItem.java @@ -5,14 +5,13 @@ public class MarketTimeItem { /** Market. */ public com.longbridge.Market market; /** - * Raw trade status code. - * 101=PreOpen, 102/103/105=Trading, 104=LunchBreak, 106=PostTrading, - * 108=Closed, 201=PreMarket, 204=PostMarket. + * Raw market trade status code. + * See the market status definition for the complete code table. */ public int tradeStatus; /** Current market time (unix timestamp string). */ public String timestamp; - /** Delayed-quote trade status code. */ + /** Delayed-quote market trade status code. */ public int delayTradeStatus; /** Delayed-quote market time (unix timestamp string). */ public String delayTimestamp; @@ -20,4 +19,4 @@ public class MarketTimeItem { public int subStatus; /** Delayed-quote sub-status code. */ public int delaySubStatus; -} \ No newline at end of file +} diff --git a/nodejs/index.d.ts b/nodejs/index.d.ts index d564d1d5f..4fcaab997 100644 --- a/nodejs/index.d.ts +++ b/nodejs/index.d.ts @@ -619,13 +619,9 @@ export declare class FundamentalContext { */ etfAssetAllocation(symbol: string): Promise /** List macroeconomic indicators */ - macroeconomicIndicators(country?: MacroeconomicCountry | undefined | null, offset?: number | undefined | null, limit?: number | undefined | null): Promise + macroeconomicIndicators(country?: MacroeconomicCountry | undefined | null, keyword?: string | undefined | null, offset?: number | undefined | null, limit?: number | undefined | null): Promise /** Get historical data for a macroeconomic indicator */ macroeconomic(indicatorCode: string, startDate?: string | undefined | null, endDate?: string | undefined | null, offset?: number | undefined | null, limit?: number | undefined | null): Promise - /** List macroeconomic indicators (v2) with optional keyword filter */ - macroeconomicIndicatorsV2(country?: MacroeconomicCountry | undefined | null, keyword?: string | undefined | null, offset?: number | undefined | null, limit?: number | undefined | null): Promise - /** Get historical data for a macroeconomic indicator (v2) with sort support */ - macroeconomicV2(indicatorCode: string, startDate?: string | undefined | null, endDate?: string | undefined | null, offset?: number | undefined | null, limit?: number | undefined | null, sort?: string | undefined | null): Promise } /** Fund position */ @@ -4566,13 +4562,13 @@ export interface MarketTimeItem { /** Market */ market: Market /** - * Raw trade status code (101=PreOpen, 102/103/105=Trading, 104=LunchBreak, - * 106=PostTrading, 108=Closed, 201=PreMarket, 204=PostMarket) + * Raw market trade status code. See the market status definition for the + * complete code table. */ tradeStatus: number /** Current market time (unix timestamp string) */ timestamp: string - /** Delayed-quote trade status code */ + /** Delayed-quote market trade status code */ delayTradeStatus: number /** Delayed-quote market time (unix timestamp string) */ delayTimestamp: string diff --git a/nodejs/src/market/types.rs b/nodejs/src/market/types.rs index e0036cf98..defaa16a7 100644 --- a/nodejs/src/market/types.rs +++ b/nodejs/src/market/types.rs @@ -22,12 +22,12 @@ impl From for MarketStatusResponse { pub struct MarketTimeItem { /// Market pub market: crate::types::Market, - /// Raw trade status code (101=PreOpen, 102/103/105=Trading, 104=LunchBreak, - /// 106=PostTrading, 108=Closed, 201=PreMarket, 204=PostMarket) + /// Raw market trade status code. See the market status definition for the + /// complete code table. pub trade_status: i32, /// Current market time (unix timestamp string) pub timestamp: String, - /// Delayed-quote trade status code + /// Delayed-quote market trade status code pub delay_trade_status: i32, /// Delayed-quote market time (unix timestamp string) pub delay_timestamp: String, diff --git a/python/pysrc/longbridge/openapi.pyi b/python/pysrc/longbridge/openapi.pyi index bef3ba940..b5a518f60 100644 --- a/python/pysrc/longbridge/openapi.pyi +++ b/python/pysrc/longbridge/openapi.pyi @@ -10159,11 +10159,11 @@ class MarketTimeItem: market: Market """Market""" trade_status: int - """Raw trade status code (101=PreOpen, 102/105=Trading, 104=LunchBreak, 106=PostTrading, 108=Closed, 201=PreMarket, 204=PostMarket)""" + """Raw market trade status code. See the market status definition for the complete code table.""" timestamp: str """Current market time (unix timestamp string)""" delay_trade_status: int - """Delayed-quote trade status code""" + """Delayed-quote market trade status code""" delay_timestamp: str """Delayed-quote market time (unix timestamp string)""" sub_status: int diff --git a/python/src/market/types.rs b/python/src/market/types.rs index a13473c0c..a6a93ac05 100644 --- a/python/src/market/types.rs +++ b/python/src/market/types.rs @@ -217,11 +217,12 @@ impl From for MarketStatusResponse { pub(crate) struct MarketTimeItem { /// Market pub market: crate::types::Market, - /// Raw trade status code + /// Raw market trade status code. See the market status definition for the + /// complete code table. pub trade_status: i32, /// Current market time (unix timestamp string) pub timestamp: String, - /// Delayed-quote trade status code + /// Delayed-quote market trade status code pub delay_trade_status: i32, /// Delayed-quote time (unix timestamp string) pub delay_timestamp: String, diff --git a/rust/src/market/types.rs b/rust/src/market/types.rs index dfcc86fe2..462da29ec 100644 --- a/rust/src/market/types.rs +++ b/rust/src/market/types.rs @@ -35,76 +35,81 @@ pub enum TradeStatus { UNKNOWN = -1, /// Quote is not registered NO_REGISTER_QUOTE = 0, - /// Clearing + /// Clearing before the market opens. CLEAN = 101, - /// Opening auction + /// Opening auction. OPEN_BID = 102, - /// Morning break, currently used by VIX indexes + /// Morning break, currently used by VIX indexes. MORNING_CLOSING = 103, - /// Trading + /// Regular trading. TRADING = 105, - /// Midday break + /// Midday break. NOON_CLOSING = 106, - /// Closing auction + /// Closing auction. CLOSE_BID = 107, - /// Closed + /// Market closed. CLOSING = 108, - /// Dark pool waiting to open + /// Dark trading waiting to open. DARK_WAIT = 110, - /// Dark pool trading + /// Dark trading. DARK_TRADING = 111, - /// Dark pool closed + /// Dark trading closed. DARK_CLOSING = 112, - /// After-hours fixed-price trading + /// After-hours fixed-price trading. AFTER_FIX = 120, - /// Half-day market closed + /// Half-day market closed. Defined by the market status table but currently + /// unused. HALF_CLOSING = 121, - /// Not opened + /// Not opened because the exchange is waiting to open under special + /// conditions. NOT_OPENED = 122, - /// Realtime quotes + /// Temporary intraday break. The historical variant name is kept for + /// compatibility. REALTIME_QUOTE = 123, - /// US pre-market + /// US pre-market. US_PREV = 201, - /// US regular trading + /// US regular trading. US_TRADING = 202, - /// US post-market + /// US post-market. US_AFTER = 203, - /// US closed + /// US closed. US_CLOSING = 204, - /// US halted + /// US halted. US_STOP = 205, - /// US clearing before pre-market + /// US clearing plus pre-market. US_CLEAN = 206, - /// US overnight trading + /// US overnight trading. US_NIGHT = 207, - /// US pre-market clearing + /// US pre-market clearing alias returned by the quote engine. US_PREV_MARKET_CLEAN = 209, - /// US post-market clearing + /// US post-market clearing alias returned by the quote engine. US_AFTER_MARKET_CLEAN = 210, - /// Stock refresh + /// Stock refresh. Deprecated in the status definition. REFRESH = 1000, - /// Delisted + /// Delisted. DELIST = 1001, - /// Preparing to list + /// Preparing to list. PREPARE = 1002, - /// Code changed + /// Code changed. CODE_CHANGE = 1003, - /// Halted + /// Halted. STOP = 1004, - /// Waiting to open + /// Waiting to open, typically for a US IPO auction. WILL_OPEN = 1005, - /// Split or merge suspended + /// Split or merge suspended. COMMON_SUSPEND = 1006, - /// Expired + /// Expired. EXPIRE = 1007, - /// No quote + /// No quote data. NO_QUOTE = 1008, - /// Not listed + /// Not listed. The historical variant name is kept for compatibility. UNITED = 1009, - /// Trading halted + /// Terminated trading, usually for warrants. TRADING_HALT = 1010, - /// Waiting to list + /// Waiting to list, usually for new warrants. WAIT_LISTING = 1011, + /// Fuse. + FUSE = 2001, } impl From for TradeStatus { @@ -165,7 +170,7 @@ impl TradeStatus { TradeStatus::DARK_CLOSING => "Closing", TradeStatus::AFTER_FIX => "After Fix", TradeStatus::NOT_OPENED => "Not Open", - TradeStatus::REALTIME_QUOTE => "Realtime Quotes", + TradeStatus::REALTIME_QUOTE => "Temporary Break", TradeStatus::US_PREV | TradeStatus::US_CLEAN => "Pre-Market", TradeStatus::US_AFTER => "Post-Market", TradeStatus::US_STOP | TradeStatus::STOP => "Stop", @@ -178,9 +183,10 @@ impl TradeStatus { TradeStatus::COMMON_SUSPEND => "Common Suspend", TradeStatus::EXPIRE => "Expire", TradeStatus::NO_QUOTE => "No Quote", - TradeStatus::UNITED => "United", - TradeStatus::TRADING_HALT => "Trading Halt", + TradeStatus::UNITED => "Not Listed", + TradeStatus::TRADING_HALT => "Terminated", TradeStatus::WAIT_LISTING => "Wait Listing", + TradeStatus::FUSE => "Fuse", } } @@ -288,11 +294,12 @@ pub struct MarketStatusResponse { pub struct MarketTimeItem { /// Market code pub market: Market, - /// Trade status + /// Market trade status. See [`TradeStatus`] for the code table. pub trade_status: TradeStatus, /// Current market time (unix timestamp string) pub timestamp: String, - /// Delayed-quote trade status + /// Delayed-quote market trade status. See [`TradeStatus`] for the code + /// table. pub delay_trade_status: TradeStatus, /// Delayed-quote market time (unix timestamp string) pub delay_timestamp: String, @@ -360,10 +367,11 @@ mod tests { let cases = [ (TradeStatus::MORNING_CLOSING, "Morning Break"), (TradeStatus::NOON_CLOSING, "Mid-Day Break"), - (TradeStatus::REALTIME_QUOTE, "Realtime Quotes"), + (TradeStatus::REALTIME_QUOTE, "Temporary Break"), (TradeStatus::US_STOP, "Stop"), - (TradeStatus::TRADING_HALT, "Trading Halt"), + (TradeStatus::TRADING_HALT, "Terminated"), (TradeStatus::WAIT_LISTING, "Wait Listing"), + (TradeStatus::FUSE, "Fuse"), (TradeStatus::UNKNOWN, "Unknown"), (TradeStatus::NO_REGISTER_QUOTE, "Unknown"), ]; @@ -373,6 +381,37 @@ mod tests { } } + #[test] + fn market_trade_status_codes_match_phase_definition_document() { + let codes = [ + 101, 102, 103, 105, 106, 107, 108, 110, 111, 112, 120, 121, 122, 123, 201, 202, 203, + 204, 206, 207, 1000, 1001, 1002, 1003, 1004, 1005, 1006, 1007, 1008, 1009, 1010, 1011, + 2001, + ]; + + for code in codes { + assert_eq!(TradeStatus::from(code).code(), code, "status code {code}"); + } + } + + #[test] + fn market_trade_status_names_match_phase_definition_document() { + let cases = [ + (123, "Temporary Break"), + (1009, "Not Listed"), + (1010, "Terminated"), + (2001, "Fuse"), + ]; + + for (code, expected) in cases { + assert_eq!( + TradeStatus::from(code).name(), + expected, + "status code {code}" + ); + } + } + #[test] fn market_time_item_uses_market_trade_status_type() { let item = serde_json::from_str::(