完善了一些数据获取的bug

This commit is contained in:
xucheng 2026-01-12 19:20:18 +08:00
parent e786e885e6
commit 282cec080b
19 changed files with 2256 additions and 312 deletions

View File

@ -9,7 +9,7 @@ import websocket
import psycopg2 import psycopg2
import pandas as pd import pandas as pd
from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT from psycopg2.extensions import ISOLATION_LEVEL_AUTOCOMMIT
from datetime import datetime from datetime import datetime, timedelta
from dotenv import load_dotenv from dotenv import load_dotenv
from pathlib import Path from pathlib import Path
import logging import logging
@ -81,7 +81,7 @@ PRICE_CONFIG = {
} }
STOCKCARD_CONFIG = { STOCKCARD_CONFIG = {
"period": 15, "period": 10,
"unit": 100000000 "unit": 100000000
} }
@ -300,6 +300,14 @@ class BloombergClient:
except Exception: except Exception:
conn.rollback() # Should not happen with IF NOT EXISTS but good practice conn.rollback() # Should not happen with IF NOT EXISTS but good practice
# Migrate update_date to TIMESTAMP
try:
cur.execute("ALTER TABLE stockcard ALTER COLUMN update_date TYPE TIMESTAMP USING update_date::timestamp;")
except Exception as e:
# Likely already converted or failed, log but don't crash
logger.info(f"Schema migration note (update_date): {e}")
conn.rollback()
conn.commit() conn.commit()
def save_data(self, data_list): def save_data(self, data_list):
@ -307,6 +315,8 @@ class BloombergClient:
if not data_list: if not data_list:
return return
conn = self._get_db_connection() conn = self._get_db_connection()
if not conn: return if not conn: return
@ -354,7 +364,7 @@ class BloombergClient:
id, id,
ROW_NUMBER() OVER( ROW_NUMBER() OVER(
PARTITION BY company_code, currency, indicator, value_date PARTITION BY company_code, currency, indicator, value_date
ORDER BY update_date DESC ORDER BY update_date DESC, id DESC
) as rn ) as rn
FROM FROM
stockcard stockcard
@ -407,12 +417,28 @@ class BloombergClient:
# If symbol already has Equity, use it. Else append. # If symbol already has Equity, use it. Else append.
if "Equity" in symbol: if "Equity" in symbol:
company_code = symbol company_code = symbol
bucket_code = symbol # Usage for bucket?
# If symbol comes in as '631 HK Equity', we might want to standardize?
# Assuming symbol is correct input.
else: else:
# Special case for China market: use 'CH Equity' instead of 'CN Equity' # Special case for China market: use 'CH Equity' instead of 'CN Equity'
mapped_market = "CH" if market == "CN" else market mapped_market = "CH" if market == "CN" else market
# Canonical Code (Store in DB): Keep explicit zeros if provided in symbol
company_code = f"{symbol} {mapped_market} Equity" company_code = f"{symbol} {mapped_market} Equity"
today_str = datetime.now().strftime('%Y-%m-%d') # Query Ticker (Send to Bloomberg): Handle HK special case
query_ticker = company_code
if market == "HK" or (len(company_code.split()) > 1 and company_code.split()[1] == "HK"):
# Extract number part
parts = company_code.split()
ticker_part = parts[0]
if ticker_part.isdigit():
short_ticker = str(int(ticker_part))
# Reconstruct: 631 HK Equity
query_ticker = f"{short_ticker} {' '.join(parts[1:])}"
today_str = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
logger.info(f"🚀 Starting fetch for: {company_code}") logger.info(f"🚀 Starting fetch for: {company_code}")
if progress_callback: progress_callback("Starting Bloomberg session...", 0) if progress_callback: progress_callback("Starting Bloomberg session...", 0)
@ -438,12 +464,8 @@ if 'bquery' not in globals():
try: try:
self.execute_remote_code(init_code) self.execute_remote_code(init_code)
# 1. Fetch Basic Info
logger.info("Fetching Basic Data...")
if progress_callback: progress_callback("Fetching Company Basic Info...", 10)
basic_data = self._fetch_basic_remote(company_code, "USD")
self.save_data(basic_data)
# 1. Fetch Basic Info
# Determine currency # Determine currency
if force_currency and force_currency != "Auto": if force_currency and force_currency != "Auto":
currency = force_currency currency = force_currency
@ -456,46 +478,71 @@ if 'bquery' not in globals():
elif "HK" in market.upper(): currency = "HKD" elif "HK" in market.upper(): currency = "HKD"
logger.info(f"Using auto-detected currency: {currency}") logger.info(f"Using auto-detected currency: {currency}")
# 2. Fetch Currency Data # 2. Fetch Basic Info
logger.info("Fetching Basic Data...")
if progress_callback: progress_callback("Fetching Company Basic Info...", 10)
try:
basic_data = self._fetch_basic_remote(company_code, currency, query_ticker=query_ticker)
logger.info(f"DEBUG: basic_data before save: {basic_data}")
self.save_data(basic_data)
except Exception as e:
logger.error(f"Error fetching basic data: {e}")
# 3. Fetch Currency Data
logger.info("Fetching Currency Data...") logger.info("Fetching Currency Data...")
if progress_callback: progress_callback(f"正在获取货币指标 ({currency})...", 30) if progress_callback: progress_callback(f"正在获取货币指标 ({currency})...", 30)
curr_data = self._fetch_series_remote(company_code, currency, CURRENCY_CONFIG, "currency") curr_data = []
self.save_data(curr_data) try:
curr_data = self._fetch_series_remote(company_code, currency, CURRENCY_CONFIG, "currency", query_ticker=query_ticker)
self.save_data(curr_data)
except Exception as e:
logger.error(f"Error fetching currency series: {e}")
# 3. Fetch Non-Currency Data # 4. Fetch Non-Currency Data
logger.info("Fetching Non-Currency Data...") logger.info("Fetching Non-Currency Data...")
if progress_callback: progress_callback("正在获取非货币指标...", 50) if progress_callback: progress_callback("正在获取非货币指标...", 50)
non_curr_data = self._fetch_series_remote(company_code, currency, NON_CURRENCY_CONFIG, "non_currency") try:
self.save_data(non_curr_data) non_curr_data = self._fetch_series_remote(company_code, currency, NON_CURRENCY_CONFIG, "non_currency", query_ticker=query_ticker)
self.save_data(non_curr_data)
except Exception as e:
logger.error(f"Error fetching non-currency series: {e}")
# 4. Fetch Price Data (Aligned with Revenue Dates) # 5. Fetch Price Data (Aligned with Revenue Dates)
logger.info("Fetching Price Data (Aligned)...") logger.info("Fetching Price Data (Aligned)...")
if progress_callback: progress_callback("正在获取价格指标...", 70) if progress_callback: progress_callback("正在获取价格指标...", 70)
# Extract Revenue dates # Extract Revenue dates
revenue_dates = [] revenue_dates = []
rev_key = CURRENCY_CONFIG.get("Revenue", "SALES_REV_TURN") if curr_data:
# The saved data uses indicator name from config keys (e.g. "Revenue") for item in curr_data:
# So looking for "Revenue" in saved entries # Check for "Revenue"
if item['indicator'].lower() == "revenue": # Robust case-insensitive check
if item['value_date']:
revenue_dates.append(item['value_date'])
for item in curr_data: # Remove duplicates, sort
# Check for "Revenue" (case insensitive match if needed)
if item['indicator'].lower() == 'revenue':
if item['value_date']:
# Ensure YYYY-MM-DD
revenue_dates.append(item['value_date'])
# Remove specs, duplicates, sort
revenue_dates = sorted(list(set(revenue_dates)), reverse=True) revenue_dates = sorted(list(set(revenue_dates)), reverse=True)
if revenue_dates: if revenue_dates:
logger.info(f"Found {len(revenue_dates)} revenue reporting dates. Fetching aligned price data...") logger.info(f"Found {len(revenue_dates)} revenue reporting dates. Fetching aligned price data...")
price_data = self._fetch_price_by_dates_remote(company_code, currency, revenue_dates) try:
self.save_data(price_data) price_data = self._fetch_price_by_dates_remote(company_code, currency, revenue_dates, query_ticker=query_ticker)
self.save_data(price_data)
except Exception as e:
logger.error(f"Error fetching aligned price data: {e}")
else: else:
logger.warning("No revenue dates found. Falling back to yearly price fetch.") logger.warning("No revenue dates found. Falling back to yearly price fetch (Dec 31).")
price_data = self._fetch_series_remote(company_code, currency, PRICE_CONFIG, "price") # Generate last 10 years Dec 31
self.save_data(price_data) fallback_dates = []
current_year = datetime.now().year
for i in range(1, 11):
fallback_dates.append(f"{current_year - i}-12-31")
try:
price_data = self._fetch_price_by_dates_remote(company_code, currency, fallback_dates, query_ticker=query_ticker)
self.save_data(price_data)
except Exception as e:
logger.error(f"Error fetching fallback price data: {e}")
# 5. Cleanup # 5. Cleanup
if progress_callback: progress_callback("Finalizing data...", 90) if progress_callback: progress_callback("Finalizing data...", 90)
@ -508,74 +555,80 @@ if 'bquery' not in globals():
if progress_callback: progress_callback(f"Error: {e}", 0) if progress_callback: progress_callback(f"Error: {e}", 0)
raise e raise e
def _fetch_basic_remote(self, company_code, currency): def _fetch_basic_remote(self, company_code, currency, query_ticker=None):
"""Generates code to fetch basic data""" """Generates code to fetch basic data"""
target_ticker = query_ticker if query_ticker else company_code
code = f""" code = f"""
def get_basic(): def get_basic():
company = "{company_code}" company = "{company_code}"
query_ticker = "{target_ticker}"
curr = "{currency}" curr = "{currency}"
res_list = [] res_list = []
# 1. BQL query # 1. BDP Query for most fields (except Market Cap)
q = f"for(['{{company}}']) get(name,listing_date,pe_ratio,px_to_book_ratio,cur_mkt_cap(currency={{curr}}),PCT_REVENUE_FROM_FOREIGN_SOURCES)" fields = ["NAME", "PE_RATIO", "PX_TO_BOOK_RATIO", "PCT_REVENUE_FROM_FOREIGN_SOURCES", "DIVIDEND_12_MONTH_YIELD", "EQY_INIT_PO_DT"]
try:
df = bquery.bql(q)
if not df.empty:
def get_val(df, field_name):
if field_name == 'name':
rows = df[df['field'] == 'name']
elif 'cur_mkt_cap' in field_name:
rows = df[df['field'].str.contains('cur_mkt_cap')]
elif 'FOREIGN' in field_name:
rows = df[df['field'].str.contains('FOREIGN')]
else:
rows = df[df['field'] == field_name]
if not rows.empty: try:
val = rows['value'].iloc[0] # Use overrides for currency. Expects list of tuples.
# Handle Timestamp object from remote pandas # Try both CURRENCY (for price) and EQY_FUND_CRNCY (for fundamentals)
if hasattr(val, 'strftime'): df = bquery.bdp([query_ticker], fields, overrides=[('CURRENCY', curr), ('EQY_FUND_CRNCY', curr)])
return val.strftime('%Y-%m-%d')
return str(val) if val is not None else None if not df.empty:
def safe_get(df, col):
if col in df.columns:
val = df[col].iloc[0]
if val is None: return None
if hasattr(val, 'strftime'): return val.strftime('%Y-%m-%d')
return str(val)
return None return None
res_list.append({{"indicator": "company_name", "value": get_val(df, 'name')}}) res_list.append({{"indicator": "company_name", "value": safe_get(df, 'NAME')}})
res_list.append({{"indicator": "pe_ratio", "value": get_val(df, 'pe_ratio')}}) res_list.append({{"indicator": "pe_ratio", "value": safe_get(df, 'PE_RATIO')}})
res_list.append({{"indicator": "pb_ratio", "value": get_val(df, 'pb_ratio')}}) res_list.append({{"indicator": "pb_ratio", "value": safe_get(df, 'PX_TO_BOOK_RATIO')}})
res_list.append({{"indicator": "market_cap", "value": get_val(df, 'cur_mkt_cap')}}) # res_list.append({{"indicator": "market_cap", "value": safe_get(df, 'CUR_MKT_CAP')}}) # Moved to BDH
res_list.append({{"indicator": "Rev_Abroad", "value": get_val(df, 'FOREIGN')}}) res_list.append({{"indicator": "Rev_Abroad", "value": safe_get(df, 'PCT_REVENUE_FROM_FOREIGN_SOURCES')}})
except Exception as e: res_list.append({{"indicator": "dividend_yield", "value": safe_get(df, 'DIVIDEND_12_MONTH_YIELD')}})
print(f"Basic BQL Error: {{e}}") res_list.append({{"indicator": "IPO_date", "value": safe_get(df, 'EQY_INIT_PO_DT')}})
# 2. BDP for IPO and Dividend
try:
did = bquery.bdp([company], ["DIVIDEND_12_MONTH_YIELD"])
if not did.empty and 'DIVIDEND_12_MONTH_YIELD' in did.columns:
res_list.append({{"indicator": "dividend_yield", "value": str(did['DIVIDEND_12_MONTH_YIELD'][0])}})
ipo = bquery.bdp([company], ["EQY_INIT_PO_DT"])
if not ipo.empty and 'EQY_INIT_PO_DT' in ipo.columns:
val = ipo['EQY_INIT_PO_DT'][0]
val_str = str(val)
if hasattr(val, 'strftime'):
val_str = val.strftime('%Y-%m-%d')
res_list.append({{"indicator": "IPO_date", "value": val_str}})
except Exception as e: except Exception as e:
print(f"Basic BDP Error: {{e}}") print(f"Basic BDP Error: {{e}}")
# 2. BDH Query for Market Cap (To enforce Currency)
try:
import datetime
end_date = datetime.datetime.now().strftime('%Y%m%d')
start_date = (datetime.datetime.now() - datetime.timedelta(days=10)).strftime('%Y%m%d')
# Fetch CUR_MKT_CAP via BDH to respect currency option
df_cap = bquery.bdh([query_ticker], ['CUR_MKT_CAP'], start_date=start_date, end_date=end_date, options={{'currency': curr}})
if not df_cap.empty:
# BDH usually returns Market Cap in Millions.
# User simplified requirement: Keep it in Millions.
# Frontend will divide by 100 to get "Yi".
val_millions = df_cap.iloc[-1]['CUR_MKT_CAP']
res_list.append({{"indicator": "market_cap", "value": str(val_millions)}})
except Exception as e:
print(f"Basic BDH Market Cap Error: {{e}}")
# Format result # Format result
final_res = [] final_res = []
today = datetime.now().strftime('%Y-%m-%d')
import datetime
today_dt = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
for item in res_list: for item in res_list:
if item['value']: # Check against None string too if needed
if item['value'] and str(item['value']) != 'None':
final_res.append({{ final_res.append({{
"Company_code": company, "Company_code": company,
"update_date": today, "update_date": today_dt,
"currency": curr, "currency": curr,
"indicator": item['indicator'], "indicator": item['indicator'],
"value": item['value'], "value": item['value'],
"value_date": today "value_date": today_dt
}}) }})
print("JSON_START") print("JSON_START")
@ -586,27 +639,35 @@ get_basic()
""" """
return self._execute_and_parse(code) return self._execute_and_parse(code)
def _fetch_series_remote(self, company_code, currency, config_dict, result_type): def _fetch_series_remote(self, company_code, currency, config_dict, result_type, query_ticker=None):
"""Generates code to fetch series data using BDH""" """Generates code to fetch series data using BDH"""
target_ticker = query_ticker if query_ticker else company_code
config_json = json.dumps(config_dict) config_json = json.dumps(config_dict)
period_years = STOCKCARD_CONFIG['period'] period_years = STOCKCARD_CONFIG['period']
start_year = datetime.now().year - period_years # Calculate start date
start_date = f"{start_year}0101" end_date = datetime.now()
end_date = datetime.now().strftime('%Y%m%d') start_date = end_date - timedelta(days=period_years*365)
# Format dates for BDH (YYYYMMDD)
start_date_str = start_date.strftime('%Y%m%d')
end_date_str = end_date.strftime('%Y%m%d')
# BDH Options
bdh_options = { bdh_options = {
'periodicitySelection': 'YEARLY', "periodicityAdjustment": "FISCAL",
'currency': currency, "periodicitySelection": "YEARLY",
'nonTradingDayFillOption': 'ALL_CALENDAR_DAYS', "currency": currency,
'nonTradingDayFillMethod': 'PREVIOUS_VALUE' # "nonTradingDayFillOption": "NON_TRADING_WEEKDAYS",
# "nonTradingDayFillMethod": "PREVIOUS_VALUE"
} }
bdh_opts_json = json.dumps(bdh_options) bdh_opts_json = json.dumps(bdh_options)
code = f""" code = f"""
def get_series(): def get_series():
company = "{company_code}" company = "{company_code}"
query_ticker = "{target_ticker}"
curr = "{currency}" curr = "{currency}"
config = {config_json} config = {config_json}
@ -617,10 +678,10 @@ def get_series():
try: try:
df = bquery.bdh( df = bquery.bdh(
[company], [query_ticker],
fields, fields,
start_date='{start_date}', start_date='{start_date_str}',
end_date='{end_date}', end_date='{end_date_str}',
options={bdh_opts_json} options={bdh_opts_json}
) )
@ -659,7 +720,7 @@ def get_series():
res_list.append({{ res_list.append({{
"Company_code": company, "Company_code": company,
"update_date": "{datetime.now().strftime('%Y-%m-%d')}", "update_date": "{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}",
"currency": curr, "currency": curr,
"indicator": indicator_name, "indicator": indicator_name,
"value": val_str, "value": val_str,
@ -677,11 +738,12 @@ get_series()
""" """
return self._execute_and_parse(code) return self._execute_and_parse(code)
def _fetch_price_by_dates_remote(self, company_code, currency, dates): def _fetch_price_by_dates_remote(self, company_code, currency, dates, query_ticker=None):
"""Generates code to fetch price/mkt_cap for specific dates""" """Generates code to fetch price/mkt_cap for specific dates"""
if not dates: if not dates:
return [] return []
target_ticker = query_ticker if query_ticker else company_code
dates_json = json.dumps(dates) dates_json = json.dumps(dates)
config_json = json.dumps(PRICE_CONFIG) config_json = json.dumps(PRICE_CONFIG)
@ -695,6 +757,7 @@ get_series()
code = f""" code = f"""
def get_price_by_dates(): def get_price_by_dates():
company = "{company_code}" company = "{company_code}"
query_ticker = "{target_ticker}"
curr = "{currency}" curr = "{currency}"
dates = {dates_json} dates = {dates_json}
config = {config_json} config = {config_json}
@ -708,27 +771,30 @@ def get_price_by_dates():
# d_str is 'YYYY-MM-DD', bdh needs 'YYYYMMDD' # d_str is 'YYYY-MM-DD', bdh needs 'YYYYMMDD'
d_param = d_str.replace('-', '') d_param = d_str.replace('-', '')
try: for mnemonic, indicator_name in mnemonic_map.items():
df = bquery.bdh( field = mnemonic
[company], try:
fields, df = bquery.bdh(
start_date=d_param, [query_ticker],
end_date=d_param, [field],
options={bdh_opts_json} start_date=d_param,
) end_date=d_param,
options={bdh_opts_json}
if not df.empty: )
for _, row in df.iterrows():
# value_date is d_str
for mnemonic, indicator_name in mnemonic_map.items():
col_name = mnemonic
# bdh columns might be tuple or just string depending on request
# usually 'PX_LAST'
if not df.empty:
for _, row in df.iterrows():
val = None val = None
if col_name in df.columns: if field in df.columns:
val = row[col_name] val = row[field]
elif field in row:
val = row[field]
else:
# Try case insensitive
for c in df.columns:
if c.upper() == field:
val = row[c]
break
if pd.isna(val) or val is None: if pd.isna(val) or val is None:
continue continue
@ -737,14 +803,16 @@ def get_price_by_dates():
res_list.append({{ res_list.append({{
"Company_code": company, "Company_code": company,
"update_date": "{datetime.now().strftime('%Y-%m-%d')}", "update_date": "{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}",
"currency": curr, "currency": curr,
"indicator": indicator_name, "indicator": indicator_name,
"value": val_str, "value": val_str,
"value_date": d_str "value_date": d_str
}}) }})
except Exception as e:
print(f"Error fetching price for {{d_str}}: {{e}}") except Exception as e:
# print(f"BDH Error for {{field}}: {{e}}")
pass
print("JSON_START") print("JSON_START")
print(json.dumps(res_list)) print(json.dumps(res_list))
@ -758,7 +826,9 @@ get_price_by_dates()
"""Execute code and parse [JSON_START]...[JSON_END]""" """Execute code and parse [JSON_START]...[JSON_END]"""
raw_output_list = self.execute_remote_code(code) raw_output_list = self.execute_remote_code(code)
raw_output = "".join(raw_output_list) if isinstance(raw_output_list, list) else str(raw_output_list) raw_output = "".join(raw_output_list) if isinstance(raw_output_list, list) else str(raw_output_list)
# logger.debug(f"Remote execution returned {len(raw_output)} chars.") # Optional debug # Always log raw output first few chars for debug
logger.info(f"REMOTE RAW OUTPUT: {raw_output[:1000]}")
# Actually let's log everything if it fails to find JSON
# Simple parser # Simple parser
try: try:
@ -771,7 +841,7 @@ get_price_by_dates()
logger.info(f"✅ Parsed {len(data) if isinstance(data, list) else 1} items from remote.") logger.info(f"✅ Parsed {len(data) if isinstance(data, list) else 1} items from remote.")
return data return data
else: else:
logger.warning(f"⚠️ No JSON output found in remote response.") logger.warning(f"⚠️ No JSON output found in remote response. Raw: {raw_output}")
return [] return []
except Exception as e: except Exception as e:
logger.error(f"❌ Error parsing JSON from remote: {e}") logger.error(f"❌ Error parsing JSON from remote: {e}")

View File

@ -58,8 +58,9 @@ async def get_bloomberg_data(
# 2. 获取该公司的所有数据 # 2. 获取该公司的所有数据
# schema: indicator, value, value_date (作为报告期) # schema: indicator, value, value_date (作为报告期)
# Added update_date
query = text(""" query = text("""
SELECT indicator, value, value_date, currency SELECT indicator, value, value_date, currency, update_date
FROM stockcard FROM stockcard
WHERE Company_code = :code WHERE Company_code = :code
""") """)
@ -73,11 +74,16 @@ async def get_bloomberg_data(
val = row.value val = row.value
v_date = row.value_date v_date = row.value_date
curr = row.currency curr = row.currency
u_date = row.update_date
if not v_date: if not v_date:
continue continue
date_str = v_date.isoformat() if hasattr(v_date, 'isoformat') else str(v_date) date_str = v_date.isoformat() if hasattr(v_date, 'isoformat') else str(v_date)
# Handle update_date formatting
update_date_str = ""
if u_date:
update_date_str = u_date.isoformat() if hasattr(u_date, 'isoformat') else str(u_date)
# Key by (date, currency) to support multiple currencies for the same date # Key by (date, currency) to support multiple currencies for the same date
unique_key = f"{date_str}_{curr}" unique_key = f"{date_str}_{curr}"
@ -85,9 +91,14 @@ async def get_bloomberg_data(
if unique_key not in data_by_date: if unique_key not in data_by_date:
data_by_date[unique_key] = { data_by_date[unique_key] = {
"end_date": date_str, "end_date": date_str,
"currency": curr "currency": curr,
"update_date": ""
} }
# Update the group's update_date if we find a newer one in this batch
if update_date_str > data_by_date[unique_key]["update_date"]:
data_by_date[unique_key]["update_date"] = update_date_str
# Normalize key to match frontend expectation (mostly lowercase) # Normalize key to match frontend expectation (mostly lowercase)
# e.g. "ROE" -> "roe", "PE" -> "pe" # e.g. "ROE" -> "roe", "PE" -> "pe"
norm_indicator = indicator.lower() norm_indicator = indicator.lower()

70
backend/debug_bdh.py Normal file
View File

@ -0,0 +1,70 @@
import sys
import os
import time
import logging
# Ensure we can import from backend
sys.path.append(os.path.join(os.getcwd(), 'backend'))
# Setup logging
logging.basicConfig(level=logging.INFO)
from app.clients.bloomberg_client import BloombergClient
def test_bdh_currency():
print("Initializing BloombergClient...")
client = BloombergClient()
ticker = "6301 JP Equity"
code = """
import sys
import datetime
try:
if 'bquery' not in globals():
import bquery
except ImportError:
pass
ticker = "{ticker}"
fields = ["CUR_MKT_CAP", "PX_LAST"]
print(f"--- BDH Currency Test for {{ticker}} ---")
def get_bdh_val(curr, desc):
try:
# BDH request for last 5 days to ensure we hit a trading day
end_date = datetime.datetime.now().strftime('%Y%m%d')
start_date = (datetime.datetime.now() - datetime.timedelta(days=10)).strftime('%Y%m%d')
# Pass currency in options
df = bquery.bdh([ticker], fields, start_date=start_date, end_date=end_date, options={{'currency': curr}})
if not df.empty:
print(f"--- {{desc}} (Currency: {{curr}}) ---")
# Get last row
last_row = df.iloc[-1]
for col in df.columns:
print(f" {{col}}: {{last_row[col]}}")
else:
print(f"{{desc}} Empty")
except Exception as e:
print(f"{{desc}} Error: {{e}}")
# 1. JPY
get_bdh_val('JPY', "BDH_JPY")
# 2. USD
get_bdh_val('USD', "BDH_USD")
"""
formatted_code = code.format(ticker=ticker)
print(f"Executing remote logic for {ticker}...")
output = client.execute_remote_code(formatted_code)
print("Remote Output:")
print(output)
if __name__ == "__main__":
test_bdh_currency()

View File

@ -0,0 +1,67 @@
import sys
import os
import time
import logging
# Ensure we can import from backend
sys.path.append(os.path.join(os.getcwd(), 'backend'))
# Setup logging
logging.basicConfig(level=logging.INFO)
from app.clients.bloomberg_client import BloombergClient
def test_bdp_options_injection():
print("Initializing BloombergClient...")
client = BloombergClient()
ticker = "6301 JP Equity"
code = """
import sys
try:
if 'bquery' not in globals():
import bquery
except ImportError:
pass
ticker = "{ticker}"
fields = ["CUR_MKT_CAP", "PX_LAST"]
print(f"--- Option Injection Test for {{ticker}} ---")
def get_val_via_options(custom_overrides, desc):
try:
# Pass overrides=None, pass custom overrides via options
# Escape braces for format string by doubling them
df = bquery.bdp([ticker], fields, overrides=None, options={{'overrides': custom_overrides}})
if not df.empty:
print(f"--- {{desc}} ---")
for col in df.columns:
print(f" {{col}}: {{df.iloc[0][col]}}")
print(f" Sent: {{custom_overrides}}")
else:
print(f"{{desc}} Empty")
except Exception as e:
print(f"{{desc}} Error: {{e}}")
# 1. Direct fieldId (No wrapper)
get_val_via_options([{{'fieldId': 'CURRENCY', 'value': 'USD'}}], "Try1_Direct_Dict")
# 2. Wrapped in 'overrides' (Same as current impl)
get_val_via_options([{{'overrides': {{'fieldId': 'CURRENCY', 'value': 'USD'}}}}], "Try2_Wrapped_Overrides")
# 3. Wrapped in 'override' (Singular)
get_val_via_options([{{'override': {{'fieldId': 'CURRENCY', 'value': 'USD'}}}}], "Try3_Wrapped_Override")
"""
formatted_code = code.format(ticker=ticker)
print(f"Executing remote logic for {ticker}...")
output = client.execute_remote_code(formatted_code)
print("Remote Output:")
print(output)
if __name__ == "__main__":
test_bdp_options_injection()

View File

@ -0,0 +1,94 @@
import asyncio
from app.clients.bloomberg_client import BloombergClient, CURRENCY_CONFIG
async def run():
client = BloombergClient()
company = "2503 JP Equity"
# Simulate fetch of currency data (which includes Revenue)
# CURRENCY_CONFIG key "Revenue" is "SALES_REV_TURN"
print(f"Debugging Revenue Dates for {company} (CNY)...")
# We'll use the exact simulating logic of _fetch_series_remote but print the dates
config = {"Revenue": CURRENCY_CONFIG["Revenue"]}
# Force CNY
currency = "CNY"
# Generate the code that _fetch_series_remote generates
# We need to replicate the remote code construction roughly or call execute_remote_code
import json
from datetime import datetime
STOCKCARD_CONFIG = { "period": 10 }
period_years = STOCKCARD_CONFIG['period']
start_year = datetime.now().year - period_years
start_date = f"{start_year}0101"
end_date = datetime.now().strftime('%Y%m%d')
bdh_options = {
'periodicitySelection': 'YEARLY',
'currency': currency,
'nonTradingDayFillOption': 'ALL_CALENDAR_DAYS',
'nonTradingDayFillMethod': 'PREVIOUS_VALUE'
}
config_json = json.dumps(config)
bdh_opts_json = json.dumps(bdh_options)
remote_code = f"""
def debug_series():
company = "{company}"
curr = "{currency}"
config = {config_json}
mnemonic_map = {{v.upper(): k for k, v in config.items()}}
fields = list(mnemonic_map.keys())
try:
df = bquery.bdh(
[company],
fields,
start_date='{start_date}',
end_date='{end_date}',
options={bdh_opts_json}
)
print(f"--- Raw Revenue Data (CNY) ---")
if not df.empty:
print(df)
revenue_dates = []
for _, row in df.iterrows():
# Extract date
date_val = None
if 'date' in df.columns: date_val = row['date']
elif 'DATE' in df.columns: date_val = row['DATE']
if date_val:
d_str = str(date_val)[:10]
# Check for value
val = None
if fields[0] in row: val = row[fields[0]]
elif fields[0] in df.columns: val = row[fields[0]]
if val is not None:
revenue_dates.append(d_str)
print(f"\\nExtracted Revenue Dates: {{sorted(revenue_dates, reverse=True)}}")
else:
print("DataFrame is empty.")
except Exception as e:
print(f"Error: {{e}}")
debug_series()
"""
result = client.execute_remote_code(remote_code)
print(result)
if __name__ == "__main__":
asyncio.run(run())

42
backend/inspect_db.py Normal file
View File

@ -0,0 +1,42 @@
import os
import psycopg2
from dotenv import load_dotenv
load_dotenv()
def inspect_schema():
db_host = os.getenv("DB_HOST", "192.168.3.195")
db_user = os.getenv("DB_USER", "value")
db_pass = os.getenv("DB_PASSWORD", "Value609!")
db_name = os.getenv("DB_NAME", "fa3")
db_port = os.getenv("DB_PORT", "5432")
try:
conn = psycopg2.connect(
host=db_host, user=db_user, password=db_pass, dbname=db_name, port=db_port
)
cur = conn.cursor()
print("--- Table Columns ---")
cur.execute("""
SELECT column_name, data_type
FROM information_schema.columns
WHERE table_name = 'stockcard';
""")
rows = cur.fetchall()
for row in rows:
print(f"{row[0]}: {row[1]}")
print("\n--- Recent Records update_date ---")
cur.execute("SELECT update_date FROM stockcard ORDER BY id DESC LIMIT 5")
rows = cur.fetchall()
for row in rows:
print(f"{row[0]} (Type: {type(row[0])})")
conn.close()
except Exception as e:
print(f"Error: {e}")
if __name__ == "__main__":
inspect_schema()

View File

@ -0,0 +1,39 @@
import os
import psycopg2
import logging
from datetime import datetime
# Config logging
logging.basicConfig(level=logging.INFO)
def inspect_db():
db_host = os.getenv("DB_HOST", "192.168.3.195")
db_user = os.getenv("DB_USER", "value")
db_pass = os.getenv("DB_PASSWORD", "Value609!")
db_name = os.getenv("DB_NAME", "fa3")
conn = psycopg2.connect(
host=db_host, user=db_user, password=db_pass, dbname=db_name
)
with conn.cursor() as cur:
# Check basic data market cap
cur.execute("""
SELECT update_date, indicator, value, value_date, currency, source
FROM stockcard
WHERE Company_code LIKE '6301 JP%'
AND (indicator = 'market_cap' OR indicator = 'Market_Cap')
ORDER BY update_date DESC, value_date DESC
LIMIT 20;
""")
rows = cur.fetchall()
print(f"{'Update Date':<20} | {'Indicator':<15} | {'Currency':<5} | {'Value Date':<12} | {'Value (Raw)':<20} | {'Source'}")
print("-" * 100)
for row in rows:
print(f"{str(row[0]):<20} | {row[1]:<15} | {row[4]:<5} | {str(row[3]):<12} | {row[2]:<20} | {row[5]}")
conn.close()
if __name__ == "__main__":
inspect_db()

View File

@ -1556,3 +1556,982 @@ sqlalchemy.exc.ProgrammingError: (sqlalchemy.dialects.postgresql.asyncpg.Program
2026-01-12 09:31:26,489 - app.clients.bloomberg_client - INFO - ✅ Completed processing for 2503 JP Equity 2026-01-12 09:31:26,489 - app.clients.bloomberg_client - INFO - ✅ Completed processing for 2503 JP Equity
2026-01-12 09:31:26,490 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=54, Msg=Bloomberg data sync complete, Progress=90% 2026-01-12 09:31:26,490 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=54, Msg=Bloomberg data sync complete, Progress=90%
2026-01-12 09:31:26,791 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=54, Msg=Bloomberg 数据同步完成, Progress=100% 2026-01-12 09:31:26,791 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=54, Msg=Bloomberg 数据同步完成, Progress=100%
2026-01-12 10:15:52,800 - app.main - INFO - 🔍 [搜索] 开始搜索股票: 三一国际
2026-01-12 10:15:53,105 - app.main - INFO - 🤖 [搜索-LLM] 调用 gemini-2.5-flash 进行股票搜索
2026-01-12 10:15:53,112 - google_genai.models - INFO - AFC is enabled with max remote calls: 10.
2026-01-12 10:15:57,833 - httpx - INFO - HTTP Request: POST https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent "HTTP/1.1 200 OK"
2026-01-12 10:15:57,856 - app.main - INFO - ✅ [搜索-LLM] 模型响应完成, 耗时: 4.75秒, Tokens: prompt=166, completion=78, total=244
2026-01-12 10:15:57,857 - app.main - INFO - ✅ [搜索] 搜索完成, 找到 1 个结果, 总耗时: 5.05秒
2026-01-12 10:16:22,607 - app.main - INFO - 🔍 [搜索] 开始搜索股票: 三一国际
2026-01-12 10:16:22,609 - app.main - INFO - 🤖 [搜索-LLM] 调用 gemini-2.5-flash 进行股票搜索
2026-01-12 10:16:22,611 - google_genai.models - INFO - AFC is enabled with max remote calls: 10.
2026-01-12 10:16:26,693 - httpx - INFO - HTTP Request: POST https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent "HTTP/1.1 200 OK"
2026-01-12 10:16:26,716 - app.main - INFO - ✅ [搜索-LLM] 模型响应完成, 耗时: 4.11秒, Tokens: prompt=166, completion=78, total=244
2026-01-12 10:16:26,717 - app.main - INFO - ✅ [搜索] 搜索完成, 找到 1 个结果, 总耗时: 4.11秒
2026-01-12 10:39:45,586 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=55, Msg=正在初始化数据获取..., Progress=0%
2026-01-12 10:39:46,580 - app.clients.bloomberg_client - INFO - Connecting to Jupyter at http://192.168.3.161:8888...
2026-01-12 10:39:47,135 - app.clients.bloomberg_client - INFO - ✅ Authentication successful.
2026-01-12 10:39:47,166 - app.clients.bloomberg_client - INFO - ✅ Found existing kernel: bc27f3b1-b028-434a-99fa-c1cad4495a87 (remote_env)
2026-01-12 10:39:47,228 - app.clients.bloomberg_client - INFO - ✅ WebSocket connected.
2026-01-12 10:39:47,228 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=55, Msg=数据源连接成功, Progress=10%
2026-01-12 10:39:47,502 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=55, Msg=正在连接 Bloomberg 终端..., Progress=20%
2026-01-12 10:39:47,936 - app.clients.bloomberg_client - INFO - 🚀 Starting fetch for: SAB VN Equity
2026-01-12 10:39:47,937 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=55, Msg=Starting Bloomberg session..., Progress=20%
2026-01-12 10:39:48,418 - app.clients.bloomberg_client - INFO - Fetching Basic Data...
2026-01-12 10:39:48,418 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=55, Msg=Fetching Company Basic Info..., Progress=27%
2026-01-12 10:39:50,974 - app.clients.bloomberg_client - INFO - ✅ Parsed 2 items from remote.
2026-01-12 10:39:51,644 - app.clients.bloomberg_client - INFO - ✅ Saved 2 records to database.
2026-01-12 10:39:51,645 - app.clients.bloomberg_client - INFO - Using forced currency: CNY
2026-01-12 10:39:51,645 - app.clients.bloomberg_client - INFO - Fetching Currency Data...
2026-01-12 10:39:51,646 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=55, Msg=正在获取货币指标 (CNY)..., Progress=41%
2026-01-12 10:39:53,556 - app.clients.bloomberg_client - INFO - ✅ Parsed 275 items from remote.
2026-01-12 10:40:05,191 - app.clients.bloomberg_client - INFO - ✅ Saved 275 records to database.
2026-01-12 10:40:05,201 - app.clients.bloomberg_client - INFO - Fetching Non-Currency Data...
2026-01-12 10:40:05,201 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=55, Msg=正在获取非货币指标..., Progress=55%
2026-01-12 10:40:06,376 - app.clients.bloomberg_client - INFO - ✅ Parsed 290 items from remote.
2026-01-12 10:40:18,886 - app.clients.bloomberg_client - INFO - ✅ Saved 290 records to database.
2026-01-12 10:40:18,888 - app.clients.bloomberg_client - INFO - Fetching Price Data (Aligned)...
2026-01-12 10:40:18,888 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=55, Msg=正在获取价格指标..., Progress=69%
2026-01-12 10:40:19,463 - app.clients.bloomberg_client - INFO - Found 11 revenue reporting dates. Fetching aligned price data...
2026-01-12 10:40:24,699 - app.clients.bloomberg_client - INFO - ✅ Parsed 27 items from remote.
2026-01-12 10:40:26,363 - app.clients.bloomberg_client - INFO - ✅ Saved 27 records to database.
2026-01-12 10:40:26,366 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=55, Msg=Finalizing data..., Progress=82%
2026-01-12 10:40:27,693 - app.clients.bloomberg_client - INFO - ✅ Cleanup and View Refresh completed.
2026-01-12 10:40:27,694 - app.clients.bloomberg_client - INFO - ✅ Completed processing for SAB VN Equity
2026-01-12 10:40:27,694 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=55, Msg=Bloomberg data sync complete, Progress=90%
2026-01-12 10:40:28,421 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=55, Msg=Bloomberg 数据同步完成, Progress=100%
2026-01-12 10:42:39,579 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=56, Msg=正在初始化数据获取..., Progress=0%
2026-01-12 10:42:39,887 - app.clients.bloomberg_client - INFO - Connecting to Jupyter at http://192.168.3.161:8888...
2026-01-12 10:42:40,132 - app.clients.bloomberg_client - INFO - ✅ Authentication successful.
2026-01-12 10:42:40,160 - app.clients.bloomberg_client - INFO - ✅ Found existing kernel: bc27f3b1-b028-434a-99fa-c1cad4495a87 (remote_env)
2026-01-12 10:42:41,230 - app.clients.bloomberg_client - INFO - ✅ WebSocket connected.
2026-01-12 10:42:41,231 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=56, Msg=数据源连接成功, Progress=10%
2026-01-12 10:42:42,048 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=56, Msg=正在连接 Bloomberg 终端..., Progress=20%
2026-01-12 10:42:42,308 - app.clients.bloomberg_client - INFO - 🚀 Starting fetch for: SAB VN Equity
2026-01-12 10:42:42,309 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=56, Msg=Starting Bloomberg session..., Progress=20%
2026-01-12 10:42:42,624 - app.clients.bloomberg_client - INFO - Fetching Basic Data...
2026-01-12 10:42:42,625 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=56, Msg=Fetching Company Basic Info..., Progress=27%
2026-01-12 10:42:43,914 - app.clients.bloomberg_client - INFO - ✅ Parsed 2 items from remote.
2026-01-12 10:42:44,298 - app.clients.bloomberg_client - INFO - ✅ Saved 2 records to database.
2026-01-12 10:42:44,299 - app.clients.bloomberg_client - INFO - Using forced currency: USD
2026-01-12 10:42:44,299 - app.clients.bloomberg_client - INFO - Fetching Currency Data...
2026-01-12 10:42:44,299 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=56, Msg=正在获取货币指标 (USD)..., Progress=41%
2026-01-12 10:42:45,638 - app.clients.bloomberg_client - INFO - ✅ Parsed 275 items from remote.
2026-01-12 10:42:59,116 - app.clients.bloomberg_client - INFO - ✅ Saved 275 records to database.
2026-01-12 10:42:59,117 - app.clients.bloomberg_client - INFO - Fetching Non-Currency Data...
2026-01-12 10:42:59,118 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=56, Msg=正在获取非货币指标..., Progress=55%
2026-01-12 10:43:00,410 - app.clients.bloomberg_client - INFO - ✅ Parsed 290 items from remote.
2026-01-12 10:43:13,907 - app.clients.bloomberg_client - INFO - ✅ Saved 290 records to database.
2026-01-12 10:43:13,908 - app.clients.bloomberg_client - INFO - Fetching Price Data (Aligned)...
2026-01-12 10:43:13,909 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=56, Msg=正在获取价格指标..., Progress=69%
2026-01-12 10:43:14,174 - app.clients.bloomberg_client - INFO - Found 11 revenue reporting dates. Fetching aligned price data...
2026-01-12 10:43:19,382 - app.clients.bloomberg_client - INFO - ✅ Parsed 27 items from remote.
2026-01-12 10:43:20,821 - app.clients.bloomberg_client - INFO - ✅ Saved 27 records to database.
2026-01-12 10:43:20,821 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=56, Msg=Finalizing data..., Progress=82%
2026-01-12 10:43:21,609 - app.clients.bloomberg_client - INFO - ✅ Cleanup and View Refresh completed.
2026-01-12 10:43:21,609 - app.clients.bloomberg_client - INFO - ✅ Completed processing for SAB VN Equity
2026-01-12 10:43:21,609 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=56, Msg=Bloomberg data sync complete, Progress=90%
2026-01-12 10:43:21,873 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=56, Msg=Bloomberg 数据同步完成, Progress=100%
2026-01-12 10:58:49,794 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=57, Msg=正在初始化数据获取..., Progress=0%
2026-01-12 10:58:50,395 - app.clients.bloomberg_client - INFO - Connecting to Jupyter at http://192.168.3.161:8888...
2026-01-12 10:58:50,649 - app.clients.bloomberg_client - INFO - ✅ Authentication successful.
2026-01-12 10:58:50,676 - app.clients.bloomberg_client - INFO - ✅ Found existing kernel: bc27f3b1-b028-434a-99fa-c1cad4495a87 (remote_env)
2026-01-12 10:58:50,734 - app.clients.bloomberg_client - INFO - ✅ WebSocket connected.
2026-01-12 10:58:50,734 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=57, Msg=数据源连接成功, Progress=10%
2026-01-12 10:58:50,996 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=57, Msg=正在连接 Bloomberg 终端..., Progress=20%
2026-01-12 10:58:51,414 - app.clients.bloomberg_client - INFO - 🚀 Starting fetch for: 2503 JP Equity
2026-01-12 10:58:51,414 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=57, Msg=Starting Bloomberg session..., Progress=20%
2026-01-12 10:58:51,864 - app.clients.bloomberg_client - INFO - Using forced currency: CNY
2026-01-12 10:58:51,864 - app.clients.bloomberg_client - INFO - Fetching Basic Data...
2026-01-12 10:58:51,864 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=57, Msg=Fetching Company Basic Info..., Progress=27%
2026-01-12 10:58:53,027 - app.clients.bloomberg_client - INFO - ✅ Parsed 2 items from remote.
2026-01-12 10:58:53,435 - app.clients.bloomberg_client - INFO - ✅ Saved 2 records to database.
2026-01-12 10:58:53,435 - app.clients.bloomberg_client - INFO - Fetching Currency Data...
2026-01-12 10:58:53,436 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=57, Msg=正在获取货币指标 (CNY)..., Progress=41%
2026-01-12 10:58:54,938 - app.clients.bloomberg_client - INFO - ✅ Parsed 215 items from remote.
2026-01-12 10:59:04,571 - app.clients.bloomberg_client - INFO - ✅ Saved 215 records to database.
2026-01-12 10:59:04,583 - app.clients.bloomberg_client - INFO - Fetching Non-Currency Data...
2026-01-12 10:59:04,584 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=57, Msg=正在获取非货币指标..., Progress=55%
2026-01-12 10:59:05,645 - app.clients.bloomberg_client - INFO - ✅ Parsed 260 items from remote.
2026-01-12 10:59:16,477 - app.clients.bloomberg_client - INFO - ✅ Saved 260 records to database.
2026-01-12 10:59:16,477 - app.clients.bloomberg_client - INFO - Fetching Price Data (Aligned)...
2026-01-12 10:59:16,478 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=57, Msg=正在获取价格指标..., Progress=69%
2026-01-12 10:59:17,032 - app.clients.bloomberg_client - INFO - Found 9 revenue reporting dates. Fetching aligned price data...
2026-01-12 10:59:20,896 - app.clients.bloomberg_client - INFO - ✅ Parsed 27 items from remote.
2026-01-12 10:59:22,712 - app.clients.bloomberg_client - INFO - ✅ Saved 27 records to database.
2026-01-12 10:59:22,713 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=57, Msg=Finalizing data..., Progress=82%
2026-01-12 10:59:23,316 - app.clients.bloomberg_client - INFO - ✅ Cleanup and View Refresh completed.
2026-01-12 10:59:23,317 - app.clients.bloomberg_client - INFO - ✅ Completed processing for 2503 JP Equity
2026-01-12 10:59:23,317 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=57, Msg=Bloomberg data sync complete, Progress=90%
2026-01-12 10:59:23,593 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=57, Msg=Bloomberg 数据同步完成, Progress=100%
2026-01-12 11:00:00,129 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=58, Msg=正在初始化数据获取..., Progress=0%
2026-01-12 11:00:00,711 - app.clients.bloomberg_client - INFO - Connecting to Jupyter at http://192.168.3.161:8888...
2026-01-12 11:00:01,085 - app.clients.bloomberg_client - INFO - ✅ Authentication successful.
2026-01-12 11:00:01,113 - app.clients.bloomberg_client - INFO - ✅ Found existing kernel: bc27f3b1-b028-434a-99fa-c1cad4495a87 (remote_env)
2026-01-12 11:00:01,164 - app.clients.bloomberg_client - INFO - ✅ WebSocket connected.
2026-01-12 11:00:01,165 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=58, Msg=数据源连接成功, Progress=10%
2026-01-12 11:00:01,426 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=58, Msg=正在连接 Bloomberg 终端..., Progress=20%
2026-01-12 11:00:01,773 - app.clients.bloomberg_client - INFO - 🚀 Starting fetch for: 2503 JP Equity
2026-01-12 11:00:01,773 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=58, Msg=Starting Bloomberg session..., Progress=20%
2026-01-12 11:00:02,544 - app.clients.bloomberg_client - INFO - Using forced currency: USD
2026-01-12 11:00:02,545 - app.clients.bloomberg_client - INFO - Fetching Basic Data...
2026-01-12 11:00:02,545 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=58, Msg=Fetching Company Basic Info..., Progress=27%
2026-01-12 11:00:03,720 - app.clients.bloomberg_client - INFO - ✅ Parsed 2 items from remote.
2026-01-12 11:00:04,112 - app.clients.bloomberg_client - INFO - ✅ Saved 2 records to database.
2026-01-12 11:00:04,113 - app.clients.bloomberg_client - INFO - Fetching Currency Data...
2026-01-12 11:00:04,113 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=58, Msg=正在获取货币指标 (USD)..., Progress=41%
2026-01-12 11:00:05,964 - app.clients.bloomberg_client - INFO - ✅ Parsed 215 items from remote.
2026-01-12 11:00:16,994 - app.clients.bloomberg_client - INFO - ✅ Saved 215 records to database.
2026-01-12 11:00:16,996 - app.clients.bloomberg_client - INFO - Fetching Non-Currency Data...
2026-01-12 11:00:16,996 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=58, Msg=正在获取非货币指标..., Progress=55%
2026-01-12 11:00:18,214 - app.clients.bloomberg_client - INFO - ✅ Parsed 260 items from remote.
2026-01-12 11:00:31,167 - app.clients.bloomberg_client - INFO - ✅ Saved 260 records to database.
2026-01-12 11:00:31,169 - app.clients.bloomberg_client - INFO - Fetching Price Data (Aligned)...
2026-01-12 11:00:31,170 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=58, Msg=正在获取价格指标..., Progress=69%
2026-01-12 11:00:32,027 - app.clients.bloomberg_client - INFO - Found 9 revenue reporting dates. Fetching aligned price data...
2026-01-12 11:00:36,241 - app.clients.bloomberg_client - INFO - ✅ Parsed 27 items from remote.
2026-01-12 11:00:38,065 - app.clients.bloomberg_client - INFO - ✅ Saved 27 records to database.
2026-01-12 11:00:38,066 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=58, Msg=Finalizing data..., Progress=82%
2026-01-12 11:00:39,407 - app.clients.bloomberg_client - INFO - ✅ Cleanup and View Refresh completed.
2026-01-12 11:00:39,407 - app.clients.bloomberg_client - INFO - ✅ Completed processing for 2503 JP Equity
2026-01-12 11:00:39,408 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=58, Msg=Bloomberg data sync complete, Progress=90%
2026-01-12 11:00:39,748 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=58, Msg=Bloomberg 数据同步完成, Progress=100%
2026-01-12 11:44:44,232 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=59, Msg=正在初始化数据获取..., Progress=0%
2026-01-12 11:44:44,905 - app.clients.bloomberg_client - INFO - Connecting to Jupyter at http://192.168.3.161:8888...
2026-01-12 11:44:46,453 - app.clients.bloomberg_client - INFO - ✅ Authentication successful.
2026-01-12 11:44:46,649 - app.clients.bloomberg_client - INFO - ✅ Found existing kernel: bc27f3b1-b028-434a-99fa-c1cad4495a87 (remote_env)
2026-01-12 11:44:47,699 - app.clients.bloomberg_client - INFO - ✅ WebSocket connected.
2026-01-12 11:44:47,700 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=59, Msg=数据源连接成功, Progress=10%
2026-01-12 11:44:49,420 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=59, Msg=正在连接 Bloomberg 终端..., Progress=20%
2026-01-12 11:44:49,979 - app.clients.bloomberg_client - INFO - 🚀 Starting fetch for: 2503 JP Equity
2026-01-12 11:44:49,979 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=59, Msg=Starting Bloomberg session..., Progress=20%
2026-01-12 11:44:50,331 - app.clients.bloomberg_client - INFO - Using forced currency: CNY
2026-01-12 11:44:50,331 - app.clients.bloomberg_client - INFO - Fetching Basic Data...
2026-01-12 11:44:50,331 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=59, Msg=Fetching Company Basic Info..., Progress=27%
2026-01-12 11:44:52,345 - app.clients.bloomberg_client - INFO - ✅ Parsed 2 items from remote.
2026-01-12 11:44:53,037 - app.clients.bloomberg_client - INFO - ✅ Saved 2 records to database.
2026-01-12 11:44:53,038 - app.clients.bloomberg_client - INFO - Fetching Currency Data...
2026-01-12 11:44:53,038 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=59, Msg=正在获取货币指标 (CNY)..., Progress=41%
2026-01-12 11:44:54,522 - app.clients.bloomberg_client - INFO - ✅ Parsed 215 items from remote.
2026-01-12 11:45:08,541 - app.clients.bloomberg_client - INFO - ✅ Saved 215 records to database.
2026-01-12 11:45:08,543 - app.clients.bloomberg_client - INFO - Fetching Non-Currency Data...
2026-01-12 11:45:08,543 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=59, Msg=正在获取非货币指标..., Progress=55%
2026-01-12 11:45:09,996 - app.clients.bloomberg_client - INFO - ✅ Parsed 260 items from remote.
2026-01-12 11:45:25,647 - app.clients.bloomberg_client - INFO - ✅ Saved 260 records to database.
2026-01-12 11:45:25,649 - app.clients.bloomberg_client - INFO - Fetching Price Data (Aligned)...
2026-01-12 11:45:25,649 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=59, Msg=正在获取价格指标..., Progress=69%
2026-01-12 11:45:26,793 - app.clients.bloomberg_client - INFO - Found 9 revenue reporting dates. Fetching aligned price data...
2026-01-12 11:45:38,250 - app.clients.bloomberg_client - INFO - ✅ Parsed 27 items from remote.
2026-01-12 11:45:40,155 - app.clients.bloomberg_client - INFO - ✅ Saved 27 records to database.
2026-01-12 11:45:40,156 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=59, Msg=Finalizing data..., Progress=82%
2026-01-12 11:45:40,960 - app.clients.bloomberg_client - INFO - ✅ Cleanup and View Refresh completed.
2026-01-12 11:45:40,960 - app.clients.bloomberg_client - INFO - ✅ Completed processing for 2503 JP Equity
2026-01-12 11:45:40,961 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=59, Msg=Bloomberg data sync complete, Progress=90%
2026-01-12 11:45:41,250 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=59, Msg=Bloomberg 数据同步完成, Progress=100%
2026-01-12 11:46:08,013 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=60, Msg=正在初始化数据获取..., Progress=0%
2026-01-12 11:46:09,230 - app.clients.bloomberg_client - INFO - Connecting to Jupyter at http://192.168.3.161:8888...
2026-01-12 11:46:09,490 - app.clients.bloomberg_client - INFO - ✅ Authentication successful.
2026-01-12 11:46:09,518 - app.clients.bloomberg_client - INFO - ✅ Found existing kernel: bc27f3b1-b028-434a-99fa-c1cad4495a87 (remote_env)
2026-01-12 11:46:10,578 - app.clients.bloomberg_client - INFO - ✅ WebSocket connected.
2026-01-12 11:46:10,579 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=60, Msg=数据源连接成功, Progress=10%
2026-01-12 11:46:10,856 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=60, Msg=正在连接 Bloomberg 终端..., Progress=20%
2026-01-12 11:46:11,445 - app.clients.bloomberg_client - INFO - 🚀 Starting fetch for: 2503 JP Equity
2026-01-12 11:46:11,446 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=60, Msg=Starting Bloomberg session..., Progress=20%
2026-01-12 11:46:12,525 - app.clients.bloomberg_client - INFO - Using forced currency: USD
2026-01-12 11:46:12,525 - app.clients.bloomberg_client - INFO - Fetching Basic Data...
2026-01-12 11:46:12,525 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=60, Msg=Fetching Company Basic Info..., Progress=27%
2026-01-12 11:46:14,513 - app.clients.bloomberg_client - INFO - ✅ Parsed 2 items from remote.
2026-01-12 11:46:15,921 - app.clients.bloomberg_client - INFO - ✅ Saved 2 records to database.
2026-01-12 11:46:15,922 - app.clients.bloomberg_client - INFO - Fetching Currency Data...
2026-01-12 11:46:15,922 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=60, Msg=正在获取货币指标 (USD)..., Progress=41%
2026-01-12 11:46:17,800 - app.clients.bloomberg_client - INFO - ✅ Parsed 215 items from remote.
2026-01-12 11:46:35,038 - app.clients.bloomberg_client - INFO - ✅ Saved 215 records to database.
2026-01-12 11:46:35,039 - app.clients.bloomberg_client - INFO - Fetching Non-Currency Data...
2026-01-12 11:46:35,039 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=60, Msg=正在获取非货币指标..., Progress=55%
2026-01-12 11:46:35,982 - app.clients.bloomberg_client - INFO - ✅ Parsed 260 items from remote.
2026-01-12 11:46:52,433 - app.clients.bloomberg_client - INFO - ✅ Saved 260 records to database.
2026-01-12 11:46:52,440 - app.clients.bloomberg_client - INFO - Fetching Price Data (Aligned)...
2026-01-12 11:46:52,440 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=60, Msg=正在获取价格指标..., Progress=69%
2026-01-12 11:46:53,034 - app.clients.bloomberg_client - INFO - Found 9 revenue reporting dates. Fetching aligned price data...
2026-01-12 11:47:04,398 - app.clients.bloomberg_client - INFO - ✅ Parsed 27 items from remote.
2026-01-12 11:47:07,274 - app.clients.bloomberg_client - INFO - ✅ Saved 27 records to database.
2026-01-12 11:47:07,275 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=60, Msg=Finalizing data..., Progress=82%
2026-01-12 11:47:08,374 - app.clients.bloomberg_client - INFO - ✅ Cleanup and View Refresh completed.
2026-01-12 11:47:08,375 - app.clients.bloomberg_client - INFO - ✅ Completed processing for 2503 JP Equity
2026-01-12 11:47:08,375 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=60, Msg=Bloomberg data sync complete, Progress=90%
2026-01-12 11:47:09,101 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=60, Msg=Bloomberg 数据同步完成, Progress=100%
2026-01-12 11:51:11,068 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=61, Msg=正在初始化数据获取..., Progress=0%
2026-01-12 11:51:11,648 - app.clients.bloomberg_client - INFO - Connecting to Jupyter at http://192.168.3.161:8888...
2026-01-12 11:51:14,081 - app.clients.bloomberg_client - INFO - ✅ Authentication successful.
2026-01-12 11:51:14,108 - app.clients.bloomberg_client - INFO - ✅ Found existing kernel: bc27f3b1-b028-434a-99fa-c1cad4495a87 (remote_env)
2026-01-12 11:51:14,173 - app.clients.bloomberg_client - INFO - ✅ WebSocket connected.
2026-01-12 11:51:14,173 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=61, Msg=数据源连接成功, Progress=10%
2026-01-12 11:51:15,149 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=61, Msg=正在连接 Bloomberg 终端..., Progress=20%
2026-01-12 11:51:16,055 - app.clients.bloomberg_client - INFO - 🚀 Starting fetch for: 2503 JP Equity
2026-01-12 11:51:16,056 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=61, Msg=Starting Bloomberg session..., Progress=20%
2026-01-12 11:51:16,516 - app.clients.bloomberg_client - INFO - Using forced currency: CNY
2026-01-12 11:51:16,516 - app.clients.bloomberg_client - INFO - Fetching Basic Data...
2026-01-12 11:51:16,516 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=61, Msg=Fetching Company Basic Info..., Progress=27%
2026-01-12 11:51:18,000 - app.clients.bloomberg_client - INFO - ✅ Parsed 2 items from remote.
2026-01-12 11:51:20,192 - app.clients.bloomberg_client - INFO - ✅ Saved 2 records to database.
2026-01-12 11:51:20,193 - app.clients.bloomberg_client - INFO - Fetching Currency Data...
2026-01-12 11:51:20,193 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=61, Msg=正在获取货币指标 (CNY)..., Progress=41%
2026-01-12 11:51:21,634 - app.clients.bloomberg_client - INFO - ✅ Parsed 215 items from remote.
2026-01-12 11:51:38,825 - app.clients.bloomberg_client - INFO - ✅ Saved 215 records to database.
2026-01-12 11:51:38,827 - app.clients.bloomberg_client - INFO - Fetching Non-Currency Data...
2026-01-12 11:51:38,827 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=61, Msg=正在获取非货币指标..., Progress=55%
2026-01-12 11:51:39,821 - app.clients.bloomberg_client - INFO - ✅ Parsed 260 items from remote.
2026-01-12 11:51:58,838 - app.clients.bloomberg_client - INFO - ✅ Saved 260 records to database.
2026-01-12 11:51:58,839 - app.clients.bloomberg_client - INFO - Fetching Price Data (Aligned)...
2026-01-12 11:51:58,839 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=61, Msg=正在获取价格指标..., Progress=69%
2026-01-12 11:51:59,168 - app.clients.bloomberg_client - INFO - Fetching aligned price data for 11 dates (Revenue + Calendar Years)...
2026-01-12 11:52:13,001 - app.clients.bloomberg_client - INFO - ✅ Parsed 31 items from remote.
2026-01-12 11:52:15,056 - app.clients.bloomberg_client - INFO - ✅ Saved 31 records to database.
2026-01-12 11:52:15,057 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=61, Msg=Finalizing data..., Progress=82%
2026-01-12 11:52:17,040 - app.clients.bloomberg_client - INFO - ✅ Cleanup and View Refresh completed.
2026-01-12 11:52:17,040 - app.clients.bloomberg_client - INFO - ✅ Completed processing for 2503 JP Equity
2026-01-12 11:52:17,041 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=61, Msg=Bloomberg data sync complete, Progress=90%
2026-01-12 11:52:17,481 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=61, Msg=Bloomberg 数据同步完成, Progress=100%
2026-01-12 12:00:46,984 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=62, Msg=正在初始化数据获取..., Progress=0%
2026-01-12 12:00:47,396 - app.clients.bloomberg_client - INFO - Connecting to Jupyter at http://192.168.3.161:8888...
2026-01-12 12:00:47,788 - app.clients.bloomberg_client - INFO - ✅ Authentication successful.
2026-01-12 12:00:47,817 - app.clients.bloomberg_client - INFO - ✅ Found existing kernel: bc27f3b1-b028-434a-99fa-c1cad4495a87 (remote_env)
2026-01-12 12:00:48,022 - app.clients.bloomberg_client - INFO - ✅ WebSocket connected.
2026-01-12 12:00:48,022 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=62, Msg=数据源连接成功, Progress=10%
2026-01-12 12:00:48,956 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=62, Msg=正在连接 Bloomberg 终端..., Progress=20%
2026-01-12 12:00:50,482 - app.clients.bloomberg_client - INFO - 🚀 Starting fetch for: 2503 JP Equity
2026-01-12 12:00:50,483 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=62, Msg=Starting Bloomberg session..., Progress=20%
2026-01-12 12:00:50,789 - app.clients.bloomberg_client - INFO - Using forced currency: CNY
2026-01-12 12:00:50,789 - app.clients.bloomberg_client - INFO - Fetching Basic Data...
2026-01-12 12:00:50,789 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=62, Msg=Fetching Company Basic Info..., Progress=27%
2026-01-12 12:00:52,248 - app.clients.bloomberg_client - INFO - ✅ Parsed 2 items from remote.
2026-01-12 12:00:53,025 - app.clients.bloomberg_client - INFO - ✅ Saved 2 records to database.
2026-01-12 12:00:53,025 - app.clients.bloomberg_client - INFO - Fetching Currency Data...
2026-01-12 12:00:53,025 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=62, Msg=正在获取货币指标 (CNY)..., Progress=41%
2026-01-12 12:00:53,859 - app.clients.bloomberg_client - INFO - ✅ Parsed 215 items from remote.
2026-01-12 12:01:11,603 - app.clients.bloomberg_client - INFO - ✅ Saved 215 records to database.
2026-01-12 12:01:11,605 - app.clients.bloomberg_client - INFO - Fetching Non-Currency Data...
2026-01-12 12:01:11,605 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=62, Msg=正在获取非货币指标..., Progress=55%
2026-01-12 12:01:13,691 - app.clients.bloomberg_client - INFO - ✅ Parsed 260 items from remote.
2026-01-12 12:01:33,012 - app.clients.bloomberg_client - INFO - ✅ Saved 260 records to database.
2026-01-12 12:01:33,012 - app.clients.bloomberg_client - INFO - Fetching Price Data (Aligned)...
2026-01-12 12:01:33,012 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=62, Msg=正在获取价格指标..., Progress=69%
2026-01-12 12:01:33,424 - app.clients.bloomberg_client - INFO - Found 9 revenue reporting dates. Fetching aligned price data...
2026-01-12 12:01:44,341 - app.clients.bloomberg_client - INFO - ✅ Parsed 27 items from remote.
2026-01-12 12:01:46,319 - app.clients.bloomberg_client - INFO - ✅ Saved 27 records to database.
2026-01-12 12:01:46,320 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=62, Msg=Finalizing data..., Progress=82%
2026-01-12 12:01:47,279 - app.clients.bloomberg_client - INFO - ✅ Cleanup and View Refresh completed.
2026-01-12 12:01:47,280 - app.clients.bloomberg_client - INFO - ✅ Completed processing for 2503 JP Equity
2026-01-12 12:01:47,280 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=62, Msg=Bloomberg data sync complete, Progress=90%
2026-01-12 12:01:48,004 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=62, Msg=Bloomberg 数据同步完成, Progress=100%
2026-01-12 12:03:53,293 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=63, Msg=正在初始化数据获取..., Progress=0%
2026-01-12 12:03:54,343 - app.clients.bloomberg_client - INFO - Connecting to Jupyter at http://192.168.3.161:8888...
2026-01-12 12:03:54,619 - app.clients.bloomberg_client - INFO - ✅ Authentication successful.
2026-01-12 12:03:54,647 - app.clients.bloomberg_client - INFO - ✅ Found existing kernel: bc27f3b1-b028-434a-99fa-c1cad4495a87 (remote_env)
2026-01-12 12:03:54,699 - app.clients.bloomberg_client - INFO - ✅ WebSocket connected.
2026-01-12 12:03:54,699 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=63, Msg=数据源连接成功, Progress=10%
2026-01-12 12:03:55,171 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=63, Msg=正在连接 Bloomberg 终端..., Progress=20%
2026-01-12 12:03:55,838 - app.clients.bloomberg_client - INFO - 🚀 Starting fetch for: 2503 JP Equity
2026-01-12 12:03:55,839 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=63, Msg=Starting Bloomberg session..., Progress=20%
2026-01-12 12:03:56,708 - app.clients.bloomberg_client - INFO - Using forced currency: CNY
2026-01-12 12:03:56,709 - app.clients.bloomberg_client - INFO - Fetching Basic Data...
2026-01-12 12:03:56,709 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=63, Msg=Fetching Company Basic Info..., Progress=27%
2026-01-12 12:03:58,922 - app.clients.bloomberg_client - INFO - ✅ Parsed 2 items from remote.
2026-01-12 12:04:01,068 - app.clients.bloomberg_client - INFO - ✅ Saved 2 records to database.
2026-01-12 12:04:01,069 - app.clients.bloomberg_client - INFO - Fetching Currency Data...
2026-01-12 12:04:01,069 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=63, Msg=正在获取货币指标 (CNY)..., Progress=41%
2026-01-12 12:04:02,937 - app.clients.bloomberg_client - INFO - ✅ Parsed 215 items from remote.
2026-01-12 12:04:16,817 - app.clients.bloomberg_client - INFO - ✅ Saved 215 records to database.
2026-01-12 12:04:16,818 - app.clients.bloomberg_client - INFO - Fetching Non-Currency Data...
2026-01-12 12:04:16,819 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=63, Msg=正在获取非货币指标..., Progress=55%
2026-01-12 12:04:19,637 - app.clients.bloomberg_client - INFO - ✅ Parsed 260 items from remote.
2026-01-12 12:04:40,482 - app.clients.bloomberg_client - INFO - ✅ Saved 260 records to database.
2026-01-12 12:04:40,482 - app.clients.bloomberg_client - INFO - Fetching Price Data (Aligned)...
2026-01-12 12:04:40,482 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=63, Msg=正在获取价格指标..., Progress=69%
2026-01-12 12:04:41,016 - app.clients.bloomberg_client - INFO - Found 9 revenue reporting dates. Fetching aligned price data...
2026-01-12 12:04:53,208 - app.clients.bloomberg_client - INFO - ✅ Parsed 27 items from remote.
2026-01-12 12:04:53,210 - app.clients.bloomberg_client - INFO - 💾 [DEBUG] Saving Market_Cap: Date=2024-12-31, Value=86988.3177, Currency=CNY
2026-01-12 12:04:53,210 - app.clients.bloomberg_client - INFO - 💾 [DEBUG] Saving Market_Cap: Date=2023-12-31, Value=95209.9289, Currency=CNY
2026-01-12 12:04:53,211 - app.clients.bloomberg_client - INFO - 💾 [DEBUG] Saving Market_Cap: Date=2022-12-31, Value=96786.4997, Currency=CNY
2026-01-12 12:04:53,211 - app.clients.bloomberg_client - INFO - 💾 [DEBUG] Saving Market_Cap: Date=2021-12-31, Value=93410.0414, Currency=CNY
2026-01-12 12:04:53,211 - app.clients.bloomberg_client - INFO - 💾 [DEBUG] Saving Market_Cap: Date=2020-12-31, Value=140556.4302, Currency=CNY
2026-01-12 12:04:53,211 - app.clients.bloomberg_client - INFO - 💾 [DEBUG] Saving Market_Cap: Date=2019-12-31, Value=140163.3311, Currency=CNY
2026-01-12 12:04:53,211 - app.clients.bloomberg_client - INFO - 💾 [DEBUG] Saving Market_Cap: Date=2018-12-31, Value=130875.1203, Currency=CNY
2026-01-12 12:04:53,211 - app.clients.bloomberg_client - INFO - 💾 [DEBUG] Saving Market_Cap: Date=2017-12-31, Value=150051.5647, Currency=CNY
2026-01-12 12:04:53,211 - app.clients.bloomberg_client - INFO - 💾 [DEBUG] Saving Market_Cap: Date=2016-12-31, Value=103403.6124, Currency=CNY
2026-01-12 12:04:58,064 - app.clients.bloomberg_client - INFO - ✅ Saved 27 records to database.
2026-01-12 12:04:58,064 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=63, Msg=Finalizing data..., Progress=82%
2026-01-12 12:05:01,647 - app.clients.bloomberg_client - INFO - ✅ Cleanup and View Refresh completed.
2026-01-12 12:05:01,647 - app.clients.bloomberg_client - INFO - ✅ Completed processing for 2503 JP Equity
2026-01-12 12:05:01,648 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=63, Msg=Bloomberg data sync complete, Progress=90%
2026-01-12 12:05:01,910 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=63, Msg=Bloomberg 数据同步完成, Progress=100%
2026-01-12 12:09:12,429 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=64, Msg=正在初始化数据获取..., Progress=0%
2026-01-12 12:09:12,942 - app.clients.bloomberg_client - INFO - Connecting to Jupyter at http://192.168.3.161:8888...
2026-01-12 12:09:14,418 - app.clients.bloomberg_client - INFO - ✅ Authentication successful.
2026-01-12 12:09:14,447 - app.clients.bloomberg_client - INFO - ✅ Found existing kernel: bc27f3b1-b028-434a-99fa-c1cad4495a87 (remote_env)
2026-01-12 12:09:14,497 - app.clients.bloomberg_client - INFO - ✅ WebSocket connected.
2026-01-12 12:09:14,498 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=64, Msg=数据源连接成功, Progress=10%
2026-01-12 12:09:15,071 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=64, Msg=正在连接 Bloomberg 终端..., Progress=20%
2026-01-12 12:09:15,661 - app.clients.bloomberg_client - INFO - 🚀 Starting fetch for: 2503 JP Equity
2026-01-12 12:09:15,661 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=64, Msg=Starting Bloomberg session..., Progress=20%
2026-01-12 12:09:16,492 - app.clients.bloomberg_client - INFO - Using forced currency: CNY
2026-01-12 12:09:16,495 - app.clients.bloomberg_client - INFO - Fetching Basic Data...
2026-01-12 12:09:16,495 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=64, Msg=Fetching Company Basic Info..., Progress=27%
2026-01-12 12:09:18,548 - app.clients.bloomberg_client - INFO - ✅ Parsed 2 items from remote.
2026-01-12 12:09:20,215 - app.clients.bloomberg_client - INFO - ✅ Saved 2 records to database.
2026-01-12 12:09:20,215 - app.clients.bloomberg_client - INFO - Fetching Currency Data...
2026-01-12 12:09:20,215 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=64, Msg=正在获取货币指标 (CNY)..., Progress=41%
2026-01-12 12:09:21,781 - app.clients.bloomberg_client - INFO - ✅ Parsed 215 items from remote.
2026-01-12 12:09:40,266 - app.clients.bloomberg_client - INFO - ✅ Saved 215 records to database.
2026-01-12 12:09:40,268 - app.clients.bloomberg_client - INFO - Fetching Non-Currency Data...
2026-01-12 12:09:40,269 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=64, Msg=正在获取非货币指标..., Progress=55%
2026-01-12 12:09:41,884 - app.clients.bloomberg_client - INFO - ✅ Parsed 260 items from remote.
2026-01-12 12:10:05,761 - app.clients.bloomberg_client - INFO - ✅ Saved 260 records to database.
2026-01-12 12:10:05,766 - app.clients.bloomberg_client - INFO - Fetching Price Data (Aligned)...
2026-01-12 12:10:05,766 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=64, Msg=正在获取价格指标..., Progress=69%
2026-01-12 12:10:07,309 - app.clients.bloomberg_client - INFO - Found 9 revenue reporting dates. Fetching aligned price data...
2026-01-12 12:10:17,887 - app.clients.bloomberg_client - INFO - ✅ Parsed 27 items from remote.
2026-01-12 12:10:17,887 - app.clients.bloomberg_client - INFO - 💾 [DEBUG] Saving Market_Cap: Date=2024-12-31, Value=86988.3177, Currency=CNY
2026-01-12 12:10:17,887 - app.clients.bloomberg_client - INFO - 💾 [DEBUG] Saving Market_Cap: Date=2023-12-31, Value=95209.9289, Currency=CNY
2026-01-12 12:10:17,887 - app.clients.bloomberg_client - INFO - 💾 [DEBUG] Saving Market_Cap: Date=2022-12-31, Value=96786.4997, Currency=CNY
2026-01-12 12:10:17,887 - app.clients.bloomberg_client - INFO - 💾 [DEBUG] Saving Market_Cap: Date=2021-12-31, Value=93410.0414, Currency=CNY
2026-01-12 12:10:17,887 - app.clients.bloomberg_client - INFO - 💾 [DEBUG] Saving Market_Cap: Date=2020-12-31, Value=140556.4302, Currency=CNY
2026-01-12 12:10:17,887 - app.clients.bloomberg_client - INFO - 💾 [DEBUG] Saving Market_Cap: Date=2019-12-31, Value=140163.3311, Currency=CNY
2026-01-12 12:10:17,887 - app.clients.bloomberg_client - INFO - 💾 [DEBUG] Saving Market_Cap: Date=2018-12-31, Value=130875.1203, Currency=CNY
2026-01-12 12:10:17,887 - app.clients.bloomberg_client - INFO - 💾 [DEBUG] Saving Market_Cap: Date=2017-12-31, Value=150051.5647, Currency=CNY
2026-01-12 12:10:17,887 - app.clients.bloomberg_client - INFO - 💾 [DEBUG] Saving Market_Cap: Date=2016-12-31, Value=103403.6124, Currency=CNY
2026-01-12 12:10:21,706 - app.clients.bloomberg_client - INFO - ✅ Saved 27 records to database.
2026-01-12 12:10:21,708 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=64, Msg=Finalizing data..., Progress=82%
2026-01-12 12:10:25,944 - app.clients.bloomberg_client - INFO - ✅ Cleanup and View Refresh completed.
2026-01-12 12:10:25,945 - app.clients.bloomberg_client - INFO - ✅ Completed processing for 2503 JP Equity
2026-01-12 12:10:25,945 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=64, Msg=Bloomberg data sync complete, Progress=90%
2026-01-12 12:10:26,424 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=64, Msg=Bloomberg 数据同步完成, Progress=100%
2026-01-12 12:17:20,087 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=65, Msg=正在初始化数据获取..., Progress=0%
2026-01-12 12:17:21,105 - app.clients.bloomberg_client - INFO - Connecting to Jupyter at http://192.168.3.161:8888...
2026-01-12 12:17:22,164 - app.clients.bloomberg_client - INFO - ✅ Authentication successful.
2026-01-12 12:17:22,194 - app.clients.bloomberg_client - INFO - ✅ Found existing kernel: bc27f3b1-b028-434a-99fa-c1cad4495a87 (remote_env)
2026-01-12 12:17:22,251 - app.clients.bloomberg_client - INFO - ✅ WebSocket connected.
2026-01-12 12:17:22,251 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=65, Msg=数据源连接成功, Progress=10%
2026-01-12 12:17:23,267 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=65, Msg=正在连接 Bloomberg 终端..., Progress=20%
2026-01-12 12:17:23,545 - app.clients.bloomberg_client - INFO - 🚀 Starting fetch for: 2503 JP Equity
2026-01-12 12:17:23,545 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=65, Msg=Starting Bloomberg session..., Progress=20%
2026-01-12 12:17:25,394 - app.clients.bloomberg_client - INFO - Using forced currency: CNY
2026-01-12 12:17:25,395 - app.clients.bloomberg_client - INFO - Fetching Basic Data...
2026-01-12 12:17:25,395 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=65, Msg=Fetching Company Basic Info..., Progress=27%
2026-01-12 12:17:27,481 - app.clients.bloomberg_client - INFO - ✅ Parsed 2 items from remote.
2026-01-12 12:17:27,481 - app.clients.bloomberg_client - INFO - DEBUG: basic_data before save: [{'Company_code': '2503 JP Equity', 'update_date': '2026-01-12', 'currency': 'CNY', 'indicator': 'dividend_yield', 'value': '3.1230217345431526', 'value_date': '2026-01-12'}, {'Company_code': '2503 JP Equity', 'update_date': '2026-01-12', 'currency': 'CNY', 'indicator': 'IPO_date', 'value': 'None', 'value_date': '2026-01-12'}]
2026-01-12 12:17:29,452 - app.clients.bloomberg_client - INFO - ✅ Saved 2 records to database.
2026-01-12 12:17:29,452 - app.clients.bloomberg_client - INFO - Fetching Currency Data...
2026-01-12 12:17:29,452 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=65, Msg=正在获取货币指标 (CNY)..., Progress=41%
2026-01-12 12:17:31,460 - app.clients.bloomberg_client - INFO - ✅ Parsed 215 items from remote.
2026-01-12 12:17:52,620 - app.clients.bloomberg_client - INFO - ✅ Saved 215 records to database.
2026-01-12 12:17:52,623 - app.clients.bloomberg_client - INFO - Fetching Non-Currency Data...
2026-01-12 12:17:52,623 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=65, Msg=正在获取非货币指标..., Progress=55%
2026-01-12 12:17:54,783 - app.clients.bloomberg_client - INFO - ✅ Parsed 260 items from remote.
2026-01-12 12:18:31,861 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=66, Msg=正在初始化数据获取..., Progress=0%
2026-01-12 12:18:33,349 - app.clients.bloomberg_client - INFO - Connecting to Jupyter at http://192.168.3.161:8888...
2026-01-12 12:18:34,339 - app.clients.bloomberg_client - INFO - ✅ Authentication successful.
2026-01-12 12:18:34,372 - app.clients.bloomberg_client - INFO - ✅ Found existing kernel: bc27f3b1-b028-434a-99fa-c1cad4495a87 (remote_env)
2026-01-12 12:18:34,432 - app.clients.bloomberg_client - INFO - ✅ WebSocket connected.
2026-01-12 12:18:34,432 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=66, Msg=数据源连接成功, Progress=10%
2026-01-12 12:18:35,690 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=66, Msg=正在连接 Bloomberg 终端..., Progress=20%
2026-01-12 12:18:36,255 - app.clients.bloomberg_client - INFO - 🚀 Starting fetch for: 2503 JP Equity
2026-01-12 12:18:36,256 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=66, Msg=Starting Bloomberg session..., Progress=20%
2026-01-12 12:18:38,442 - app.clients.bloomberg_client - INFO - Using forced currency: CNY
2026-01-12 12:18:38,443 - app.clients.bloomberg_client - INFO - Fetching Basic Data...
2026-01-12 12:18:38,443 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=66, Msg=Fetching Company Basic Info..., Progress=27%
2026-01-12 12:18:40,961 - app.clients.bloomberg_client - INFO - ✅ Parsed 2 items from remote.
2026-01-12 12:18:40,961 - app.clients.bloomberg_client - INFO - DEBUG: basic_data before save: [{'Company_code': '2503 JP Equity', 'update_date': '2026-01-12 12:18:41', 'currency': 'CNY', 'indicator': 'dividend_yield', 'value': '3.1230217345431526', 'value_date': '2026-01-12 12:18:41'}, {'Company_code': '2503 JP Equity', 'update_date': '2026-01-12 12:18:41', 'currency': 'CNY', 'indicator': 'IPO_date', 'value': 'None', 'value_date': '2026-01-12 12:18:41'}]
2026-01-12 12:18:42,433 - app.clients.bloomberg_client - INFO - ✅ Saved 2 records to database.
2026-01-12 12:18:42,434 - app.clients.bloomberg_client - INFO - Fetching Currency Data...
2026-01-12 12:18:42,434 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=66, Msg=正在获取货币指标 (CNY)..., Progress=41%
2026-01-12 12:18:44,354 - app.clients.bloomberg_client - INFO - ✅ Parsed 215 items from remote.
2026-01-12 12:19:05,814 - app.clients.bloomberg_client - INFO - ✅ Saved 215 records to database.
2026-01-12 12:19:05,819 - app.clients.bloomberg_client - INFO - Fetching Non-Currency Data...
2026-01-12 12:19:05,820 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=66, Msg=正在获取非货币指标..., Progress=55%
2026-01-12 12:19:07,418 - app.clients.bloomberg_client - INFO - ✅ Parsed 260 items from remote.
2026-01-12 12:19:27,370 - app.clients.bloomberg_client - INFO - ✅ Saved 260 records to database.
2026-01-12 12:19:27,371 - app.clients.bloomberg_client - INFO - Fetching Price Data (Aligned)...
2026-01-12 12:19:27,371 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=66, Msg=正在获取价格指标..., Progress=69%
2026-01-12 12:19:28,080 - app.clients.bloomberg_client - INFO - Found 9 revenue reporting dates. Fetching aligned price data...
2026-01-12 12:19:39,293 - app.clients.bloomberg_client - INFO - ✅ Parsed 27 items from remote.
2026-01-12 12:19:43,961 - app.clients.bloomberg_client - INFO - ✅ Saved 27 records to database.
2026-01-12 12:19:43,962 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=66, Msg=Finalizing data..., Progress=82%
2026-01-12 12:19:45,511 - app.clients.bloomberg_client - INFO - ✅ Cleanup and View Refresh completed.
2026-01-12 12:19:45,512 - app.clients.bloomberg_client - INFO - ✅ Completed processing for 2503 JP Equity
2026-01-12 12:19:45,512 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=66, Msg=Bloomberg data sync complete, Progress=90%
2026-01-12 12:19:47,693 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=66, Msg=Bloomberg 数据同步完成, Progress=100%
2026-01-12 13:39:22,650 - app.main - INFO - 🔍 [搜索] 开始搜索股票: 三一国际
2026-01-12 13:39:22,724 - app.main - INFO - 🤖 [搜索-LLM] 调用 gemini-2.5-flash 进行股票搜索
2026-01-12 13:39:22,724 - google_genai.models - INFO - AFC is enabled with max remote calls: 10.
2026-01-12 13:39:27,383 - httpx - INFO - HTTP Request: POST https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent "HTTP/1.1 200 OK"
2026-01-12 13:39:27,390 - app.main - INFO - ✅ [搜索-LLM] 模型响应完成, 耗时: 4.67秒, Tokens: prompt=166, completion=78, total=244
2026-01-12 13:39:27,391 - app.main - INFO - ✅ [搜索] 搜索完成, 找到 1 个结果, 总耗时: 4.74秒
2026-01-12 13:39:35,605 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=67, Msg=正在初始化数据获取..., Progress=0%
2026-01-12 13:39:36,193 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=67, Msg=数据获取失败: invalid syntax. Perhaps you forgot a comma? (bloomberg_client.py, line 587), Progress=0%
2026-01-12 13:54:13,489 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=68, Msg=正在初始化数据获取..., Progress=0%
2026-01-12 13:54:13,853 - app.clients.bloomberg_client - INFO - Connecting to Jupyter at http://192.168.3.161:8888...
2026-01-12 13:54:14,191 - app.clients.bloomberg_client - INFO - ✅ Authentication successful.
2026-01-12 13:54:14,229 - app.clients.bloomberg_client - INFO - ✅ Found existing kernel: bc27f3b1-b028-434a-99fa-c1cad4495a87 (remote_env)
2026-01-12 13:54:14,427 - app.clients.bloomberg_client - INFO - ✅ WebSocket connected.
2026-01-12 13:54:14,428 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=68, Msg=数据源连接成功, Progress=10%
2026-01-12 13:54:14,824 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=68, Msg=正在连接 Bloomberg 终端..., Progress=20%
2026-01-12 13:54:15,384 - app.clients.bloomberg_client - INFO - 🚀 Starting fetch for: 00631 HK Equity
2026-01-12 13:54:15,385 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=68, Msg=Starting Bloomberg session..., Progress=20%
2026-01-12 13:54:15,833 - app.clients.bloomberg_client - INFO - Using auto-detected currency: HKD
2026-01-12 13:54:15,834 - app.clients.bloomberg_client - INFO - Fetching Basic Data...
2026-01-12 13:54:15,834 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=68, Msg=Fetching Company Basic Info..., Progress=27%
2026-01-12 13:54:16,597 - app.clients.bloomberg_client - INFO - ✅ Parsed 0 items from remote.
2026-01-12 13:54:16,597 - app.clients.bloomberg_client - INFO - DEBUG: basic_data before save: []
2026-01-12 13:54:16,597 - app.clients.bloomberg_client - INFO - Fetching Currency Data...
2026-01-12 13:54:16,597 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=68, Msg=正在获取货币指标 (HKD)..., Progress=41%
2026-01-12 13:54:17,282 - app.clients.bloomberg_client - INFO - ✅ Parsed 0 items from remote.
2026-01-12 13:54:17,283 - app.clients.bloomberg_client - INFO - Fetching Non-Currency Data...
2026-01-12 13:54:17,284 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=68, Msg=正在获取非货币指标..., Progress=55%
2026-01-12 13:54:18,408 - app.clients.bloomberg_client - INFO - ✅ Parsed 0 items from remote.
2026-01-12 13:54:18,408 - app.clients.bloomberg_client - INFO - Fetching Price Data (Aligned)...
2026-01-12 13:54:18,408 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=68, Msg=正在获取价格指标..., Progress=69%
2026-01-12 13:54:18,668 - app.clients.bloomberg_client - WARNING - No revenue dates found. Falling back to yearly price fetch.
2026-01-12 13:54:18,986 - app.clients.bloomberg_client - INFO - ✅ Parsed 0 items from remote.
2026-01-12 13:54:18,986 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=68, Msg=Finalizing data..., Progress=82%
2026-01-12 13:54:20,042 - app.clients.bloomberg_client - INFO - ✅ Cleanup and View Refresh completed.
2026-01-12 13:54:20,042 - app.clients.bloomberg_client - INFO - ✅ Completed processing for 00631 HK Equity
2026-01-12 13:54:20,043 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=68, Msg=Bloomberg data sync complete, Progress=90%
2026-01-12 13:54:20,603 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=68, Msg=Bloomberg 数据同步完成, Progress=100%
2026-01-12 13:54:24,013 - app.services.bloomberg_service - WARNING - No Bloomberg data found for symbol: 00631
2026-01-12 13:54:24,293 - app.services.bloomberg_service - WARNING - No Bloomberg data found for symbol: 00631
2026-01-12 14:10:53,933 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=69, Msg=正在初始化数据获取..., Progress=0%
2026-01-12 14:10:54,645 - app.clients.bloomberg_client - INFO - Connecting to Jupyter at http://192.168.3.161:8888...
2026-01-12 14:10:55,044 - app.clients.bloomberg_client - INFO - ✅ Authentication successful.
2026-01-12 14:10:55,071 - app.clients.bloomberg_client - INFO - ✅ Found existing kernel: bc27f3b1-b028-434a-99fa-c1cad4495a87 (remote_env)
2026-01-12 14:10:55,123 - app.clients.bloomberg_client - INFO - ✅ WebSocket connected.
2026-01-12 14:10:55,124 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=69, Msg=数据源连接成功, Progress=10%
2026-01-12 14:10:55,677 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=69, Msg=正在连接 Bloomberg 终端..., Progress=20%
2026-01-12 14:10:55,939 - app.clients.bloomberg_client - INFO - 🚀 Starting fetch for: 631 HK Equity
2026-01-12 14:10:55,939 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=69, Msg=Starting Bloomberg session..., Progress=20%
2026-01-12 14:10:56,480 - app.clients.bloomberg_client - INFO - Using auto-detected currency: HKD
2026-01-12 14:10:56,481 - app.clients.bloomberg_client - INFO - Fetching Basic Data...
2026-01-12 14:10:56,481 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=69, Msg=Fetching Company Basic Info..., Progress=27%
2026-01-12 14:10:57,704 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "631 HK Equity", "update_date": "2026-01-12 14:10:58", "currency": "HKD", "indicator": "company_name", "value": "SANY HEAVY EQUIPMENT INTL", "value_date": "2026-01-12 14:10:58"}, {"Company_code": "631 HK Equity", "update_date": "2026-01-12 14:10:58", "currency": "HKD", "indicator": "pe_ratio", "value": "19.98882739476631", "value_date": "2026-01-12 14:10:58"}, {"Company_code": "631 HK Equity", "update_date": "2026-01-12 14:10:58", "currency": "HKD", "indicator": "pb_ratio", "value": "2.116312093386662", "value_date": "2026-01-12 14:10:58"}, {"Company_code": "631 HK Equity", "update_date": "2026-01-12 14:10:58", "currency": "HKD", "indicator": "market_cap", "value": "29705920767.51", "value_date": "2026-01-12 14:10:58"}, {"Company_code": "631 HK Equity", "update_date": "2026-01-12 14:10:58", "currency": "HKD", "indicator": "Rev_Abroad", "value": "37.287945521334656", "value_date": "2026-01-12 14:10:58"}, {"Company_code": "631 HK Equity", "update_date": "2026
2026-01-12 14:10:57,705 - app.clients.bloomberg_client - INFO - ✅ Parsed 7 items from remote.
2026-01-12 14:10:57,705 - app.clients.bloomberg_client - INFO - DEBUG: basic_data before save: [{'Company_code': '631 HK Equity', 'update_date': '2026-01-12 14:10:58', 'currency': 'HKD', 'indicator': 'company_name', 'value': 'SANY HEAVY EQUIPMENT INTL', 'value_date': '2026-01-12 14:10:58'}, {'Company_code': '631 HK Equity', 'update_date': '2026-01-12 14:10:58', 'currency': 'HKD', 'indicator': 'pe_ratio', 'value': '19.98882739476631', 'value_date': '2026-01-12 14:10:58'}, {'Company_code': '631 HK Equity', 'update_date': '2026-01-12 14:10:58', 'currency': 'HKD', 'indicator': 'pb_ratio', 'value': '2.116312093386662', 'value_date': '2026-01-12 14:10:58'}, {'Company_code': '631 HK Equity', 'update_date': '2026-01-12 14:10:58', 'currency': 'HKD', 'indicator': 'market_cap', 'value': '29705920767.51', 'value_date': '2026-01-12 14:10:58'}, {'Company_code': '631 HK Equity', 'update_date': '2026-01-12 14:10:58', 'currency': 'HKD', 'indicator': 'Rev_Abroad', 'value': '37.287945521334656', 'value_date': '2026-01-12 14:10:58'}, {'Company_code': '631 HK Equity', 'update_date': '2026-01-12 14:10:58', 'currency': 'HKD', 'indicator': 'dividend_yield', 'value': '3.1556038264999975', 'value_date': '2026-01-12 14:10:58'}, {'Company_code': '631 HK Equity', 'update_date': '2026-01-12 14:10:58', 'currency': 'HKD', 'indicator': 'IPO_date', 'value': '2009-11-25', 'value_date': '2026-01-12 14:10:58'}]
2026-01-12 14:10:58,534 - app.clients.bloomberg_client - INFO - ✅ Saved 7 records to database.
2026-01-12 14:10:58,534 - app.clients.bloomberg_client - INFO - Fetching Currency Data...
2026-01-12 14:10:58,534 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=69, Msg=正在获取货币指标 (HKD)..., Progress=41%
2026-01-12 14:10:59,715 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "631 HK Equity", "update_date": "2026-01-12 14:10:58", "currency": "HKD", "indicator": "Revenue", "value": "2152.9812", "value_date": "2016-12-31"}, {"Company_code": "631 HK Equity", "update_date": "2026-01-12 14:10:58", "currency": "HKD", "indicator": "Net_Income", "value": "-753.2314", "value_date": "2016-12-31"}, {"Company_code": "631 HK Equity", "update_date": "2026-01-12 14:10:58", "currency": "HKD", "indicator": "Cash_From_Operating", "value": "1557.419", "value_date": "2016-12-31"}, {"Company_code": "631 HK Equity", "update_date": "2026-01-12 14:10:58", "currency": "HKD", "indicator": "Capital_Expenditure", "value": "-179.3705", "value_date": "2016-12-31"}, {"Company_code": "631 HK Equity", "update_date": "2026-01-12 14:10:58", "currency": "HKD", "indicator": "Free_Cash_Flow", "value": "1378.0485", "value_date": "2016-12-31"}, {"Company_code": "631 HK Equity", "update_date": "2026-01-12 14:10:58", "currency": "HKD", "indicator": "Dividends_Paid", "va
2026-01-12 14:10:59,715 - app.clients.bloomberg_client - INFO - ✅ Parsed 216 items from remote.
2026-01-12 14:11:12,684 - app.clients.bloomberg_client - INFO - ✅ Saved 216 records to database.
2026-01-12 14:11:12,686 - app.clients.bloomberg_client - INFO - Fetching Non-Currency Data...
2026-01-12 14:11:12,686 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=69, Msg=正在获取非货币指标..., Progress=55%
2026-01-12 14:11:13,789 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "631 HK Equity", "update_date": "2026-01-12 14:11:12", "currency": "HKD", "indicator": "PE", "value": "111.1384", "value_date": "2016-12-30"}, {"Company_code": "631 HK Equity", "update_date": "2026-01-12 14:11:12", "currency": "HKD", "indicator": "PB", "value": "0.5588", "value_date": "2016-12-30"}, {"Company_code": "631 HK Equity", "update_date": "2026-01-12 14:11:12", "currency": "HKD", "indicator": "ROE", "value": "-10.132", "value_date": "2016-12-31"}, {"Company_code": "631 HK Equity", "update_date": "2026-01-12 14:11:12", "currency": "HKD", "indicator": "ROA", "value": "-6.0025", "value_date": "2016-12-31"}, {"Company_code": "631 HK Equity", "update_date": "2026-01-12 14:11:12", "currency": "HKD", "indicator": "Gross_Margin", "value": "14.994", "value_date": "2016-12-31"}, {"Company_code": "631 HK Equity", "update_date": "2026-01-12 14:11:12", "currency": "HKD", "indicator": "EBITDA_margin", "value": "-28.2708", "value_date": "2016-12-31"}, {"Company_c
2026-01-12 14:11:13,790 - app.clients.bloomberg_client - INFO - ✅ Parsed 219 items from remote.
2026-01-12 14:11:26,690 - app.clients.bloomberg_client - INFO - ✅ Saved 219 records to database.
2026-01-12 14:11:26,692 - app.clients.bloomberg_client - INFO - Fetching Price Data (Aligned)...
2026-01-12 14:11:26,692 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=69, Msg=正在获取价格指标..., Progress=69%
2026-01-12 14:11:26,975 - app.clients.bloomberg_client - INFO - Found 9 revenue reporting dates. Fetching aligned price data...
2026-01-12 14:11:37,480 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "631 HK Equity", "update_date": "2026-01-12 14:11:26", "currency": "HKD", "indicator": "Last_Price", "value": "4.51", "value_date": "2024-12-31"}, {"Company_code": "631 HK Equity", "update_date": "2026-01-12 14:11:26", "currency": "HKD", "indicator": "Market_Cap", "value": "14494.6462", "value_date": "2024-12-31"}, {"Company_code": "631 HK Equity", "update_date": "2026-01-12 14:11:26", "currency": "HKD", "indicator": "Dividend_Yield", "value": "4.2129", "value_date": "2024-12-31"}, {"Company_code": "631 HK Equity", "update_date": "2026-01-12 14:11:26", "currency": "HKD", "indicator": "Last_Price", "value": "7.55", "value_date": "2023-12-31"}, {"Company_code": "631 HK Equity", "update_date": "2026-01-12 14:11:26", "currency": "HKD", "indicator": "Market_Cap", "value": "24081.9354", "value_date": "2023-12-31"}, {"Company_code": "631 HK Equity", "update_date": "2026-01-12 14:11:26", "currency": "HKD", "indicator": "Dividend_Yield", "value": "2.5166", "value_da
2026-01-12 14:11:37,481 - app.clients.bloomberg_client - INFO - ✅ Parsed 25 items from remote.
2026-01-12 14:11:39,102 - app.clients.bloomberg_client - INFO - ✅ Saved 25 records to database.
2026-01-12 14:11:39,103 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=69, Msg=Finalizing data..., Progress=82%
2026-01-12 14:11:40,554 - app.clients.bloomberg_client - INFO - ✅ Cleanup and View Refresh completed.
2026-01-12 14:11:40,555 - app.clients.bloomberg_client - INFO - ✅ Completed processing for 631 HK Equity
2026-01-12 14:11:40,555 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=69, Msg=Bloomberg data sync complete, Progress=90%
2026-01-12 14:11:40,933 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=69, Msg=Bloomberg 数据同步完成, Progress=100%
2026-01-12 14:11:46,320 - app.services.bloomberg_service - WARNING - No Bloomberg data found for symbol: 00631
2026-01-12 14:12:08,829 - app.services.bloomberg_service - WARNING - No Bloomberg data found for symbol: 00631
2026-01-12 14:15:51,872 - app.services.bloomberg_service - WARNING - No Bloomberg data found for symbol: 00631
2026-01-12 14:22:58,914 - app.services.bloomberg_service - WARNING - No Bloomberg data found for symbol: 00631
2026-01-12 14:23:02,681 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=70, Msg=正在初始化数据获取..., Progress=0%
2026-01-12 14:23:03,405 - app.clients.bloomberg_client - INFO - Connecting to Jupyter at http://192.168.3.161:8888...
2026-01-12 14:23:03,673 - app.clients.bloomberg_client - INFO - ✅ Authentication successful.
2026-01-12 14:23:03,717 - app.clients.bloomberg_client - INFO - ✅ Found existing kernel: bc27f3b1-b028-434a-99fa-c1cad4495a87 (remote_env)
2026-01-12 14:23:03,914 - app.clients.bloomberg_client - INFO - ✅ WebSocket connected.
2026-01-12 14:23:03,914 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=70, Msg=数据源连接成功, Progress=10%
2026-01-12 14:23:04,185 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=70, Msg=正在连接 Bloomberg 终端..., Progress=20%
2026-01-12 14:23:04,628 - app.clients.bloomberg_client - INFO - 🚀 Starting fetch for: 00631 HK Equity
2026-01-12 14:23:04,628 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=70, Msg=Starting Bloomberg session..., Progress=20%
2026-01-12 14:23:05,408 - app.clients.bloomberg_client - INFO - Using auto-detected currency: HKD
2026-01-12 14:23:05,408 - app.clients.bloomberg_client - INFO - Fetching Basic Data...
2026-01-12 14:23:05,408 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=70, Msg=Fetching Company Basic Info..., Progress=27%
2026-01-12 14:23:06,372 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:23:06", "currency": "HKD", "indicator": "company_name", "value": "SANY HEAVY EQUIPMENT INTL", "value_date": "2026-01-12 14:23:06"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:23:06", "currency": "HKD", "indicator": "pe_ratio", "value": "20.052832333683007", "value_date": "2026-01-12 14:23:06"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:23:06", "currency": "HKD", "indicator": "pb_ratio", "value": "2.1230886002617653", "value_date": "2026-01-12 14:23:06"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:23:06", "currency": "HKD", "indicator": "market_cap", "value": "29802893305.38", "value_date": "2026-01-12 14:23:06"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:23:06", "currency": "HKD", "indicator": "Rev_Abroad", "value": "37.287945521334656", "value_date": "2026-01-12 14:23:06"}, {"Company_code": "00631 HK Equity", "updat
2026-01-12 14:23:06,373 - app.clients.bloomberg_client - INFO - ✅ Parsed 7 items from remote.
2026-01-12 14:23:06,373 - app.clients.bloomberg_client - INFO - DEBUG: basic_data before save: [{'Company_code': '00631 HK Equity', 'update_date': '2026-01-12 14:23:06', 'currency': 'HKD', 'indicator': 'company_name', 'value': 'SANY HEAVY EQUIPMENT INTL', 'value_date': '2026-01-12 14:23:06'}, {'Company_code': '00631 HK Equity', 'update_date': '2026-01-12 14:23:06', 'currency': 'HKD', 'indicator': 'pe_ratio', 'value': '20.052832333683007', 'value_date': '2026-01-12 14:23:06'}, {'Company_code': '00631 HK Equity', 'update_date': '2026-01-12 14:23:06', 'currency': 'HKD', 'indicator': 'pb_ratio', 'value': '2.1230886002617653', 'value_date': '2026-01-12 14:23:06'}, {'Company_code': '00631 HK Equity', 'update_date': '2026-01-12 14:23:06', 'currency': 'HKD', 'indicator': 'market_cap', 'value': '29802893305.38', 'value_date': '2026-01-12 14:23:06'}, {'Company_code': '00631 HK Equity', 'update_date': '2026-01-12 14:23:06', 'currency': 'HKD', 'indicator': 'Rev_Abroad', 'value': '37.287945521334656', 'value_date': '2026-01-12 14:23:06'}, {'Company_code': '00631 HK Equity', 'update_date': '2026-01-12 14:23:06', 'currency': 'HKD', 'indicator': 'dividend_yield', 'value': '3.145336135090561', 'value_date': '2026-01-12 14:23:06'}, {'Company_code': '00631 HK Equity', 'update_date': '2026-01-12 14:23:06', 'currency': 'HKD', 'indicator': 'IPO_date', 'value': '2009-11-25', 'value_date': '2026-01-12 14:23:06'}]
2026-01-12 14:23:07,870 - app.clients.bloomberg_client - INFO - ✅ Saved 7 records to database.
2026-01-12 14:23:07,871 - app.clients.bloomberg_client - INFO - Fetching Currency Data...
2026-01-12 14:23:07,871 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=70, Msg=正在获取货币指标 (HKD)..., Progress=41%
2026-01-12 14:23:08,272 - app.clients.bloomberg_client - ERROR - Error fetching currency series: name 'timedelta' is not defined
2026-01-12 14:23:08,273 - app.clients.bloomberg_client - INFO - Fetching Non-Currency Data...
2026-01-12 14:23:08,273 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=70, Msg=正在获取非货币指标..., Progress=55%
2026-01-12 14:23:09,053 - app.clients.bloomberg_client - ERROR - Error fetching non-currency series: name 'timedelta' is not defined
2026-01-12 14:23:09,053 - app.clients.bloomberg_client - INFO - Fetching Price Data (Aligned)...
2026-01-12 14:23:09,053 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=70, Msg=正在获取价格指标..., Progress=69%
2026-01-12 14:23:09,347 - app.clients.bloomberg_client - WARNING - No revenue dates found. Falling back to yearly price fetch.
2026-01-12 14:23:09,347 - app.clients.bloomberg_client - ERROR - Error fetching fallback price data: name 'timedelta' is not defined
2026-01-12 14:23:09,348 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=70, Msg=Finalizing data..., Progress=82%
2026-01-12 14:23:10,275 - app.clients.bloomberg_client - INFO - ✅ Cleanup and View Refresh completed.
2026-01-12 14:23:10,275 - app.clients.bloomberg_client - INFO - ✅ Completed processing for 00631 HK Equity
2026-01-12 14:23:10,275 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=70, Msg=Bloomberg data sync complete, Progress=90%
2026-01-12 14:23:10,741 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=70, Msg=Bloomberg 数据同步完成, Progress=100%
2026-01-12 14:36:45,408 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=71, Msg=正在初始化数据获取..., Progress=0%
2026-01-12 14:36:45,934 - app.clients.bloomberg_client - INFO - Connecting to Jupyter at http://192.168.3.161:8888...
2026-01-12 14:36:46,331 - app.clients.bloomberg_client - INFO - ✅ Authentication successful.
2026-01-12 14:36:46,363 - app.clients.bloomberg_client - INFO - ✅ Found existing kernel: bc27f3b1-b028-434a-99fa-c1cad4495a87 (remote_env)
2026-01-12 14:36:46,418 - app.clients.bloomberg_client - INFO - ✅ WebSocket connected.
2026-01-12 14:36:46,418 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=71, Msg=数据源连接成功, Progress=10%
2026-01-12 14:36:47,610 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=71, Msg=正在连接 Bloomberg 终端..., Progress=20%
2026-01-12 14:36:48,331 - app.clients.bloomberg_client - INFO - 🚀 Starting fetch for: 00631 HK Equity
2026-01-12 14:36:48,332 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=71, Msg=Starting Bloomberg session..., Progress=20%
2026-01-12 14:36:49,795 - app.clients.bloomberg_client - INFO - Using auto-detected currency: HKD
2026-01-12 14:36:49,795 - app.clients.bloomberg_client - INFO - Fetching Basic Data...
2026-01-12 14:36:49,795 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=71, Msg=Fetching Company Basic Info..., Progress=27%
2026-01-12 14:36:50,804 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:36:51", "currency": "HKD", "indicator": "company_name", "value": "SANY HEAVY EQUIPMENT INTL", "value_date": "2026-01-12 14:36:51"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:36:51", "currency": "HKD", "indicator": "pe_ratio", "value": "20.029351716875", "value_date": "2026-01-12 14:36:51"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:36:51", "currency": "HKD", "indicator": "pb_ratio", "value": "2.120602595838916", "value_date": "2026-01-12 14:36:51"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:36:51", "currency": "HKD", "indicator": "market_cap", "value": "29770569126.09", "value_date": "2026-01-12 14:36:51"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:36:51", "currency": "HKD", "indicator": "Rev_Abroad", "value": "37.287945521334656", "value_date": "2026-01-12 14:36:51"}, {"Company_code": "00631 HK Equity", "update_da
2026-01-12 14:36:50,805 - app.clients.bloomberg_client - INFO - ✅ Parsed 7 items from remote.
2026-01-12 14:36:50,805 - app.clients.bloomberg_client - INFO - DEBUG: basic_data before save: [{'Company_code': '00631 HK Equity', 'update_date': '2026-01-12 14:36:51', 'currency': 'HKD', 'indicator': 'company_name', 'value': 'SANY HEAVY EQUIPMENT INTL', 'value_date': '2026-01-12 14:36:51'}, {'Company_code': '00631 HK Equity', 'update_date': '2026-01-12 14:36:51', 'currency': 'HKD', 'indicator': 'pe_ratio', 'value': '20.029351716875', 'value_date': '2026-01-12 14:36:51'}, {'Company_code': '00631 HK Equity', 'update_date': '2026-01-12 14:36:51', 'currency': 'HKD', 'indicator': 'pb_ratio', 'value': '2.120602595838916', 'value_date': '2026-01-12 14:36:51'}, {'Company_code': '00631 HK Equity', 'update_date': '2026-01-12 14:36:51', 'currency': 'HKD', 'indicator': 'market_cap', 'value': '29770569126.09', 'value_date': '2026-01-12 14:36:51'}, {'Company_code': '00631 HK Equity', 'update_date': '2026-01-12 14:36:51', 'currency': 'HKD', 'indicator': 'Rev_Abroad', 'value': '37.287945521334656', 'value_date': '2026-01-12 14:36:51'}, {'Company_code': '00631 HK Equity', 'update_date': '2026-01-12 14:36:51', 'currency': 'HKD', 'indicator': 'dividend_yield', 'value': '3.1487512666161748', 'value_date': '2026-01-12 14:36:51'}, {'Company_code': '00631 HK Equity', 'update_date': '2026-01-12 14:36:51', 'currency': 'HKD', 'indicator': 'IPO_date', 'value': '2009-11-25', 'value_date': '2026-01-12 14:36:51'}]
2026-01-12 14:36:51,907 - app.clients.bloomberg_client - INFO - ✅ Saved 7 records to database.
2026-01-12 14:36:51,908 - app.clients.bloomberg_client - INFO - Fetching Currency Data...
2026-01-12 14:36:51,908 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=71, Msg=正在获取货币指标 (HKD)..., Progress=41%
2026-01-12 14:36:53,347 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:36:52", "currency": "HKD", "indicator": "Revenue", "value": "2152.9812", "value_date": "2017-01-12"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:36:52", "currency": "HKD", "indicator": "Net_Income", "value": "-753.2314", "value_date": "2017-01-12"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:36:52", "currency": "HKD", "indicator": "Cash_From_Operating", "value": "1557.419", "value_date": "2017-01-12"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:36:52", "currency": "HKD", "indicator": "Capital_Expenditure", "value": "-179.3705", "value_date": "2017-01-12"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:36:52", "currency": "HKD", "indicator": "Free_Cash_Flow", "value": "1378.0485", "value_date": "2017-01-12"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:36:52", "currency": "HKD", "indicator": "Dividend
2026-01-12 14:36:53,348 - app.clients.bloomberg_client - INFO - ✅ Parsed 240 items from remote.
2026-01-12 14:37:07,885 - app.clients.bloomberg_client - INFO - ✅ Saved 240 records to database.
2026-01-12 14:37:07,887 - app.clients.bloomberg_client - INFO - Fetching Non-Currency Data...
2026-01-12 14:37:07,888 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=71, Msg=正在获取非货币指标..., Progress=55%
2026-01-12 14:37:10,019 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:37:09", "currency": "HKD", "indicator": "ROE", "value": "-10.132", "value_date": "2017-01-12"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:37:09", "currency": "HKD", "indicator": "ROA", "value": "-6.0025", "value_date": "2017-01-12"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:37:09", "currency": "HKD", "indicator": "ROCE", "value": "0.3622", "value_date": "2017-01-12"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:37:09", "currency": "HKD", "indicator": "Gross_Margin", "value": "14.994", "value_date": "2017-01-12"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:37:09", "currency": "HKD", "indicator": "EBITDA_margin", "value": "-28.2708", "value_date": "2017-01-12"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:37:09", "currency": "HKD", "indicator": "Net_Profit_Margin", "value": "-34.9855", "value_date
2026-01-12 14:37:10,019 - app.clients.bloomberg_client - INFO - ✅ Parsed 173 items from remote.
2026-01-12 14:37:20,899 - app.clients.bloomberg_client - INFO - ✅ Saved 173 records to database.
2026-01-12 14:37:20,900 - app.clients.bloomberg_client - INFO - Fetching Price Data (Aligned)...
2026-01-12 14:37:20,900 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=71, Msg=正在获取价格指标..., Progress=69%
2026-01-12 14:37:21,161 - app.clients.bloomberg_client - WARNING - No revenue dates found. Falling back to yearly price fetch.
2026-01-12 14:37:21,790 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:37:21", "currency": "HKD", "indicator": "Last_Price", "value": "1.33", "value_date": "2017-01-12"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:37:21", "currency": "HKD", "indicator": "Market_Cap", "value": "4044.5631", "value_date": "2017-01-12"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:37:21", "currency": "HKD", "indicator": "Last_Price", "value": "2.28", "value_date": "2018-01-12"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:37:21", "currency": "HKD", "indicator": "Market_Cap", "value": "6933.537", "value_date": "2018-01-12"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:37:21", "currency": "HKD", "indicator": "Last_Price", "value": "2.45", "value_date": "2019-01-12"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:37:21", "currency": "HKD", "indicator": "Market_Cap", "value": "7450.5113", "value_
2026-01-12 14:37:21,790 - app.clients.bloomberg_client - INFO - ✅ Parsed 28 items from remote.
2026-01-12 14:37:23,680 - app.clients.bloomberg_client - INFO - ✅ Saved 28 records to database.
2026-01-12 14:37:23,681 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=71, Msg=Finalizing data..., Progress=82%
2026-01-12 14:37:24,983 - app.clients.bloomberg_client - INFO - ✅ Cleanup and View Refresh completed.
2026-01-12 14:37:24,984 - app.clients.bloomberg_client - INFO - ✅ Completed processing for 00631 HK Equity
2026-01-12 14:37:24,984 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=71, Msg=Bloomberg data sync complete, Progress=90%
2026-01-12 14:37:25,270 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=71, Msg=Bloomberg 数据同步完成, Progress=100%
2026-01-12 14:43:07,865 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=72, Msg=正在初始化数据获取..., Progress=0%
2026-01-12 14:43:08,610 - app.clients.bloomberg_client - INFO - Connecting to Jupyter at http://192.168.3.161:8888...
2026-01-12 14:43:08,830 - app.clients.bloomberg_client - INFO - ✅ Authentication successful.
2026-01-12 14:43:09,009 - app.clients.bloomberg_client - INFO - ✅ Found existing kernel: bc27f3b1-b028-434a-99fa-c1cad4495a87 (remote_env)
2026-01-12 14:43:09,066 - app.clients.bloomberg_client - INFO - ✅ WebSocket connected.
2026-01-12 14:43:09,066 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=72, Msg=数据源连接成功, Progress=10%
2026-01-12 14:43:09,497 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=72, Msg=正在连接 Bloomberg 终端..., Progress=20%
2026-01-12 14:43:09,942 - app.clients.bloomberg_client - INFO - 🚀 Starting fetch for: 00631 HK Equity
2026-01-12 14:43:09,943 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=72, Msg=Starting Bloomberg session..., Progress=20%
2026-01-12 14:43:10,951 - app.clients.bloomberg_client - INFO - Using auto-detected currency: HKD
2026-01-12 14:43:10,951 - app.clients.bloomberg_client - INFO - Fetching Basic Data...
2026-01-12 14:43:10,952 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=72, Msg=Fetching Company Basic Info..., Progress=27%
2026-01-12 14:43:11,735 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:43:12", "currency": "HKD", "indicator": "company_name", "value": "SANY HEAVY EQUIPMENT INTL", "value_date": "2026-01-12 14:43:12"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:43:12", "currency": "HKD", "indicator": "pe_ratio", "value": "20.116743525594977", "value_date": "2026-01-12 14:43:12"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:43:12", "currency": "HKD", "indicator": "pb_ratio", "value": "2.1298551816962252", "value_date": "2026-01-12 14:43:12"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:43:12", "currency": "HKD", "indicator": "market_cap", "value": "29899865843.249996", "value_date": "2026-01-12 14:43:12"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:43:12", "currency": "HKD", "indicator": "Rev_Abroad", "value": "37.287945521334656", "value_date": "2026-01-12 14:43:12"}, {"Company_code": "00631 HK Equity", "u
2026-01-12 14:43:11,735 - app.clients.bloomberg_client - INFO - ✅ Parsed 7 items from remote.
2026-01-12 14:43:11,735 - app.clients.bloomberg_client - INFO - DEBUG: basic_data before save: [{'Company_code': '00631 HK Equity', 'update_date': '2026-01-12 14:43:12', 'currency': 'HKD', 'indicator': 'company_name', 'value': 'SANY HEAVY EQUIPMENT INTL', 'value_date': '2026-01-12 14:43:12'}, {'Company_code': '00631 HK Equity', 'update_date': '2026-01-12 14:43:12', 'currency': 'HKD', 'indicator': 'pe_ratio', 'value': '20.116743525594977', 'value_date': '2026-01-12 14:43:12'}, {'Company_code': '00631 HK Equity', 'update_date': '2026-01-12 14:43:12', 'currency': 'HKD', 'indicator': 'pb_ratio', 'value': '2.1298551816962252', 'value_date': '2026-01-12 14:43:12'}, {'Company_code': '00631 HK Equity', 'update_date': '2026-01-12 14:43:12', 'currency': 'HKD', 'indicator': 'market_cap', 'value': '29899865843.249996', 'value_date': '2026-01-12 14:43:12'}, {'Company_code': '00631 HK Equity', 'update_date': '2026-01-12 14:43:12', 'currency': 'HKD', 'indicator': 'Rev_Abroad', 'value': '37.287945521334656', 'value_date': '2026-01-12 14:43:12'}, {'Company_code': '00631 HK Equity', 'update_date': '2026-01-12 14:43:12', 'currency': 'HKD', 'indicator': 'dividend_yield', 'value': '3.1351350449227', 'value_date': '2026-01-12 14:43:12'}, {'Company_code': '00631 HK Equity', 'update_date': '2026-01-12 14:43:12', 'currency': 'HKD', 'indicator': 'IPO_date', 'value': '2009-11-25', 'value_date': '2026-01-12 14:43:12'}]
2026-01-12 14:43:13,034 - app.clients.bloomberg_client - INFO - ✅ Saved 7 records to database.
2026-01-12 14:43:13,035 - app.clients.bloomberg_client - INFO - Fetching Currency Data...
2026-01-12 14:43:13,035 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=72, Msg=正在获取货币指标 (HKD)..., Progress=41%
2026-01-12 14:43:13,894 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:43:13", "currency": "HKD", "indicator": "Revenue", "value": "2152.9812", "value_date": "2016-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:43:13", "currency": "HKD", "indicator": "Net_Income", "value": "-753.2314", "value_date": "2016-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:43:13", "currency": "HKD", "indicator": "Cash_From_Operating", "value": "1557.419", "value_date": "2016-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:43:13", "currency": "HKD", "indicator": "Capital_Expenditure", "value": "-179.3705", "value_date": "2016-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:43:13", "currency": "HKD", "indicator": "Free_Cash_Flow", "value": "1378.0485", "value_date": "2016-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:43:13", "currency": "HKD", "indicator": "Dividend
2026-01-12 14:43:13,894 - app.clients.bloomberg_client - INFO - ✅ Parsed 213 items from remote.
2026-01-12 14:43:25,211 - app.clients.bloomberg_client - INFO - ✅ Saved 213 records to database.
2026-01-12 14:43:25,212 - app.clients.bloomberg_client - INFO - Fetching Non-Currency Data...
2026-01-12 14:43:25,212 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=72, Msg=正在获取非货币指标..., Progress=55%
2026-01-12 14:43:26,114 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:43:25", "currency": "HKD", "indicator": "ROE", "value": "-10.132", "value_date": "2016-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:43:25", "currency": "HKD", "indicator": "ROA", "value": "-6.0025", "value_date": "2016-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:43:25", "currency": "HKD", "indicator": "Gross_Margin", "value": "14.994", "value_date": "2016-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:43:25", "currency": "HKD", "indicator": "EBITDA_margin", "value": "-28.2708", "value_date": "2016-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:43:25", "currency": "HKD", "indicator": "Net_Profit_Margin", "value": "-34.9855", "value_date": "2016-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:43:25", "currency": "HKD", "indicator": "Tax_Rate", "value": "0.25", "value_da
2026-01-12 14:43:26,115 - app.clients.bloomberg_client - INFO - ✅ Parsed 150 items from remote.
2026-01-12 14:43:34,767 - app.clients.bloomberg_client - INFO - ✅ Saved 150 records to database.
2026-01-12 14:43:34,768 - app.clients.bloomberg_client - INFO - Fetching Price Data (Aligned)...
2026-01-12 14:43:34,769 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=72, Msg=正在获取价格指标..., Progress=69%
2026-01-12 14:43:35,176 - app.clients.bloomberg_client - WARNING - No revenue dates found. Falling back to yearly price fetch.
2026-01-12 14:43:35,719 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:43:35", "currency": "HKD", "indicator": "Last_Price", "value": "1.24", "value_date": "2016-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:43:35", "currency": "HKD", "indicator": "Market_Cap", "value": "3770.8709", "value_date": "2016-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:43:35", "currency": "HKD", "indicator": "Last_Price", "value": "1.71", "value_date": "2017-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:43:35", "currency": "HKD", "indicator": "Market_Cap", "value": "5200.1528", "value_date": "2017-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:43:35", "currency": "HKD", "indicator": "Last_Price", "value": "2.67", "value_date": "2018-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:43:35", "currency": "HKD", "indicator": "Market_Cap", "value": "8119.5368", "value
2026-01-12 14:43:35,719 - app.clients.bloomberg_client - INFO - ✅ Parsed 25 items from remote.
2026-01-12 14:43:37,996 - app.clients.bloomberg_client - INFO - ✅ Saved 25 records to database.
2026-01-12 14:43:37,996 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=72, Msg=Finalizing data..., Progress=82%
2026-01-12 14:43:38,939 - app.clients.bloomberg_client - INFO - ✅ Cleanup and View Refresh completed.
2026-01-12 14:43:38,939 - app.clients.bloomberg_client - INFO - ✅ Completed processing for 00631 HK Equity
2026-01-12 14:43:38,939 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=72, Msg=Bloomberg data sync complete, Progress=90%
2026-01-12 14:43:40,030 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=72, Msg=Bloomberg 数据同步完成, Progress=100%
2026-01-12 14:45:40,102 - app.services.bloomberg_service - WARNING - No Bloomberg data found for symbol: 00631
2026-01-12 14:45:42,034 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=73, Msg=正在初始化数据获取..., Progress=0%
2026-01-12 14:45:42,964 - app.clients.bloomberg_client - INFO - Connecting to Jupyter at http://192.168.3.161:8888...
2026-01-12 14:45:43,352 - app.clients.bloomberg_client - INFO - ✅ Authentication successful.
2026-01-12 14:45:43,383 - app.clients.bloomberg_client - INFO - ✅ Found existing kernel: bc27f3b1-b028-434a-99fa-c1cad4495a87 (remote_env)
2026-01-12 14:45:43,448 - app.clients.bloomberg_client - INFO - ✅ WebSocket connected.
2026-01-12 14:45:43,449 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=73, Msg=数据源连接成功, Progress=10%
2026-01-12 14:45:43,881 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=73, Msg=正在连接 Bloomberg 终端..., Progress=20%
2026-01-12 14:45:44,623 - app.clients.bloomberg_client - INFO - 🚀 Starting fetch for: 00631 HK Equity
2026-01-12 14:45:44,623 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=73, Msg=Starting Bloomberg session..., Progress=20%
2026-01-12 14:45:45,178 - app.clients.bloomberg_client - INFO - Using auto-detected currency: HKD
2026-01-12 14:45:45,179 - app.clients.bloomberg_client - INFO - Fetching Basic Data...
2026-01-12 14:45:45,180 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=73, Msg=Fetching Company Basic Info..., Progress=27%
2026-01-12 14:45:46,576 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:45:47", "currency": "HKD", "indicator": "company_name", "value": "SANY HEAVY EQUIPMENT INTL", "value_date": "2026-01-12 14:45:47"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:45:47", "currency": "HKD", "indicator": "pe_ratio", "value": "20.138605869994777", "value_date": "2026-01-12 14:45:47"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:45:47", "currency": "HKD", "indicator": "pb_ratio", "value": "2.1321698519332197", "value_date": "2026-01-12 14:45:47"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:45:47", "currency": "HKD", "indicator": "market_cap", "value": "29932190022.539997", "value_date": "2026-01-12 14:45:47"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:45:47", "currency": "HKD", "indicator": "Rev_Abroad", "value": "37.287945521334656", "value_date": "2026-01-12 14:45:47"}, {"Company_code": "00631 HK Equity", "u
2026-01-12 14:45:46,576 - app.clients.bloomberg_client - INFO - ✅ Parsed 7 items from remote.
2026-01-12 14:45:46,576 - app.clients.bloomberg_client - INFO - DEBUG: basic_data before save: [{'Company_code': '00631 HK Equity', 'update_date': '2026-01-12 14:45:47', 'currency': 'HKD', 'indicator': 'company_name', 'value': 'SANY HEAVY EQUIPMENT INTL', 'value_date': '2026-01-12 14:45:47'}, {'Company_code': '00631 HK Equity', 'update_date': '2026-01-12 14:45:47', 'currency': 'HKD', 'indicator': 'pe_ratio', 'value': '20.138605869994777', 'value_date': '2026-01-12 14:45:47'}, {'Company_code': '00631 HK Equity', 'update_date': '2026-01-12 14:45:47', 'currency': 'HKD', 'indicator': 'pb_ratio', 'value': '2.1321698519332197', 'value_date': '2026-01-12 14:45:47'}, {'Company_code': '00631 HK Equity', 'update_date': '2026-01-12 14:45:47', 'currency': 'HKD', 'indicator': 'market_cap', 'value': '29932190022.539997', 'value_date': '2026-01-12 14:45:47'}, {'Company_code': '00631 HK Equity', 'update_date': '2026-01-12 14:45:47', 'currency': 'HKD', 'indicator': 'Rev_Abroad', 'value': '37.287945521334656', 'value_date': '2026-01-12 14:45:47'}, {'Company_code': '00631 HK Equity', 'update_date': '2026-01-12 14:45:47', 'currency': 'HKD', 'indicator': 'dividend_yield', 'value': '3.131749369928183', 'value_date': '2026-01-12 14:45:47'}, {'Company_code': '00631 HK Equity', 'update_date': '2026-01-12 14:45:47', 'currency': 'HKD', 'indicator': 'IPO_date', 'value': '2009-11-25', 'value_date': '2026-01-12 14:45:47'}]
2026-01-12 14:45:48,142 - app.clients.bloomberg_client - INFO - ✅ Saved 7 records to database.
2026-01-12 14:45:48,142 - app.clients.bloomberg_client - INFO - Fetching Currency Data...
2026-01-12 14:45:48,142 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=73, Msg=正在获取货币指标 (HKD)..., Progress=41%
2026-01-12 14:45:50,239 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:45:49", "currency": "HKD", "indicator": "Revenue", "value": "2152.9812", "value_date": "2016-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:45:49", "currency": "HKD", "indicator": "Net_Income", "value": "-753.2314", "value_date": "2016-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:45:49", "currency": "HKD", "indicator": "Cash_From_Operating", "value": "1557.419", "value_date": "2016-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:45:49", "currency": "HKD", "indicator": "Capital_Expenditure", "value": "-179.3705", "value_date": "2016-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:45:49", "currency": "HKD", "indicator": "Free_Cash_Flow", "value": "1378.0485", "value_date": "2016-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:45:49", "currency": "HKD", "indicator": "Dividend
2026-01-12 14:45:50,239 - app.clients.bloomberg_client - INFO - ✅ Parsed 213 items from remote.
2026-01-12 14:46:03,568 - app.clients.bloomberg_client - INFO - ✅ Saved 213 records to database.
2026-01-12 14:46:03,570 - app.clients.bloomberg_client - INFO - Fetching Non-Currency Data...
2026-01-12 14:46:03,570 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=73, Msg=正在获取非货币指标..., Progress=55%
2026-01-12 14:46:04,576 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:46:04", "currency": "HKD", "indicator": "ROE", "value": "-10.132", "value_date": "2016-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:46:04", "currency": "HKD", "indicator": "ROA", "value": "-6.0025", "value_date": "2016-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:46:04", "currency": "HKD", "indicator": "Gross_Margin", "value": "14.994", "value_date": "2016-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:46:04", "currency": "HKD", "indicator": "EBITDA_margin", "value": "-28.2708", "value_date": "2016-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:46:04", "currency": "HKD", "indicator": "Net_Profit_Margin", "value": "-34.9855", "value_date": "2016-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:46:04", "currency": "HKD", "indicator": "Tax_Rate", "value": "0.25", "value_da
2026-01-12 14:46:04,576 - app.clients.bloomberg_client - INFO - ✅ Parsed 150 items from remote.
2026-01-12 14:46:16,087 - app.clients.bloomberg_client - INFO - ✅ Saved 150 records to database.
2026-01-12 14:46:16,090 - app.clients.bloomberg_client - INFO - Fetching Price Data (Aligned)...
2026-01-12 14:46:16,090 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=73, Msg=正在获取价格指标..., Progress=69%
2026-01-12 14:46:16,680 - app.clients.bloomberg_client - WARNING - No revenue dates found. Falling back to yearly price fetch.
2026-01-12 14:46:17,220 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:46:16", "currency": "HKD", "indicator": "Last_Price", "value": "1.24", "value_date": "2016-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:46:16", "currency": "HKD", "indicator": "Market_Cap", "value": "3770.8709", "value_date": "2016-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:46:16", "currency": "HKD", "indicator": "Last_Price", "value": "1.71", "value_date": "2017-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:46:16", "currency": "HKD", "indicator": "Market_Cap", "value": "5200.1528", "value_date": "2017-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:46:16", "currency": "HKD", "indicator": "Last_Price", "value": "2.67", "value_date": "2018-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:46:16", "currency": "HKD", "indicator": "Market_Cap", "value": "8119.5368", "value
2026-01-12 14:46:17,220 - app.clients.bloomberg_client - INFO - ✅ Parsed 25 items from remote.
2026-01-12 14:46:19,283 - app.clients.bloomberg_client - INFO - ✅ Saved 25 records to database.
2026-01-12 14:46:19,284 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=73, Msg=Finalizing data..., Progress=82%
2026-01-12 14:46:20,269 - app.clients.bloomberg_client - INFO - ✅ Cleanup and View Refresh completed.
2026-01-12 14:46:20,269 - app.clients.bloomberg_client - INFO - ✅ Completed processing for 00631 HK Equity
2026-01-12 14:46:20,269 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=73, Msg=Bloomberg data sync complete, Progress=90%
2026-01-12 14:46:20,840 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=73, Msg=Bloomberg 数据同步完成, Progress=100%
2026-01-12 14:47:40,832 - app.main - INFO - 🔍 [搜索] 开始搜索股票: 小松
2026-01-12 14:47:40,891 - app.main - INFO - 🤖 [搜索-LLM] 调用 gemini-2.5-flash 进行股票搜索
2026-01-12 14:47:40,892 - google_genai.models - INFO - AFC is enabled with max remote calls: 10.
2026-01-12 14:47:46,554 - httpx - INFO - HTTP Request: POST https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent "HTTP/1.1 200 OK"
2026-01-12 14:47:46,561 - app.main - INFO - ✅ [搜索-LLM] 模型响应完成, 耗时: 5.67秒, Tokens: prompt=165, completion=116, total=281
2026-01-12 14:47:46,561 - app.main - INFO - ✅ [搜索] 搜索完成, 找到 2 个结果, 总耗时: 5.73秒
2026-01-12 14:47:55,573 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=74, Msg=正在初始化数据获取..., Progress=0%
2026-01-12 14:47:56,059 - app.clients.bloomberg_client - INFO - Connecting to Jupyter at http://192.168.3.161:8888...
2026-01-12 14:47:56,715 - app.clients.bloomberg_client - INFO - ✅ Authentication successful.
2026-01-12 14:47:56,744 - app.clients.bloomberg_client - INFO - ✅ Found existing kernel: bc27f3b1-b028-434a-99fa-c1cad4495a87 (remote_env)
2026-01-12 14:47:56,806 - app.clients.bloomberg_client - INFO - ✅ WebSocket connected.
2026-01-12 14:47:56,807 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=74, Msg=数据源连接成功, Progress=10%
2026-01-12 14:47:57,821 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=74, Msg=正在连接 Bloomberg 终端..., Progress=20%
2026-01-12 14:47:58,674 - app.clients.bloomberg_client - INFO - 🚀 Starting fetch for: 6301 JP Equity
2026-01-12 14:47:58,675 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=74, Msg=Starting Bloomberg session..., Progress=20%
2026-01-12 14:47:59,347 - app.clients.bloomberg_client - INFO - Using forced currency: CNY
2026-01-12 14:47:59,348 - app.clients.bloomberg_client - INFO - Fetching Basic Data...
2026-01-12 14:47:59,348 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=74, Msg=Fetching Company Basic Info..., Progress=27%
2026-01-12 14:48:01,112 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "6301 JP Equity", "update_date": "2026-01-12 14:48:01", "currency": "CNY", "indicator": "company_name", "value": "KOMATSU LTD", "value_date": "2026-01-12 14:48:01"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 14:48:01", "currency": "CNY", "indicator": "pe_ratio", "value": "11.538204871538206", "value_date": "2026-01-12 14:48:01"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 14:48:01", "currency": "CNY", "indicator": "pb_ratio", "value": "1.4637777168999744", "value_date": "2026-01-12 14:48:01"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 14:48:01", "currency": "CNY", "indicator": "market_cap", "value": "4825676795940.001", "value_date": "2026-01-12 14:48:01"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 14:48:01", "currency": "CNY", "indicator": "Rev_Abroad", "value": "86.05716369679564", "value_date": "2026-01-12 14:48:01"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-
2026-01-12 14:48:01,113 - app.clients.bloomberg_client - INFO - ✅ Parsed 6 items from remote.
2026-01-12 14:48:01,114 - app.clients.bloomberg_client - INFO - DEBUG: basic_data before save: [{'Company_code': '6301 JP Equity', 'update_date': '2026-01-12 14:48:01', 'currency': 'CNY', 'indicator': 'company_name', 'value': 'KOMATSU LTD', 'value_date': '2026-01-12 14:48:01'}, {'Company_code': '6301 JP Equity', 'update_date': '2026-01-12 14:48:01', 'currency': 'CNY', 'indicator': 'pe_ratio', 'value': '11.538204871538206', 'value_date': '2026-01-12 14:48:01'}, {'Company_code': '6301 JP Equity', 'update_date': '2026-01-12 14:48:01', 'currency': 'CNY', 'indicator': 'pb_ratio', 'value': '1.4637777168999744', 'value_date': '2026-01-12 14:48:01'}, {'Company_code': '6301 JP Equity', 'update_date': '2026-01-12 14:48:01', 'currency': 'CNY', 'indicator': 'market_cap', 'value': '4825676795940.001', 'value_date': '2026-01-12 14:48:01'}, {'Company_code': '6301 JP Equity', 'update_date': '2026-01-12 14:48:01', 'currency': 'CNY', 'indicator': 'Rev_Abroad', 'value': '86.05716369679564', 'value_date': '2026-01-12 14:48:01'}, {'Company_code': '6301 JP Equity', 'update_date': '2026-01-12 14:48:01', 'currency': 'CNY', 'indicator': 'dividend_yield', 'value': '3.894351262772315', 'value_date': '2026-01-12 14:48:01'}]
2026-01-12 14:48:02,208 - app.clients.bloomberg_client - INFO - ✅ Saved 6 records to database.
2026-01-12 14:48:02,208 - app.clients.bloomberg_client - INFO - Fetching Currency Data...
2026-01-12 14:48:02,209 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=74, Msg=正在获取货币指标 (CNY)..., Progress=41%
2026-01-12 14:48:03,577 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "6301 JP Equity", "update_date": "2026-01-12 14:48:02", "currency": "CNY", "indicator": "Revenue", "value": "98388.5158", "value_date": "2016-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 14:48:02", "currency": "CNY", "indicator": "Net_Income", "value": "7289.1658", "value_date": "2016-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 14:48:02", "currency": "CNY", "indicator": "Cash_From_Operating", "value": "16953.5985", "value_date": "2016-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 14:48:02", "currency": "CNY", "indicator": "Capital_Expenditure", "value": "-8830.1561", "value_date": "2016-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 14:48:02", "currency": "CNY", "indicator": "Free_Cash_Flow", "value": "8123.4424", "value_date": "2016-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 14:48:02", "currency": "CNY", "indicator": "Dividends_
2026-01-12 14:48:03,578 - app.clients.bloomberg_client - INFO - ✅ Parsed 248 items from remote.
2026-01-12 14:48:18,179 - app.clients.bloomberg_client - INFO - ✅ Saved 248 records to database.
2026-01-12 14:48:18,181 - app.clients.bloomberg_client - INFO - Fetching Non-Currency Data...
2026-01-12 14:48:18,181 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=74, Msg=正在获取非货币指标..., Progress=55%
2026-01-12 14:48:19,384 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "6301 JP Equity", "update_date": "2026-01-12 14:48:18", "currency": "CNY", "indicator": "ROE", "value": "9.0222", "value_date": "2016-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 14:48:18", "currency": "CNY", "indicator": "ROA", "value": "5.0776", "value_date": "2016-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 14:48:18", "currency": "CNY", "indicator": "ROCE", "value": "10.4918", "value_date": "2016-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 14:48:18", "currency": "CNY", "indicator": "Gross_Margin", "value": "29.0675", "value_date": "2016-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 14:48:18", "currency": "CNY", "indicator": "EBITDA_margin", "value": "17.3073", "value_date": "2016-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 14:48:18", "currency": "CNY", "indicator": "Net_Profit_Margin", "value": "7.4086", "value_date": "2016-
2026-01-12 14:48:19,384 - app.clients.bloomberg_client - INFO - ✅ Parsed 200 items from remote.
2026-01-12 14:48:30,521 - app.clients.bloomberg_client - INFO - ✅ Saved 200 records to database.
2026-01-12 14:48:30,522 - app.clients.bloomberg_client - INFO - Fetching Price Data (Aligned)...
2026-01-12 14:48:30,523 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=74, Msg=正在获取价格指标..., Progress=69%
2026-01-12 14:48:31,242 - app.clients.bloomberg_client - WARNING - No revenue dates found. Falling back to yearly price fetch.
2026-01-12 14:48:31,965 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "6301 JP Equity", "update_date": "2026-01-12 14:48:31", "currency": "CNY", "indicator": "Last_Price", "value": "109.89665", "value_date": "2016-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 14:48:31", "currency": "CNY", "indicator": "Market_Cap", "value": "6126.6803", "value_date": "2016-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 14:48:31", "currency": "CNY", "indicator": "Last_Price", "value": "179.2773", "value_date": "2017-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 14:48:31", "currency": "CNY", "indicator": "Market_Cap", "value": "10766.6315", "value_date": "2017-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 14:48:31", "currency": "CNY", "indicator": "Last_Price", "value": "209.97492", "value_date": "2018-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 14:48:31", "currency": "CNY", "indicator": "Market_Cap", "value": "12081.628
2026-01-12 14:48:31,966 - app.clients.bloomberg_client - INFO - ✅ Parsed 20 items from remote.
2026-01-12 14:48:34,609 - app.clients.bloomberg_client - INFO - ✅ Saved 20 records to database.
2026-01-12 14:48:34,610 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=74, Msg=Finalizing data..., Progress=82%
2026-01-12 14:48:35,541 - app.clients.bloomberg_client - INFO - ✅ Cleanup and View Refresh completed.
2026-01-12 14:48:35,542 - app.clients.bloomberg_client - INFO - ✅ Completed processing for 6301 JP Equity
2026-01-12 14:48:35,542 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=74, Msg=Bloomberg data sync complete, Progress=90%
2026-01-12 14:48:36,209 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=74, Msg=Bloomberg 数据同步完成, Progress=100%
2026-01-12 14:49:44,963 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=75, Msg=正在初始化数据获取..., Progress=0%
2026-01-12 14:49:45,392 - app.clients.bloomberg_client - INFO - Connecting to Jupyter at http://192.168.3.161:8888...
2026-01-12 14:49:45,772 - app.clients.bloomberg_client - INFO - ✅ Authentication successful.
2026-01-12 14:49:45,800 - app.clients.bloomberg_client - INFO - ✅ Found existing kernel: bc27f3b1-b028-434a-99fa-c1cad4495a87 (remote_env)
2026-01-12 14:49:46,296 - app.clients.bloomberg_client - INFO - ✅ WebSocket connected.
2026-01-12 14:49:46,297 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=75, Msg=数据源连接成功, Progress=10%
2026-01-12 14:49:46,646 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=75, Msg=正在连接 Bloomberg 终端..., Progress=20%
2026-01-12 14:49:47,067 - app.clients.bloomberg_client - INFO - 🚀 Starting fetch for: 6301 JP Equity
2026-01-12 14:49:47,067 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=75, Msg=Starting Bloomberg session..., Progress=20%
2026-01-12 14:49:47,538 - app.clients.bloomberg_client - INFO - Using auto-detected currency: JPY
2026-01-12 14:49:47,538 - app.clients.bloomberg_client - INFO - Fetching Basic Data...
2026-01-12 14:49:47,539 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=75, Msg=Fetching Company Basic Info..., Progress=27%
2026-01-12 14:49:48,960 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "6301 JP Equity", "update_date": "2026-01-12 14:49:49", "currency": "JPY", "indicator": "company_name", "value": "KOMATSU LTD", "value_date": "2026-01-12 14:49:49"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 14:49:49", "currency": "JPY", "indicator": "pe_ratio", "value": "11.538204871538206", "value_date": "2026-01-12 14:49:49"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 14:49:49", "currency": "JPY", "indicator": "pb_ratio", "value": "1.4637777168999744", "value_date": "2026-01-12 14:49:49"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 14:49:49", "currency": "JPY", "indicator": "market_cap", "value": "4825676795940.001", "value_date": "2026-01-12 14:49:49"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 14:49:49", "currency": "JPY", "indicator": "Rev_Abroad", "value": "86.05716369679564", "value_date": "2026-01-12 14:49:49"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-
2026-01-12 14:49:48,961 - app.clients.bloomberg_client - INFO - ✅ Parsed 6 items from remote.
2026-01-12 14:49:48,961 - app.clients.bloomberg_client - INFO - DEBUG: basic_data before save: [{'Company_code': '6301 JP Equity', 'update_date': '2026-01-12 14:49:49', 'currency': 'JPY', 'indicator': 'company_name', 'value': 'KOMATSU LTD', 'value_date': '2026-01-12 14:49:49'}, {'Company_code': '6301 JP Equity', 'update_date': '2026-01-12 14:49:49', 'currency': 'JPY', 'indicator': 'pe_ratio', 'value': '11.538204871538206', 'value_date': '2026-01-12 14:49:49'}, {'Company_code': '6301 JP Equity', 'update_date': '2026-01-12 14:49:49', 'currency': 'JPY', 'indicator': 'pb_ratio', 'value': '1.4637777168999744', 'value_date': '2026-01-12 14:49:49'}, {'Company_code': '6301 JP Equity', 'update_date': '2026-01-12 14:49:49', 'currency': 'JPY', 'indicator': 'market_cap', 'value': '4825676795940.001', 'value_date': '2026-01-12 14:49:49'}, {'Company_code': '6301 JP Equity', 'update_date': '2026-01-12 14:49:49', 'currency': 'JPY', 'indicator': 'Rev_Abroad', 'value': '86.05716369679564', 'value_date': '2026-01-12 14:49:49'}, {'Company_code': '6301 JP Equity', 'update_date': '2026-01-12 14:49:49', 'currency': 'JPY', 'indicator': 'dividend_yield', 'value': '3.894351262772315', 'value_date': '2026-01-12 14:49:49'}]
2026-01-12 14:49:49,780 - app.clients.bloomberg_client - INFO - ✅ Saved 6 records to database.
2026-01-12 14:49:49,781 - app.clients.bloomberg_client - INFO - Fetching Currency Data...
2026-01-12 14:49:49,781 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=75, Msg=正在获取货币指标 (JPY)..., Progress=41%
2026-01-12 14:49:50,861 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "6301 JP Equity", "update_date": "2026-01-12 14:49:50", "currency": "JPY", "indicator": "Revenue", "value": "1854964.0", "value_date": "2016-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 14:49:50", "currency": "JPY", "indicator": "Net_Income", "value": "137426.0", "value_date": "2016-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 14:49:50", "currency": "JPY", "indicator": "Cash_From_Operating", "value": "319634.0", "value_date": "2016-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 14:49:50", "currency": "JPY", "indicator": "Capital_Expenditure", "value": "-166479.0", "value_date": "2016-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 14:49:50", "currency": "JPY", "indicator": "Free_Cash_Flow", "value": "153155.0", "value_date": "2016-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 14:49:50", "currency": "JPY", "indicator": "Dividends_Paid",
2026-01-12 14:49:50,862 - app.clients.bloomberg_client - INFO - ✅ Parsed 248 items from remote.
2026-01-12 14:50:05,970 - app.clients.bloomberg_client - INFO - ✅ Saved 248 records to database.
2026-01-12 14:50:05,972 - app.clients.bloomberg_client - INFO - Fetching Non-Currency Data...
2026-01-12 14:50:05,973 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=75, Msg=正在获取非货币指标..., Progress=55%
2026-01-12 14:50:08,245 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "6301 JP Equity", "update_date": "2026-01-12 14:50:07", "currency": "JPY", "indicator": "ROE", "value": "9.0222", "value_date": "2016-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 14:50:07", "currency": "JPY", "indicator": "ROA", "value": "5.0776", "value_date": "2016-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 14:50:07", "currency": "JPY", "indicator": "ROCE", "value": "10.4918", "value_date": "2016-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 14:50:07", "currency": "JPY", "indicator": "Gross_Margin", "value": "29.0675", "value_date": "2016-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 14:50:07", "currency": "JPY", "indicator": "EBITDA_margin", "value": "17.3073", "value_date": "2016-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 14:50:07", "currency": "JPY", "indicator": "Net_Profit_Margin", "value": "7.4086", "value_date": "2016-
2026-01-12 14:50:08,245 - app.clients.bloomberg_client - INFO - ✅ Parsed 200 items from remote.
2026-01-12 14:50:21,679 - app.clients.bloomberg_client - INFO - ✅ Saved 200 records to database.
2026-01-12 14:50:21,680 - app.clients.bloomberg_client - INFO - Fetching Price Data (Aligned)...
2026-01-12 14:50:21,680 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=75, Msg=正在获取价格指标..., Progress=69%
2026-01-12 14:50:22,256 - app.clients.bloomberg_client - WARNING - No revenue dates found. Falling back to yearly price fetch.
2026-01-12 14:50:23,865 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "6301 JP Equity", "update_date": "2026-01-12 14:50:22", "currency": "JPY", "indicator": "Last_Price", "value": "1916.0", "value_date": "2016-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 14:50:22", "currency": "JPY", "indicator": "Market_Cap", "value": "1862290.02", "value_date": "2016-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 14:50:22", "currency": "JPY", "indicator": "Dividend_Yield", "value": "3.0271", "value_date": "2016-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 14:50:22", "currency": "JPY", "indicator": "Last_Price", "value": "2901.5", "value_date": "2017-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 14:50:22", "currency": "JPY", "indicator": "Market_Cap", "value": "2820164.1404", "value_date": "2017-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 14:50:22", "currency": "JPY", "indicator": "Dividend_Yield", "value": "1.999"
2026-01-12 14:50:23,866 - app.clients.bloomberg_client - INFO - ✅ Parsed 30 items from remote.
2026-01-12 14:50:26,009 - app.clients.bloomberg_client - INFO - ✅ Saved 30 records to database.
2026-01-12 14:50:26,009 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=75, Msg=Finalizing data..., Progress=82%
2026-01-12 14:50:27,009 - app.clients.bloomberg_client - INFO - ✅ Cleanup and View Refresh completed.
2026-01-12 14:50:27,009 - app.clients.bloomberg_client - INFO - ✅ Completed processing for 6301 JP Equity
2026-01-12 14:50:27,009 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=75, Msg=Bloomberg data sync complete, Progress=90%
2026-01-12 14:50:27,898 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=75, Msg=Bloomberg 数据同步完成, Progress=100%
2026-01-12 14:51:20,076 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=76, Msg=正在初始化数据获取..., Progress=0%
2026-01-12 14:51:20,584 - app.clients.bloomberg_client - INFO - Connecting to Jupyter at http://192.168.3.161:8888...
2026-01-12 14:51:21,537 - app.clients.bloomberg_client - INFO - ✅ Authentication successful.
2026-01-12 14:51:21,567 - app.clients.bloomberg_client - INFO - ✅ Found existing kernel: bc27f3b1-b028-434a-99fa-c1cad4495a87 (remote_env)
2026-01-12 14:51:21,624 - app.clients.bloomberg_client - INFO - ✅ WebSocket connected.
2026-01-12 14:51:21,628 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=76, Msg=数据源连接成功, Progress=10%
2026-01-12 14:51:22,917 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=76, Msg=正在连接 Bloomberg 终端..., Progress=20%
2026-01-12 14:51:23,220 - app.clients.bloomberg_client - INFO - 🚀 Starting fetch for: 00631 HK Equity
2026-01-12 14:51:23,220 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=76, Msg=Starting Bloomberg session..., Progress=20%
2026-01-12 14:51:24,335 - app.clients.bloomberg_client - INFO - Using auto-detected currency: HKD
2026-01-12 14:51:24,335 - app.clients.bloomberg_client - INFO - Fetching Basic Data...
2026-01-12 14:51:24,335 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=76, Msg=Fetching Company Basic Info..., Progress=27%
2026-01-12 14:51:25,182 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:51:25", "currency": "HKD", "indicator": "company_name", "value": "SANY HEAVY EQUIPMENT INTL", "value_date": "2026-01-12 14:51:25"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:51:25", "currency": "HKD", "indicator": "pe_ratio", "value": "20.029578510589843", "value_date": "2026-01-12 14:51:25"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:51:25", "currency": "HKD", "indicator": "pb_ratio", "value": "2.120626607566665", "value_date": "2026-01-12 14:51:25"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:51:25", "currency": "HKD", "indicator": "market_cap", "value": "29770569126.09", "value_date": "2026-01-12 14:51:25"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:51:25", "currency": "HKD", "indicator": "Rev_Abroad", "value": "37.287945521334656", "value_date": "2026-01-12 14:51:25"}, {"Company_code": "00631 HK Equity", "update
2026-01-12 14:51:25,183 - app.clients.bloomberg_client - INFO - ✅ Parsed 7 items from remote.
2026-01-12 14:51:25,183 - app.clients.bloomberg_client - INFO - DEBUG: basic_data before save: [{'Company_code': '00631 HK Equity', 'update_date': '2026-01-12 14:51:25', 'currency': 'HKD', 'indicator': 'company_name', 'value': 'SANY HEAVY EQUIPMENT INTL', 'value_date': '2026-01-12 14:51:25'}, {'Company_code': '00631 HK Equity', 'update_date': '2026-01-12 14:51:25', 'currency': 'HKD', 'indicator': 'pe_ratio', 'value': '20.029578510589843', 'value_date': '2026-01-12 14:51:25'}, {'Company_code': '00631 HK Equity', 'update_date': '2026-01-12 14:51:25', 'currency': 'HKD', 'indicator': 'pb_ratio', 'value': '2.120626607566665', 'value_date': '2026-01-12 14:51:25'}, {'Company_code': '00631 HK Equity', 'update_date': '2026-01-12 14:51:25', 'currency': 'HKD', 'indicator': 'market_cap', 'value': '29770569126.09', 'value_date': '2026-01-12 14:51:25'}, {'Company_code': '00631 HK Equity', 'update_date': '2026-01-12 14:51:25', 'currency': 'HKD', 'indicator': 'Rev_Abroad', 'value': '37.287945521334656', 'value_date': '2026-01-12 14:51:25'}, {'Company_code': '00631 HK Equity', 'update_date': '2026-01-12 14:51:25', 'currency': 'HKD', 'indicator': 'dividend_yield', 'value': '3.1487512666161748', 'value_date': '2026-01-12 14:51:25'}, {'Company_code': '00631 HK Equity', 'update_date': '2026-01-12 14:51:25', 'currency': 'HKD', 'indicator': 'IPO_date', 'value': '2009-11-25', 'value_date': '2026-01-12 14:51:25'}]
2026-01-12 14:51:26,622 - app.clients.bloomberg_client - INFO - ✅ Saved 7 records to database.
2026-01-12 14:51:26,624 - app.clients.bloomberg_client - INFO - Fetching Currency Data...
2026-01-12 14:51:26,624 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=76, Msg=正在获取货币指标 (HKD)..., Progress=41%
2026-01-12 14:51:27,834 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:51:27", "currency": "HKD", "indicator": "Revenue", "value": "2152.9812", "value_date": "2016-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:51:27", "currency": "HKD", "indicator": "Net_Income", "value": "-753.2314", "value_date": "2016-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:51:27", "currency": "HKD", "indicator": "Cash_From_Operating", "value": "1557.419", "value_date": "2016-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:51:27", "currency": "HKD", "indicator": "Capital_Expenditure", "value": "-179.3705", "value_date": "2016-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:51:27", "currency": "HKD", "indicator": "Free_Cash_Flow", "value": "1378.0485", "value_date": "2016-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:51:27", "currency": "HKD", "indicator": "Dividend
2026-01-12 14:51:27,835 - app.clients.bloomberg_client - INFO - ✅ Parsed 213 items from remote.
2026-01-12 14:51:37,677 - app.clients.bloomberg_client - INFO - ✅ Saved 213 records to database.
2026-01-12 14:51:37,679 - app.clients.bloomberg_client - INFO - Fetching Non-Currency Data...
2026-01-12 14:51:37,679 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=76, Msg=正在获取非货币指标..., Progress=55%
2026-01-12 14:51:39,919 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:51:39", "currency": "HKD", "indicator": "ROE", "value": "-10.132", "value_date": "2016-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:51:39", "currency": "HKD", "indicator": "ROA", "value": "-6.0025", "value_date": "2016-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:51:39", "currency": "HKD", "indicator": "Gross_Margin", "value": "14.994", "value_date": "2016-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:51:39", "currency": "HKD", "indicator": "EBITDA_margin", "value": "-28.2708", "value_date": "2016-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:51:39", "currency": "HKD", "indicator": "Net_Profit_Margin", "value": "-34.9855", "value_date": "2016-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:51:39", "currency": "HKD", "indicator": "Tax_Rate", "value": "0.25", "value_da
2026-01-12 14:51:39,919 - app.clients.bloomberg_client - INFO - ✅ Parsed 150 items from remote.
2026-01-12 14:51:50,298 - app.clients.bloomberg_client - INFO - ✅ Saved 150 records to database.
2026-01-12 14:51:50,300 - app.clients.bloomberg_client - INFO - Fetching Price Data (Aligned)...
2026-01-12 14:51:50,300 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=76, Msg=正在获取价格指标..., Progress=69%
2026-01-12 14:51:50,718 - app.clients.bloomberg_client - WARNING - No revenue dates found. Falling back to yearly price fetch.
2026-01-12 14:51:51,380 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:51:50", "currency": "HKD", "indicator": "Last_Price", "value": "1.24", "value_date": "2016-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:51:50", "currency": "HKD", "indicator": "Market_Cap", "value": "3770.8709", "value_date": "2016-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:51:50", "currency": "HKD", "indicator": "Last_Price", "value": "1.71", "value_date": "2017-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:51:50", "currency": "HKD", "indicator": "Market_Cap", "value": "5200.1528", "value_date": "2017-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:51:50", "currency": "HKD", "indicator": "Last_Price", "value": "2.67", "value_date": "2018-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 14:51:50", "currency": "HKD", "indicator": "Market_Cap", "value": "8119.5368", "value
2026-01-12 14:51:51,380 - app.clients.bloomberg_client - INFO - ✅ Parsed 25 items from remote.
2026-01-12 14:51:53,217 - app.clients.bloomberg_client - INFO - ✅ Saved 25 records to database.
2026-01-12 14:51:53,218 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=76, Msg=Finalizing data..., Progress=82%
2026-01-12 14:51:54,383 - app.clients.bloomberg_client - INFO - ✅ Cleanup and View Refresh completed.
2026-01-12 14:51:54,384 - app.clients.bloomberg_client - INFO - ✅ Completed processing for 00631 HK Equity
2026-01-12 14:51:54,384 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=76, Msg=Bloomberg data sync complete, Progress=90%
2026-01-12 14:51:54,664 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=76, Msg=Bloomberg 数据同步完成, Progress=100%
2026-01-12 15:00:38,249 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=77, Msg=正在初始化数据获取..., Progress=0%
2026-01-12 15:00:39,187 - app.clients.bloomberg_client - INFO - Connecting to Jupyter at http://192.168.3.161:8888...
2026-01-12 15:00:39,747 - app.clients.bloomberg_client - INFO - ✅ Authentication successful.
2026-01-12 15:00:39,779 - app.clients.bloomberg_client - INFO - ✅ Found existing kernel: bc27f3b1-b028-434a-99fa-c1cad4495a87 (remote_env)
2026-01-12 15:00:39,850 - app.clients.bloomberg_client - INFO - ✅ WebSocket connected.
2026-01-12 15:00:39,850 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=77, Msg=数据源连接成功, Progress=10%
2026-01-12 15:00:40,301 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=77, Msg=正在连接 Bloomberg 终端..., Progress=20%
2026-01-12 15:00:40,995 - app.clients.bloomberg_client - INFO - 🚀 Starting fetch for: 6301 JP Equity
2026-01-12 15:00:40,995 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=77, Msg=Starting Bloomberg session..., Progress=20%
2026-01-12 15:00:41,901 - app.clients.bloomberg_client - INFO - Using forced currency: CNY
2026-01-12 15:00:41,901 - app.clients.bloomberg_client - INFO - Fetching Basic Data...
2026-01-12 15:00:41,901 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=77, Msg=Fetching Company Basic Info..., Progress=27%
2026-01-12 15:00:43,438 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "6301 JP Equity", "update_date": "2026-01-12 15:00:43", "currency": "CNY", "indicator": "company_name", "value": "KOMATSU LTD", "value_date": "2026-01-12 15:00:43"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 15:00:43", "currency": "CNY", "indicator": "pe_ratio", "value": "11.538204871538206", "value_date": "2026-01-12 15:00:43"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 15:00:43", "currency": "CNY", "indicator": "pb_ratio", "value": "1.4637777168999744", "value_date": "2026-01-12 15:00:43"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 15:00:43", "currency": "CNY", "indicator": "market_cap", "value": "4825676795940.001", "value_date": "2026-01-12 15:00:43"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 15:00:43", "currency": "CNY", "indicator": "Rev_Abroad", "value": "86.05716369679564", "value_date": "2026-01-12 15:00:43"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-
2026-01-12 15:00:43,438 - app.clients.bloomberg_client - INFO - ✅ Parsed 6 items from remote.
2026-01-12 15:00:43,439 - app.clients.bloomberg_client - INFO - DEBUG: basic_data before save: [{'Company_code': '6301 JP Equity', 'update_date': '2026-01-12 15:00:43', 'currency': 'CNY', 'indicator': 'company_name', 'value': 'KOMATSU LTD', 'value_date': '2026-01-12 15:00:43'}, {'Company_code': '6301 JP Equity', 'update_date': '2026-01-12 15:00:43', 'currency': 'CNY', 'indicator': 'pe_ratio', 'value': '11.538204871538206', 'value_date': '2026-01-12 15:00:43'}, {'Company_code': '6301 JP Equity', 'update_date': '2026-01-12 15:00:43', 'currency': 'CNY', 'indicator': 'pb_ratio', 'value': '1.4637777168999744', 'value_date': '2026-01-12 15:00:43'}, {'Company_code': '6301 JP Equity', 'update_date': '2026-01-12 15:00:43', 'currency': 'CNY', 'indicator': 'market_cap', 'value': '4825676795940.001', 'value_date': '2026-01-12 15:00:43'}, {'Company_code': '6301 JP Equity', 'update_date': '2026-01-12 15:00:43', 'currency': 'CNY', 'indicator': 'Rev_Abroad', 'value': '86.05716369679564', 'value_date': '2026-01-12 15:00:43'}, {'Company_code': '6301 JP Equity', 'update_date': '2026-01-12 15:00:43', 'currency': 'CNY', 'indicator': 'dividend_yield', 'value': '3.894351262772315', 'value_date': '2026-01-12 15:00:43'}]
2026-01-12 15:00:45,449 - app.clients.bloomberg_client - INFO - ✅ Saved 6 records to database.
2026-01-12 15:00:45,450 - app.clients.bloomberg_client - INFO - Fetching Currency Data...
2026-01-12 15:00:45,450 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=77, Msg=正在获取货币指标 (CNY)..., Progress=41%
2026-01-12 15:00:46,868 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "6301 JP Equity", "update_date": "2026-01-12 15:00:46", "currency": "CNY", "indicator": "Revenue", "value": "98388.5158", "value_date": "2016-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 15:00:46", "currency": "CNY", "indicator": "Net_Income", "value": "7289.1658", "value_date": "2016-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 15:00:46", "currency": "CNY", "indicator": "Cash_From_Operating", "value": "16953.5985", "value_date": "2016-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 15:00:46", "currency": "CNY", "indicator": "Capital_Expenditure", "value": "-8830.1561", "value_date": "2016-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 15:00:46", "currency": "CNY", "indicator": "Free_Cash_Flow", "value": "8123.4424", "value_date": "2016-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 15:00:46", "currency": "CNY", "indicator": "Dividends_
2026-01-12 15:00:46,869 - app.clients.bloomberg_client - INFO - ✅ Parsed 248 items from remote.
2026-01-12 15:01:02,833 - app.clients.bloomberg_client - INFO - ✅ Saved 248 records to database.
2026-01-12 15:01:02,835 - app.clients.bloomberg_client - INFO - Fetching Non-Currency Data...
2026-01-12 15:01:02,835 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=77, Msg=正在获取非货币指标..., Progress=55%
2026-01-12 15:01:03,945 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "6301 JP Equity", "update_date": "2026-01-12 15:01:03", "currency": "CNY", "indicator": "ROE", "value": "9.0222", "value_date": "2016-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 15:01:03", "currency": "CNY", "indicator": "ROA", "value": "5.0776", "value_date": "2016-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 15:01:03", "currency": "CNY", "indicator": "ROCE", "value": "10.4918", "value_date": "2016-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 15:01:03", "currency": "CNY", "indicator": "Gross_Margin", "value": "29.0675", "value_date": "2016-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 15:01:03", "currency": "CNY", "indicator": "EBITDA_margin", "value": "17.3073", "value_date": "2016-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 15:01:03", "currency": "CNY", "indicator": "Net_Profit_Margin", "value": "7.4086", "value_date": "2016-
2026-01-12 15:01:03,946 - app.clients.bloomberg_client - INFO - ✅ Parsed 200 items from remote.
2026-01-12 15:01:16,421 - app.clients.bloomberg_client - INFO - ✅ Saved 200 records to database.
2026-01-12 15:01:16,422 - app.clients.bloomberg_client - INFO - Fetching Price Data (Aligned)...
2026-01-12 15:01:16,422 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=77, Msg=正在获取价格指标..., Progress=69%
2026-01-12 15:01:17,447 - app.clients.bloomberg_client - WARNING - No revenue dates found. Falling back to yearly price fetch (Dec 31).
2026-01-12 15:01:30,781 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "6301 JP Equity", "update_date": "2026-01-12 15:01:17", "currency": "CNY", "indicator": "Last_Price", "value": "223.73673", "value_date": "2025-12-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 15:01:17", "currency": "CNY", "indicator": "Market_Cap", "value": "208151.3659", "value_date": "2025-12-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 15:01:17", "currency": "CNY", "indicator": "Dividend_Yield", "value": "4.04", "value_date": "2025-12-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 15:01:17", "currency": "CNY", "indicator": "Last_Price", "value": "202.05148", "value_date": "2024-12-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 15:01:17", "currency": "CNY", "indicator": "Market_Cap", "value": "192141.4848", "value_date": "2024-12-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 15:01:17", "currency": "CNY", "indicator": "Dividend_Yield", "value": "4.
2026-01-12 15:01:30,783 - app.clients.bloomberg_client - INFO - ✅ Parsed 30 items from remote.
2026-01-12 15:01:33,358 - app.clients.bloomberg_client - INFO - ✅ Saved 30 records to database.
2026-01-12 15:01:33,358 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=77, Msg=Finalizing data..., Progress=82%
2026-01-12 15:01:34,774 - app.clients.bloomberg_client - INFO - ✅ Cleanup and View Refresh completed.
2026-01-12 15:01:34,774 - app.clients.bloomberg_client - INFO - ✅ Completed processing for 6301 JP Equity
2026-01-12 15:01:34,775 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=77, Msg=Bloomberg data sync complete, Progress=90%
2026-01-12 15:01:35,316 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=77, Msg=Bloomberg 数据同步完成, Progress=100%
2026-01-12 15:03:03,280 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=78, Msg=正在初始化数据获取..., Progress=0%
2026-01-12 15:03:04,370 - app.clients.bloomberg_client - INFO - Connecting to Jupyter at http://192.168.3.161:8888...
2026-01-12 15:03:04,916 - app.clients.bloomberg_client - INFO - ✅ Authentication successful.
2026-01-12 15:03:04,945 - app.clients.bloomberg_client - INFO - ✅ Found existing kernel: bc27f3b1-b028-434a-99fa-c1cad4495a87 (remote_env)
2026-01-12 15:03:05,071 - app.clients.bloomberg_client - INFO - ✅ WebSocket connected.
2026-01-12 15:03:05,196 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=78, Msg=数据源连接成功, Progress=10%
2026-01-12 15:03:06,469 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=78, Msg=正在连接 Bloomberg 终端..., Progress=20%
2026-01-12 15:03:06,746 - app.clients.bloomberg_client - INFO - 🚀 Starting fetch for: 6301 JP Equity
2026-01-12 15:03:06,746 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=78, Msg=Starting Bloomberg session..., Progress=20%
2026-01-12 15:03:07,404 - app.clients.bloomberg_client - INFO - Using forced currency: CNY
2026-01-12 15:03:07,405 - app.clients.bloomberg_client - INFO - Fetching Basic Data...
2026-01-12 15:03:07,406 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=78, Msg=Fetching Company Basic Info..., Progress=27%
2026-01-12 15:03:08,864 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "6301 JP Equity", "update_date": "2026-01-12 15:03:09", "currency": "CNY", "indicator": "company_name", "value": "KOMATSU LTD", "value_date": "2026-01-12 15:03:09"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 15:03:09", "currency": "CNY", "indicator": "pe_ratio", "value": "11.538204871538206", "value_date": "2026-01-12 15:03:09"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 15:03:09", "currency": "CNY", "indicator": "pb_ratio", "value": "1.4637777168999744", "value_date": "2026-01-12 15:03:09"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 15:03:09", "currency": "CNY", "indicator": "market_cap", "value": "4825676795940.001", "value_date": "2026-01-12 15:03:09"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 15:03:09", "currency": "CNY", "indicator": "Rev_Abroad", "value": "86.05716369679564", "value_date": "2026-01-12 15:03:09"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-
2026-01-12 15:03:08,865 - app.clients.bloomberg_client - INFO - ✅ Parsed 6 items from remote.
2026-01-12 15:03:08,865 - app.clients.bloomberg_client - INFO - DEBUG: basic_data before save: [{'Company_code': '6301 JP Equity', 'update_date': '2026-01-12 15:03:09', 'currency': 'CNY', 'indicator': 'company_name', 'value': 'KOMATSU LTD', 'value_date': '2026-01-12 15:03:09'}, {'Company_code': '6301 JP Equity', 'update_date': '2026-01-12 15:03:09', 'currency': 'CNY', 'indicator': 'pe_ratio', 'value': '11.538204871538206', 'value_date': '2026-01-12 15:03:09'}, {'Company_code': '6301 JP Equity', 'update_date': '2026-01-12 15:03:09', 'currency': 'CNY', 'indicator': 'pb_ratio', 'value': '1.4637777168999744', 'value_date': '2026-01-12 15:03:09'}, {'Company_code': '6301 JP Equity', 'update_date': '2026-01-12 15:03:09', 'currency': 'CNY', 'indicator': 'market_cap', 'value': '4825676795940.001', 'value_date': '2026-01-12 15:03:09'}, {'Company_code': '6301 JP Equity', 'update_date': '2026-01-12 15:03:09', 'currency': 'CNY', 'indicator': 'Rev_Abroad', 'value': '86.05716369679564', 'value_date': '2026-01-12 15:03:09'}, {'Company_code': '6301 JP Equity', 'update_date': '2026-01-12 15:03:09', 'currency': 'CNY', 'indicator': 'dividend_yield', 'value': '3.894351262772315', 'value_date': '2026-01-12 15:03:09'}]
2026-01-12 15:03:10,135 - app.clients.bloomberg_client - INFO - ✅ Saved 6 records to database.
2026-01-12 15:03:10,135 - app.clients.bloomberg_client - INFO - Fetching Currency Data...
2026-01-12 15:03:10,136 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=78, Msg=正在获取货币指标 (CNY)..., Progress=41%
2026-01-12 15:03:11,570 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "6301 JP Equity", "update_date": "2026-01-12 15:03:10", "currency": "CNY", "indicator": "Revenue", "value": "98388.5158", "value_date": "2016-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 15:03:10", "currency": "CNY", "indicator": "Net_Income", "value": "7289.1658", "value_date": "2016-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 15:03:10", "currency": "CNY", "indicator": "Cash_From_Operating", "value": "16953.5985", "value_date": "2016-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 15:03:10", "currency": "CNY", "indicator": "Capital_Expenditure", "value": "-8830.1561", "value_date": "2016-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 15:03:10", "currency": "CNY", "indicator": "Free_Cash_Flow", "value": "8123.4424", "value_date": "2016-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 15:03:10", "currency": "CNY", "indicator": "Dividends_
2026-01-12 15:03:11,570 - app.clients.bloomberg_client - INFO - ✅ Parsed 248 items from remote.
2026-01-12 15:03:29,582 - app.clients.bloomberg_client - INFO - ✅ Saved 248 records to database.
2026-01-12 15:03:29,585 - app.clients.bloomberg_client - INFO - Fetching Non-Currency Data...
2026-01-12 15:03:29,585 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=78, Msg=正在获取非货币指标..., Progress=55%
2026-01-12 15:03:30,903 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "6301 JP Equity", "update_date": "2026-01-12 15:03:30", "currency": "CNY", "indicator": "ROE", "value": "9.0222", "value_date": "2016-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 15:03:30", "currency": "CNY", "indicator": "ROA", "value": "5.0776", "value_date": "2016-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 15:03:30", "currency": "CNY", "indicator": "ROCE", "value": "10.4918", "value_date": "2016-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 15:03:30", "currency": "CNY", "indicator": "Gross_Margin", "value": "29.0675", "value_date": "2016-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 15:03:30", "currency": "CNY", "indicator": "EBITDA_margin", "value": "17.3073", "value_date": "2016-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 15:03:30", "currency": "CNY", "indicator": "Net_Profit_Margin", "value": "7.4086", "value_date": "2016-
2026-01-12 15:03:30,904 - app.clients.bloomberg_client - INFO - ✅ Parsed 200 items from remote.
2026-01-12 15:03:42,872 - app.clients.bloomberg_client - INFO - ✅ Saved 200 records to database.
2026-01-12 15:03:42,874 - app.clients.bloomberg_client - INFO - Fetching Price Data (Aligned)...
2026-01-12 15:03:42,874 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=78, Msg=正在获取价格指标..., Progress=69%
2026-01-12 15:03:44,697 - app.clients.bloomberg_client - INFO - Found 10 revenue reporting dates. Fetching aligned price data...
2026-01-12 15:03:57,466 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "6301 JP Equity", "update_date": "2026-01-12 15:03:44", "currency": "CNY", "indicator": "Last_Price", "value": "208.47187", "value_date": "2025-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 15:03:44", "currency": "CNY", "indicator": "Market_Cap", "value": "198246.9783", "value_date": "2025-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 15:03:44", "currency": "CNY", "indicator": "Dividend_Yield", "value": "4.4124", "value_date": "2025-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 15:03:44", "currency": "CNY", "indicator": "Last_Price", "value": "211.10676", "value_date": "2024-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 15:03:44", "currency": "CNY", "indicator": "Market_Cap", "value": "205578.0066", "value_date": "2024-03-31"}, {"Company_code": "6301 JP Equity", "update_date": "2026-01-12 15:03:44", "currency": "CNY", "indicator": "Dividend_Yield", "value": "
2026-01-12 15:03:57,467 - app.clients.bloomberg_client - INFO - ✅ Parsed 30 items from remote.
2026-01-12 15:04:01,642 - app.clients.bloomberg_client - INFO - ✅ Saved 30 records to database.
2026-01-12 15:04:01,642 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=78, Msg=Finalizing data..., Progress=82%
2026-01-12 15:04:03,197 - app.clients.bloomberg_client - INFO - ✅ Cleanup and View Refresh completed.
2026-01-12 15:04:03,198 - app.clients.bloomberg_client - INFO - ✅ Completed processing for 6301 JP Equity
2026-01-12 15:04:03,199 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=78, Msg=Bloomberg data sync complete, Progress=90%
2026-01-12 15:04:03,616 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=78, Msg=Bloomberg 数据同步完成, Progress=100%
2026-01-12 18:12:48,235 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=79, Msg=正在初始化数据获取..., Progress=0%
2026-01-12 18:12:49,501 - app.clients.bloomberg_client - INFO - Connecting to Jupyter at http://192.168.3.161:8888...
2026-01-12 18:12:49,900 - app.clients.bloomberg_client - INFO - ✅ Authentication successful.
2026-01-12 18:12:50,098 - app.clients.bloomberg_client - INFO - ✅ Found existing kernel: bc27f3b1-b028-434a-99fa-c1cad4495a87 (remote_env)
2026-01-12 18:12:50,156 - app.clients.bloomberg_client - INFO - ✅ WebSocket connected.
2026-01-12 18:12:50,156 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=79, Msg=数据源连接成功, Progress=10%
2026-01-12 18:12:51,415 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=79, Msg=正在连接 Bloomberg 终端..., Progress=20%
2026-01-12 18:12:53,347 - app.clients.bloomberg_client - INFO - 🚀 Starting fetch for: 000725 CH Equity
2026-01-12 18:12:53,347 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=79, Msg=Starting Bloomberg session..., Progress=20%
2026-01-12 18:12:54,548 - app.clients.bloomberg_client - INFO - Using auto-detected currency: CNY
2026-01-12 18:12:54,548 - app.clients.bloomberg_client - INFO - Fetching Basic Data...
2026-01-12 18:12:54,548 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=79, Msg=Fetching Company Basic Info..., Progress=27%
2026-01-12 18:12:55,901 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "000725 CH Equity", "update_date": "2026-01-12 18:12:56", "currency": "CNY", "indicator": "company_name", "value": "BOE TECHNOLOGY GROUP CO LT-A", "value_date": "2026-01-12 18:12:56"}, {"Company_code": "000725 CH Equity", "update_date": "2026-01-12 18:12:56", "currency": "CNY", "indicator": "pe_ratio", "value": "25.959361598462067", "value_date": "2026-01-12 18:12:56"}, {"Company_code": "000725 CH Equity", "update_date": "2026-01-12 18:12:56", "currency": "CNY", "indicator": "pb_ratio", "value": "1.2417412746613823", "value_date": "2026-01-12 18:12:56"}, {"Company_code": "000725 CH Equity", "update_date": "2026-01-12 18:12:56", "currency": "CNY", "indicator": "market_cap", "value": "164036307936.54987", "value_date": "2026-01-12 18:12:56"}, {"Company_code": "000725 CH Equity", "update_date": "2026-01-12 18:12:56", "currency": "CNY", "indicator": "Rev_Abroad", "value": "49.83268989557015", "value_date": "2026-01-12 18:12:56"}, {"Company_code": "000725 CH Equ
2026-01-12 18:12:55,905 - app.clients.bloomberg_client - INFO - ✅ Parsed 7 items from remote.
2026-01-12 18:12:55,906 - app.clients.bloomberg_client - INFO - DEBUG: basic_data before save: [{'Company_code': '000725 CH Equity', 'update_date': '2026-01-12 18:12:56', 'currency': 'CNY', 'indicator': 'company_name', 'value': 'BOE TECHNOLOGY GROUP CO LT-A', 'value_date': '2026-01-12 18:12:56'}, {'Company_code': '000725 CH Equity', 'update_date': '2026-01-12 18:12:56', 'currency': 'CNY', 'indicator': 'pe_ratio', 'value': '25.959361598462067', 'value_date': '2026-01-12 18:12:56'}, {'Company_code': '000725 CH Equity', 'update_date': '2026-01-12 18:12:56', 'currency': 'CNY', 'indicator': 'pb_ratio', 'value': '1.2417412746613823', 'value_date': '2026-01-12 18:12:56'}, {'Company_code': '000725 CH Equity', 'update_date': '2026-01-12 18:12:56', 'currency': 'CNY', 'indicator': 'market_cap', 'value': '164036307936.54987', 'value_date': '2026-01-12 18:12:56'}, {'Company_code': '000725 CH Equity', 'update_date': '2026-01-12 18:12:56', 'currency': 'CNY', 'indicator': 'Rev_Abroad', 'value': '49.83268989557015', 'value_date': '2026-01-12 18:12:56'}, {'Company_code': '000725 CH Equity', 'update_date': '2026-01-12 18:12:56', 'currency': 'CNY', 'indicator': 'dividend_yield', 'value': '1.1210762498891942', 'value_date': '2026-01-12 18:12:56'}, {'Company_code': '000725 CH Equity', 'update_date': '2026-01-12 18:12:56', 'currency': 'CNY', 'indicator': 'IPO_date', 'value': '2001-01-12', 'value_date': '2026-01-12 18:12:56'}]
2026-01-12 18:12:56,950 - app.clients.bloomberg_client - INFO - ✅ Saved 7 records to database.
2026-01-12 18:12:56,951 - app.clients.bloomberg_client - INFO - Fetching Currency Data...
2026-01-12 18:12:56,951 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=79, Msg=正在获取货币指标 (CNY)..., Progress=41%
2026-01-12 18:13:00,033 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "000725 CH Equity", "update_date": "2026-01-12 18:12:59", "currency": "CNY", "indicator": "Revenue", "value": "68895.659", "value_date": "2016-12-31"}, {"Company_code": "000725 CH Equity", "update_date": "2026-01-12 18:12:59", "currency": "CNY", "indicator": "Net_Income", "value": "1882.5717", "value_date": "2016-12-31"}, {"Company_code": "000725 CH Equity", "update_date": "2026-01-12 18:12:59", "currency": "CNY", "indicator": "Cash_From_Operating", "value": "8308.9467", "value_date": "2016-12-31"}, {"Company_code": "000725 CH Equity", "update_date": "2026-01-12 18:12:59", "currency": "CNY", "indicator": "Capital_Expenditure", "value": "-30702.6147", "value_date": "2016-12-31"}, {"Company_code": "000725 CH Equity", "update_date": "2026-01-12 18:12:59", "currency": "CNY", "indicator": "Free_Cash_Flow", "value": "-22393.668", "value_date": "2016-12-31"}, {"Company_code": "000725 CH Equity", "update_date": "2026-01-12 18:12:59", "currency": "CNY", "indicator":
2026-01-12 18:13:00,034 - app.clients.bloomberg_client - INFO - ✅ Parsed 225 items from remote.
2026-01-12 18:13:21,758 - app.clients.bloomberg_client - INFO - ✅ Saved 225 records to database.
2026-01-12 18:13:21,759 - app.clients.bloomberg_client - INFO - Fetching Non-Currency Data...
2026-01-12 18:13:21,760 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=79, Msg=正在获取非货币指标..., Progress=55%
2026-01-12 18:13:22,781 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "000725 CH Equity", "update_date": "2026-01-12 18:13:22", "currency": "CNY", "indicator": "ROE", "value": "2.4107", "value_date": "2016-12-31"}, {"Company_code": "000725 CH Equity", "update_date": "2026-01-12 18:13:22", "currency": "CNY", "indicator": "ROA", "value": "1.0525", "value_date": "2016-12-31"}, {"Company_code": "000725 CH Equity", "update_date": "2026-01-12 18:13:22", "currency": "CNY", "indicator": "ROCE", "value": "2.905", "value_date": "2016-12-31"}, {"Company_code": "000725 CH Equity", "update_date": "2026-01-12 18:13:22", "currency": "CNY", "indicator": "Gross_Margin", "value": "17.8675", "value_date": "2016-12-31"}, {"Company_code": "000725 CH Equity", "update_date": "2026-01-12 18:13:22", "currency": "CNY", "indicator": "EBITDA_margin", "value": "18.8079", "value_date": "2016-12-31"}, {"Company_code": "000725 CH Equity", "update_date": "2026-01-12 18:13:22", "currency": "CNY", "indicator": "Net_Profit_Margin", "value": "2.7325", "value_dat
2026-01-12 18:13:22,781 - app.clients.bloomberg_client - INFO - ✅ Parsed 175 items from remote.
2026-01-12 18:13:42,509 - app.clients.bloomberg_client - INFO - ✅ Saved 175 records to database.
2026-01-12 18:13:42,510 - app.clients.bloomberg_client - INFO - Fetching Price Data (Aligned)...
2026-01-12 18:13:42,510 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=79, Msg=正在获取价格指标..., Progress=69%
2026-01-12 18:13:43,034 - app.clients.bloomberg_client - INFO - Found 9 revenue reporting dates. Fetching aligned price data...
2026-01-12 18:13:53,991 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "000725 CH Equity", "update_date": "2026-01-12 18:13:43", "currency": "CNY", "indicator": "Last_Price", "value": "4.39", "value_date": "2024-12-31"}, {"Company_code": "000725 CH Equity", "update_date": "2026-01-12 18:13:43", "currency": "CNY", "indicator": "Market_Cap", "value": "163990.883", "value_date": "2024-12-31"}, {"Company_code": "000725 CH Equity", "update_date": "2026-01-12 18:13:43", "currency": "CNY", "indicator": "Dividend_Yield", "value": "0.6834", "value_date": "2024-12-31"}, {"Company_code": "000725 CH Equity", "update_date": "2026-01-12 18:13:43", "currency": "CNY", "indicator": "Last_Price", "value": "3.9", "value_date": "2023-12-31"}, {"Company_code": "000725 CH Equity", "update_date": "2026-01-12 18:13:43", "currency": "CNY", "indicator": "Market_Cap", "value": "145742.6957", "value_date": "2023-12-31"}, {"Company_code": "000725 CH Equity", "update_date": "2026-01-12 18:13:43", "currency": "CNY", "indicator": "Dividend_Yield", "value": "
2026-01-12 18:13:53,992 - app.clients.bloomberg_client - INFO - ✅ Parsed 27 items from remote.
2026-01-12 18:13:56,649 - app.clients.bloomberg_client - INFO - ✅ Saved 27 records to database.
2026-01-12 18:13:56,649 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=79, Msg=Finalizing data..., Progress=82%
2026-01-12 18:13:59,126 - app.clients.bloomberg_client - INFO - ✅ Cleanup and View Refresh completed.
2026-01-12 18:13:59,127 - app.clients.bloomberg_client - INFO - ✅ Completed processing for 000725 CH Equity
2026-01-12 18:13:59,127 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=79, Msg=Bloomberg data sync complete, Progress=90%
2026-01-12 18:13:59,568 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=79, Msg=Bloomberg 数据同步完成, Progress=100%
2026-01-12 18:50:10,831 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=80, Msg=正在初始化数据获取..., Progress=0%
2026-01-12 18:50:11,898 - app.clients.bloomberg_client - INFO - Connecting to Jupyter at http://192.168.3.161:8888...
2026-01-12 18:50:12,774 - app.clients.bloomberg_client - INFO - ✅ Authentication successful.
2026-01-12 18:50:12,816 - app.clients.bloomberg_client - INFO - ✅ Found existing kernel: bc27f3b1-b028-434a-99fa-c1cad4495a87 (remote_env)
2026-01-12 18:50:12,900 - app.clients.bloomberg_client - INFO - ✅ WebSocket connected.
2026-01-12 18:50:12,900 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=80, Msg=数据源连接成功, Progress=10%
2026-01-12 18:50:13,188 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=80, Msg=正在连接 Bloomberg 终端..., Progress=20%
2026-01-12 18:50:13,808 - app.clients.bloomberg_client - INFO - 🚀 Starting fetch for: 000725 CH Equity
2026-01-12 18:50:13,808 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=80, Msg=Starting Bloomberg session..., Progress=20%
2026-01-12 18:50:14,304 - app.clients.bloomberg_client - INFO - Using auto-detected currency: CNY
2026-01-12 18:50:14,305 - app.clients.bloomberg_client - INFO - Fetching Basic Data...
2026-01-12 18:50:14,305 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=80, Msg=Fetching Company Basic Info..., Progress=27%
2026-01-12 18:50:16,663 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "000725 CH Equity", "update_date": "2026-01-12 18:50:17", "currency": "CNY", "indicator": "company_name", "value": "BOE TECHNOLOGY GROUP CO LT-A", "value_date": "2026-01-12 18:50:17"}, {"Company_code": "000725 CH Equity", "update_date": "2026-01-12 18:50:17", "currency": "CNY", "indicator": "pe_ratio", "value": "25.959361598462067", "value_date": "2026-01-12 18:50:17"}, {"Company_code": "000725 CH Equity", "update_date": "2026-01-12 18:50:17", "currency": "CNY", "indicator": "pb_ratio", "value": "1.2417412746613823", "value_date": "2026-01-12 18:50:17"}, {"Company_code": "000725 CH Equity", "update_date": "2026-01-12 18:50:17", "currency": "CNY", "indicator": "Rev_Abroad", "value": "49.83268989557015", "value_date": "2026-01-12 18:50:17"}, {"Company_code": "000725 CH Equity", "update_date": "2026-01-12 18:50:17", "currency": "CNY", "indicator": "dividend_yield", "value": "1.1210762498891942", "value_date": "2026-01-12 18:50:17"}, {"Company_code": "000725 CH
2026-01-12 18:50:16,664 - app.clients.bloomberg_client - INFO - ✅ Parsed 7 items from remote.
2026-01-12 18:50:16,664 - app.clients.bloomberg_client - INFO - DEBUG: basic_data before save: [{'Company_code': '000725 CH Equity', 'update_date': '2026-01-12 18:50:17', 'currency': 'CNY', 'indicator': 'company_name', 'value': 'BOE TECHNOLOGY GROUP CO LT-A', 'value_date': '2026-01-12 18:50:17'}, {'Company_code': '000725 CH Equity', 'update_date': '2026-01-12 18:50:17', 'currency': 'CNY', 'indicator': 'pe_ratio', 'value': '25.959361598462067', 'value_date': '2026-01-12 18:50:17'}, {'Company_code': '000725 CH Equity', 'update_date': '2026-01-12 18:50:17', 'currency': 'CNY', 'indicator': 'pb_ratio', 'value': '1.2417412746613823', 'value_date': '2026-01-12 18:50:17'}, {'Company_code': '000725 CH Equity', 'update_date': '2026-01-12 18:50:17', 'currency': 'CNY', 'indicator': 'Rev_Abroad', 'value': '49.83268989557015', 'value_date': '2026-01-12 18:50:17'}, {'Company_code': '000725 CH Equity', 'update_date': '2026-01-12 18:50:17', 'currency': 'CNY', 'indicator': 'dividend_yield', 'value': '1.1210762498891942', 'value_date': '2026-01-12 18:50:17'}, {'Company_code': '000725 CH Equity', 'update_date': '2026-01-12 18:50:17', 'currency': 'CNY', 'indicator': 'IPO_date', 'value': '2001-01-12', 'value_date': '2026-01-12 18:50:17'}, {'Company_code': '000725 CH Equity', 'update_date': '2026-01-12 18:50:17', 'currency': 'CNY', 'indicator': 'market_cap', 'value': '164036.2257', 'value_date': '2026-01-12 18:50:17'}]
2026-01-12 18:50:17,449 - app.clients.bloomberg_client - INFO - ✅ Saved 7 records to database.
2026-01-12 18:50:17,449 - app.clients.bloomberg_client - INFO - Fetching Currency Data...
2026-01-12 18:50:17,450 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=80, Msg=正在获取货币指标 (CNY)..., Progress=41%
2026-01-12 18:50:18,858 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "000725 CH Equity", "update_date": "2026-01-12 18:50:18", "currency": "CNY", "indicator": "Revenue", "value": "68895.659", "value_date": "2016-12-31"}, {"Company_code": "000725 CH Equity", "update_date": "2026-01-12 18:50:18", "currency": "CNY", "indicator": "Net_Income", "value": "1882.5717", "value_date": "2016-12-31"}, {"Company_code": "000725 CH Equity", "update_date": "2026-01-12 18:50:18", "currency": "CNY", "indicator": "Cash_From_Operating", "value": "8308.9467", "value_date": "2016-12-31"}, {"Company_code": "000725 CH Equity", "update_date": "2026-01-12 18:50:18", "currency": "CNY", "indicator": "Capital_Expenditure", "value": "-30702.6147", "value_date": "2016-12-31"}, {"Company_code": "000725 CH Equity", "update_date": "2026-01-12 18:50:18", "currency": "CNY", "indicator": "Free_Cash_Flow", "value": "-22393.668", "value_date": "2016-12-31"}, {"Company_code": "000725 CH Equity", "update_date": "2026-01-12 18:50:18", "currency": "CNY", "indicator":
2026-01-12 18:50:18,864 - app.clients.bloomberg_client - INFO - ✅ Parsed 225 items from remote.
2026-01-12 18:50:41,919 - app.clients.bloomberg_client - INFO - ✅ Saved 225 records to database.
2026-01-12 18:50:41,920 - app.clients.bloomberg_client - INFO - Fetching Non-Currency Data...
2026-01-12 18:50:41,920 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=80, Msg=正在获取非货币指标..., Progress=55%
2026-01-12 18:50:43,550 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "000725 CH Equity", "update_date": "2026-01-12 18:50:43", "currency": "CNY", "indicator": "ROE", "value": "2.4107", "value_date": "2016-12-31"}, {"Company_code": "000725 CH Equity", "update_date": "2026-01-12 18:50:43", "currency": "CNY", "indicator": "ROA", "value": "1.0525", "value_date": "2016-12-31"}, {"Company_code": "000725 CH Equity", "update_date": "2026-01-12 18:50:43", "currency": "CNY", "indicator": "ROCE", "value": "2.905", "value_date": "2016-12-31"}, {"Company_code": "000725 CH Equity", "update_date": "2026-01-12 18:50:43", "currency": "CNY", "indicator": "Gross_Margin", "value": "17.8675", "value_date": "2016-12-31"}, {"Company_code": "000725 CH Equity", "update_date": "2026-01-12 18:50:43", "currency": "CNY", "indicator": "EBITDA_margin", "value": "18.8079", "value_date": "2016-12-31"}, {"Company_code": "000725 CH Equity", "update_date": "2026-01-12 18:50:43", "currency": "CNY", "indicator": "Net_Profit_Margin", "value": "2.7325", "value_dat
2026-01-12 18:50:43,551 - app.clients.bloomberg_client - INFO - ✅ Parsed 175 items from remote.
2026-01-12 18:51:00,614 - app.clients.bloomberg_client - INFO - ✅ Saved 175 records to database.
2026-01-12 18:51:00,616 - app.clients.bloomberg_client - INFO - Fetching Price Data (Aligned)...
2026-01-12 18:51:00,616 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=80, Msg=正在获取价格指标..., Progress=69%
2026-01-12 18:51:01,579 - app.clients.bloomberg_client - INFO - Found 9 revenue reporting dates. Fetching aligned price data...
2026-01-12 18:51:12,149 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "000725 CH Equity", "update_date": "2026-01-12 18:51:01", "currency": "CNY", "indicator": "Last_Price", "value": "4.39", "value_date": "2024-12-31"}, {"Company_code": "000725 CH Equity", "update_date": "2026-01-12 18:51:01", "currency": "CNY", "indicator": "Market_Cap", "value": "163990.883", "value_date": "2024-12-31"}, {"Company_code": "000725 CH Equity", "update_date": "2026-01-12 18:51:01", "currency": "CNY", "indicator": "Dividend_Yield", "value": "0.6834", "value_date": "2024-12-31"}, {"Company_code": "000725 CH Equity", "update_date": "2026-01-12 18:51:01", "currency": "CNY", "indicator": "Last_Price", "value": "3.9", "value_date": "2023-12-31"}, {"Company_code": "000725 CH Equity", "update_date": "2026-01-12 18:51:01", "currency": "CNY", "indicator": "Market_Cap", "value": "145742.6957", "value_date": "2023-12-31"}, {"Company_code": "000725 CH Equity", "update_date": "2026-01-12 18:51:01", "currency": "CNY", "indicator": "Dividend_Yield", "value": "
2026-01-12 18:51:12,150 - app.clients.bloomberg_client - INFO - ✅ Parsed 27 items from remote.
2026-01-12 18:51:20,135 - app.clients.bloomberg_client - INFO - ✅ Saved 27 records to database.
2026-01-12 18:51:20,137 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=80, Msg=Finalizing data..., Progress=82%
2026-01-12 18:51:21,801 - app.clients.bloomberg_client - INFO - ✅ Cleanup and View Refresh completed.
2026-01-12 18:51:21,802 - app.clients.bloomberg_client - INFO - ✅ Completed processing for 000725 CH Equity
2026-01-12 18:51:21,803 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=80, Msg=Bloomberg data sync complete, Progress=90%
2026-01-12 18:51:24,153 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=80, Msg=Bloomberg 数据同步完成, Progress=100%
2026-01-12 19:07:13,245 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=81, Msg=正在初始化数据获取..., Progress=0%
2026-01-12 19:07:15,033 - app.clients.bloomberg_client - INFO - Connecting to Jupyter at http://192.168.3.161:8888...
2026-01-12 19:07:16,023 - app.clients.bloomberg_client - INFO - ✅ Authentication successful.
2026-01-12 19:07:16,065 - app.clients.bloomberg_client - INFO - ✅ Found existing kernel: bc27f3b1-b028-434a-99fa-c1cad4495a87 (remote_env)
2026-01-12 19:07:16,139 - app.clients.bloomberg_client - INFO - ✅ WebSocket connected.
2026-01-12 19:07:16,140 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=81, Msg=数据源连接成功, Progress=10%
2026-01-12 19:07:17,324 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=81, Msg=正在连接 Bloomberg 终端..., Progress=20%
2026-01-12 19:07:18,445 - app.clients.bloomberg_client - INFO - 🚀 Starting fetch for: 00631 HK Equity
2026-01-12 19:07:18,447 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=81, Msg=Starting Bloomberg session..., Progress=20%
2026-01-12 19:07:19,414 - app.clients.bloomberg_client - INFO - Using auto-detected currency: HKD
2026-01-12 19:07:19,414 - app.clients.bloomberg_client - INFO - Fetching Basic Data...
2026-01-12 19:07:19,415 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=81, Msg=Fetching Company Basic Info..., Progress=27%
2026-01-12 19:07:22,487 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "00631 HK Equity", "update_date": "2026-01-12 19:07:23", "currency": "HKD", "indicator": "company_name", "value": "SANY HEAVY EQUIPMENT INTL", "value_date": "2026-01-12 19:07:23"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 19:07:23", "currency": "HKD", "indicator": "pe_ratio", "value": "19.933741441016245", "value_date": "2026-01-12 19:07:23"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 19:07:23", "currency": "HKD", "indicator": "pb_ratio", "value": "2.110479881831945", "value_date": "2026-01-12 19:07:23"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 19:07:23", "currency": "HKD", "indicator": "Rev_Abroad", "value": "37.287945521334656", "value_date": "2026-01-12 19:07:23"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 19:07:23", "currency": "HKD", "indicator": "dividend_yield", "value": "3.162486277593781", "value_date": "2026-01-12 19:07:23"}, {"Company_code": "00631 HK Equity",
2026-01-12 19:07:22,488 - app.clients.bloomberg_client - INFO - ✅ Parsed 7 items from remote.
2026-01-12 19:07:22,488 - app.clients.bloomberg_client - INFO - DEBUG: basic_data before save: [{'Company_code': '00631 HK Equity', 'update_date': '2026-01-12 19:07:23', 'currency': 'HKD', 'indicator': 'company_name', 'value': 'SANY HEAVY EQUIPMENT INTL', 'value_date': '2026-01-12 19:07:23'}, {'Company_code': '00631 HK Equity', 'update_date': '2026-01-12 19:07:23', 'currency': 'HKD', 'indicator': 'pe_ratio', 'value': '19.933741441016245', 'value_date': '2026-01-12 19:07:23'}, {'Company_code': '00631 HK Equity', 'update_date': '2026-01-12 19:07:23', 'currency': 'HKD', 'indicator': 'pb_ratio', 'value': '2.110479881831945', 'value_date': '2026-01-12 19:07:23'}, {'Company_code': '00631 HK Equity', 'update_date': '2026-01-12 19:07:23', 'currency': 'HKD', 'indicator': 'Rev_Abroad', 'value': '37.287945521334656', 'value_date': '2026-01-12 19:07:23'}, {'Company_code': '00631 HK Equity', 'update_date': '2026-01-12 19:07:23', 'currency': 'HKD', 'indicator': 'dividend_yield', 'value': '3.162486277593781', 'value_date': '2026-01-12 19:07:23'}, {'Company_code': '00631 HK Equity', 'update_date': '2026-01-12 19:07:23', 'currency': 'HKD', 'indicator': 'IPO_date', 'value': '2009-11-25', 'value_date': '2026-01-12 19:07:23'}, {'Company_code': '00631 HK Equity', 'update_date': '2026-01-12 19:07:23', 'currency': 'HKD', 'indicator': 'market_cap', 'value': '29641.2727', 'value_date': '2026-01-12 19:07:23'}]
2026-01-12 19:07:23,816 - app.clients.bloomberg_client - INFO - ✅ Saved 7 records to database.
2026-01-12 19:07:23,818 - app.clients.bloomberg_client - INFO - Fetching Currency Data...
2026-01-12 19:07:23,818 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=81, Msg=正在获取货币指标 (HKD)..., Progress=41%
2026-01-12 19:07:26,292 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "00631 HK Equity", "update_date": "2026-01-12 19:07:24", "currency": "HKD", "indicator": "Revenue", "value": "2152.9812", "value_date": "2016-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 19:07:24", "currency": "HKD", "indicator": "Net_Income", "value": "-753.2314", "value_date": "2016-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 19:07:24", "currency": "HKD", "indicator": "Cash_From_Operating", "value": "1557.419", "value_date": "2016-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 19:07:24", "currency": "HKD", "indicator": "Capital_Expenditure", "value": "-179.3705", "value_date": "2016-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 19:07:24", "currency": "HKD", "indicator": "Free_Cash_Flow", "value": "1378.0485", "value_date": "2016-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 19:07:24", "currency": "HKD", "indicator": "Dividend
2026-01-12 19:07:26,293 - app.clients.bloomberg_client - INFO - ✅ Parsed 213 items from remote.
2026-01-12 19:07:47,000 - app.clients.bloomberg_client - INFO - ✅ Saved 213 records to database.
2026-01-12 19:07:47,006 - app.clients.bloomberg_client - INFO - Fetching Non-Currency Data...
2026-01-12 19:07:47,006 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=81, Msg=正在获取非货币指标..., Progress=55%
2026-01-12 19:07:48,166 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "00631 HK Equity", "update_date": "2026-01-12 19:07:47", "currency": "HKD", "indicator": "ROE", "value": "-10.132", "value_date": "2016-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 19:07:47", "currency": "HKD", "indicator": "ROA", "value": "-6.0025", "value_date": "2016-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 19:07:47", "currency": "HKD", "indicator": "Gross_Margin", "value": "14.994", "value_date": "2016-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 19:07:47", "currency": "HKD", "indicator": "EBITDA_margin", "value": "-28.2708", "value_date": "2016-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 19:07:47", "currency": "HKD", "indicator": "Net_Profit_Margin", "value": "-34.9855", "value_date": "2016-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 19:07:47", "currency": "HKD", "indicator": "Tax_Rate", "value": "0.25", "value_da
2026-01-12 19:07:48,168 - app.clients.bloomberg_client - INFO - ✅ Parsed 150 items from remote.
2026-01-12 19:08:07,614 - app.clients.bloomberg_client - INFO - ✅ Saved 150 records to database.
2026-01-12 19:08:07,618 - app.clients.bloomberg_client - INFO - Fetching Price Data (Aligned)...
2026-01-12 19:08:07,619 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=81, Msg=正在获取价格指标..., Progress=69%
2026-01-12 19:08:08,123 - app.clients.bloomberg_client - INFO - Found 9 revenue reporting dates. Fetching aligned price data...
2026-01-12 19:08:18,378 - app.clients.bloomberg_client - INFO - REMOTE RAW OUTPUT: JSON_START
[{"Company_code": "00631 HK Equity", "update_date": "2026-01-12 19:08:08", "currency": "HKD", "indicator": "Last_Price", "value": "4.51", "value_date": "2024-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 19:08:08", "currency": "HKD", "indicator": "Market_Cap", "value": "14494.6462", "value_date": "2024-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 19:08:08", "currency": "HKD", "indicator": "Dividend_Yield", "value": "4.2129", "value_date": "2024-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 19:08:08", "currency": "HKD", "indicator": "Last_Price", "value": "7.55", "value_date": "2023-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 19:08:08", "currency": "HKD", "indicator": "Market_Cap", "value": "24081.9354", "value_date": "2023-12-31"}, {"Company_code": "00631 HK Equity", "update_date": "2026-01-12 19:08:08", "currency": "HKD", "indicator": "Dividend_Yield", "value": "2.5166
2026-01-12 19:08:18,379 - app.clients.bloomberg_client - INFO - ✅ Parsed 25 items from remote.
2026-01-12 19:08:23,531 - app.clients.bloomberg_client - INFO - ✅ Saved 25 records to database.
2026-01-12 19:08:23,532 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=81, Msg=Finalizing data..., Progress=82%
2026-01-12 19:08:25,393 - app.clients.bloomberg_client - INFO - ✅ Cleanup and View Refresh completed.
2026-01-12 19:08:25,394 - app.clients.bloomberg_client - INFO - ✅ Completed processing for 00631 HK Equity
2026-01-12 19:08:25,394 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=81, Msg=Bloomberg data sync complete, Progress=90%
2026-01-12 19:08:26,834 - app.services.data_fetcher_service - INFO - 🔄 [进度更新] ID=81, Msg=Bloomberg 数据同步完成, Progress=100%

View File

@ -0,0 +1,61 @@
import sys
import os
import logging
import json
from datetime import datetime, timedelta
# Add app to path
sys.path.append(os.path.join(os.path.dirname(__file__), 'app'))
from app.clients.bloomberg_client import BloombergClient
# Config logging
logging.basicConfig(level=logging.INFO)
def test_market_cap():
print("Initializing Client...")
client = BloombergClient()
# Target: 6301 JP Equity (Komatsu Ltd)
company_code = "6301 JP Equity"
# Dates to fetch (last few years)
dates = ["2023-03-31", "2024-03-31"] # Komatsu fiscal year end is usually March 31
# 1. Fetch in JPY (Local)
print("\nfetching Market Cap in JPY...")
try:
data_jpy = client._fetch_price_by_dates_remote(
company_code=company_code,
currency="JPY",
dates=dates,
query_ticker=company_code
)
print("--- Result JPY ---")
print(json.dumps(data_jpy, indent=2, ensure_ascii=False))
except Exception as e:
print(f"Error JPY: {e}")
# 2. Fetch in CNY (Converted) - Using Series Remote (Fallback Path)
print("\nfetching Market Cap in CNY (Series Remote Fallback)...")
try:
from app.clients.bloomberg_client import PRICE_CONFIG
# We need to simulate the fallback call:
# price_data = self._fetch_series_remote(company_code, currency, PRICE_CONFIG, "price", query_ticker=query_ticker)
data_cny = client._fetch_series_remote(
company_code=company_code,
currency="CNY",
config_dict=PRICE_CONFIG,
result_type="price",
query_ticker=company_code
)
print("--- Result CNY (Series) ---")
print(json.dumps(data_cny[:5], indent=2, ensure_ascii=False))
except Exception as e:
print(f"Error CNY: {e}")
if __name__ == "__main__":
test_market_cap()

View File

@ -0,0 +1,66 @@
import sys
import os
import logging
import json
from datetime import datetime, timedelta
# Add app to path
sys.path.append(os.path.join(os.path.dirname(__file__), 'app'))
from app.clients.bloomberg_client import BloombergClient
# Config logging
logging.basicConfig(level=logging.INFO)
def test_series():
print("Initializing Client...")
client = BloombergClient()
# Simulate the logic in fetch_company for HK
symbol = "00631"
market = "HK"
# 1. Ticker Logic
mapped_market = "CH" if market == "CN" else market
company_code = f"{symbol} {mapped_market} Equity" # "00631 HK Equity"
query_ticker = company_code
if market == "HK" or (len(company_code.split()) > 1 and company_code.split()[1] == "HK"):
parts = company_code.split()
ticker_part = parts[0]
if ticker_part.isdigit():
short_ticker = str(int(ticker_part))
query_ticker = f"{short_ticker} {' '.join(parts[1:])}" # "631 HK Equity"
print(f"Company Code (Storage): {company_code}")
print(f"Query Ticker (Bloomberg): {query_ticker}")
currency = "HKD"
# 2. Test Currency Data Fetch (Revenue)
print("\nfetching Currency Data (Series)...")
curr_indicators = {
"Revenue": "SALES_REV_TURN"
}
try:
# Call the internal method directly
data = client._fetch_series_remote(
company_code=company_code,
currency=currency,
config_dict=curr_indicators,
result_type="currency",
query_ticker=query_ticker
)
print("--- Result (First 5 items) ---")
print(json.dumps(data[:5], indent=2, ensure_ascii=False))
print(f"Total items: {len(data)}")
except Exception as e:
print(f"Error: {e}")
except Exception as e:
print(f"Error: {e}")
if __name__ == "__main__":
test_series()

View File

@ -0,0 +1,57 @@
import sys
import asyncio
from app.clients.bloomberg_client import BloombergClient
async def run():
client = BloombergClient()
company = "2503 JP Equity"
# We want to check 2024-12-31 data for JPY, CNY, USD
currencies = ["JPY", "CNY", "USD"]
print(f"Testing Market Cap for {company} on 2024-12-31 in {currencies}")
remote_code = f"""
def test_currency():
company = "{company}"
currencies = {currencies}
date = "20241231"
results = {{}}
try:
for curr in currencies:
print(f"Fetching for {{curr}}...")
# Use BDH for historical specific date
df = bquery.bdh(
[company],
['CUR_MKT_CAP'],
start_date=date,
end_date=date,
options={{'currency': curr, 'periodicitySelection': 'DAILY', 'nonTradingDayFillOption': 'ALL_CALENDAR_DAYS', 'nonTradingDayFillMethod': 'PREVIOUS_VALUE'}}
)
if not df.empty and 'CUR_MKT_CAP' in df.columns:
val = df['CUR_MKT_CAP'].iloc[0]
results[curr] = val
else:
results[curr] = "No Data"
except Exception as e:
print(f"Error: {{e}}")
import json
print("JSON_START")
print(json.dumps(results))
print("JSON_END")
test_currency()
"""
result = client.execute_remote_code(remote_code)
print("\nCheck Result:")
print(result)
if __name__ == "__main__":
asyncio.run(run())

View File

@ -0,0 +1,41 @@
import sys
import asyncio
import json
from app.clients.bloomberg_client import BloombergClient
# Mock the PRICE_CONFIG to ensure we are fetching what we expect if it's not imported
# But BloombergClient imports it from configuration.
# Let's rely on the real client.
async def run():
client = BloombergClient()
company = "2503 JP Equity"
dates = ['2024-12-31', '2023-12-31', '2022-12-31', '2021-12-31', '2020-12-31', '2019-12-31', '2018-12-31', '2017-12-31', '2016-12-31']
currencies = ["CNY"]
print(f"Testing _fetch_price_by_dates_remote for {company} on {dates}...")
for curr in currencies:
print(f"\n--- Fetching in {curr} ---")
try:
# The method allows fetching price data for specific dates
# It uses PRICE_CONFIG which includes 'Market_Cap'
data = client._fetch_price_by_dates_remote(company, curr, dates)
# Filter for Market_Cap to show user
mkt_caps = [d for d in data if d['indicator'] == 'Market_Cap']
if mkt_caps:
for item in mkt_caps:
print(f"Currency: {item['currency']}, Date: {item['value_date']}, Value: {item['value']}")
else:
print("No Market_Cap data returned.")
print("Raw data returned:", json.dumps(data, indent=2))
except Exception as e:
print(f"Error fetching {curr}: {e}")
if __name__ == "__main__":
asyncio.run(run())

View File

@ -19,6 +19,8 @@ import { Progress } from "@/components/ui/progress"
import { formatTimestamp } from "@/lib/formatters" import { formatTimestamp } from "@/lib/formatters"
import { BloombergView } from "@/components/bloomberg-view" import { BloombergView } from "@/components/bloomberg-view"
import { HeaderPortal } from "@/components/header-portal" import { HeaderPortal } from "@/components/header-portal"
import { AppSidebar } from "@/components/app-sidebar"
import { StockChart } from "@/components/stock-chart"
export default function Home() { export default function Home() {
const searchParams = useSearchParams() const searchParams = useSearchParams()
@ -27,18 +29,23 @@ export default function Home() {
const [selectedCompany, setSelectedCompany] = useState<SearchResult | null>(null) const [selectedCompany, setSelectedCompany] = useState<SearchResult | null>(null)
const [selectedDataSource, setSelectedDataSource] = useState<string>("iFinD") const [selectedDataSource, setSelectedDataSource] = useState<string>("iFinD")
const [companyId, setCompanyId] = useState<number | null>(null) const [companyId, setCompanyId] = useState<number | null>(null)
const [showFinancialData, setShowFinancialData] = useState(false)
const [analysisId, setAnalysisId] = useState<number | null>(null) const [analysisId, setAnalysisId] = useState<number | null>(null)
const [oneTimeModel, setOneTimeModel] = useState<string | undefined>(undefined) const [oneTimeModel, setOneTimeModel] = useState<string | undefined>(undefined)
const [currency, setCurrency] = useState<string>("Auto")
// View State (home, financial, chart)
const [currentView, setCurrentView] = useState<string>("home")
// 处理公司选择 // 处理公司选择
const handleCompanySelect = (company: SearchResult, dataSource?: string) => { const handleCompanySelect = (company: SearchResult, dataSource?: string) => {
setSelectedCompany(company) setSelectedCompany(company)
setCompanyId(null) setCompanyId(null)
setShowFinancialData(false)
setAnalysisId(null) setAnalysisId(null)
setOneTimeModel(undefined) setOneTimeModel(undefined)
// Switch to financial view by default when company is selected
setCurrentView("financial")
// 如果没有传入数据源,则根据市场设置默认值 // 如果没有传入数据源,则根据市场设置默认值
const targetDataSource = dataSource || (company.market === 'CN' ? 'Tushare' : 'iFinD') const targetDataSource = dataSource || (company.market === 'CN' ? 'Tushare' : 'iFinD')
setSelectedDataSource(targetDataSource) setSelectedDataSource(targetDataSource)
@ -64,7 +71,6 @@ export default function Home() {
// 数据准备就绪 // 数据准备就绪
const handleDataReady = (id: number) => { const handleDataReady = (id: number) => {
setCompanyId(id) setCompanyId(id)
setShowFinancialData(true)
} }
// AI分析完成 // AI分析完成
@ -72,20 +78,30 @@ export default function Home() {
setAnalysisId(id) setAnalysisId(id)
} }
// 返回搜索 // 返回搜索 (Reset)
const handleBackToSearch = () => { const handleBackToSearch = () => {
setSelectedCompany(null) setSelectedCompany(null)
setCompanyId(null) setCompanyId(null)
setShowFinancialData(false)
setAnalysisId(null) setAnalysisId(null)
setOneTimeModel(undefined) setOneTimeModel(undefined)
setCurrentView("home")
} }
return ( // Navigation Handler
<div className="min-h-screen w-full p-8"> const handleTabChange = (tab: string) => {
{/* 标题和描述 */} if (tab === "home") {
{!selectedCompany && ( handleBackToSearch()
<div className="max-w-7xl mx-auto flex flex-col gap-8"> } else {
setCurrentView(tab)
}
}
// Render Content based on View
const renderContent = () => {
// Home View
if (!selectedCompany || currentView === "home") {
return (
<div className="max-w-7xl mx-auto flex flex-col gap-8 p-8">
<div className="flex flex-col gap-4"> <div className="flex flex-col gap-4">
<h1 className="text-3xl font-bold tracking-tight"></h1> <h1 className="text-3xl font-bold tracking-tight"></h1>
<p className="text-muted-foreground"> <p className="text-muted-foreground">
@ -98,183 +114,220 @@ export default function Home() {
<SearchStockWithSelection onSelect={handleCompanySelect} /> <SearchStockWithSelection onSelect={handleCompanySelect} />
</div> </div>
{/* 最近的报告 */} {/* 历史记录 */}
<div className="flex flex-col gap-4 mt-8"> <div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<h2 className="text-2xl font-bold tracking-tight"></h2> <HistoryList onSelect={handleCompanySelect} />
<HistoryList />
</div> </div>
</div> </div>
)} )
}
{selectedCompany && ( // Chart View
<div className="w-full"> if (currentView === "chart") {
<CompanyAnalysisView return (
company={selectedCompany} <div className="h-full p-4 flex flex-col gap-4">
dataSource={selectedDataSource} {/* Top Navigation for Chart View */}
onBack={handleBackToSearch} <div className="flex flex-row items-center justify-between px-2">
onDataSourceChange={setSelectedDataSource} <div className="flex items-center gap-4">
oneTimeModel={oneTimeModel} <Button variant="ghost" size="sm" onClick={handleBackToSearch} className="gap-2">
/> <ArrowLeft className="h-4 w-4" />
</Button>
<div className="flex items-center gap-2">
<h1 className="text-2xl font-bold">{selectedCompany.company_name}</h1>
<Badge variant="outline">{selectedCompany.symbol}</Badge>
<Badge>{selectedCompany.market}</Badge>
</div>
</div>
</div>
<StockChart symbol={selectedCompany.symbol} market={selectedCompany.market} />
</div> </div>
)} )
}
// Financial Data View (Default fallback)
return (
<div className="w-full pl-2 pr-32 py-6 space-y-6">
{/* 顶部导航栏 (Portal Target) */}
<div className="grid grid-cols-1 gap-6">
{/* 数据源选择 */}
<div className="flex flex-col gap-4">
<div className="hidden">
<DataSourceSelector
market={selectedCompany.market}
selectedSource={selectedDataSource}
onSourceChange={setSelectedDataSource}
/>
</div>
{/* 数据获取状态 */}
<CompanyAnalysisView
company={selectedCompany}
dataSource={selectedDataSource}
onDataReady={handleDataReady}
onAnalysisComplete={handleAnalysisComplete}
selectedModel={oneTimeModel}
currency={currency}
setCurrency={setCurrency}
/>
</div>
</div>
</div>
)
}
return (
<div className="flex h-screen w-full bg-background overflow-hidden">
{/* Sidebar */}
<AppSidebar
activeTab={currentView}
onTabChange={handleTabChange}
hasSelectedCompany={!!selectedCompany}
className="flex-shrink-0 z-10"
/>
{/* Main Content Area */}
<main className="flex-1 overflow-auto bg-background/50 relative">
{renderContent()}
</main>
</div> </div>
) )
} }
// 拆分出单独的组件以使用Hooks // ----------------------------------------------------------------------
// Sub-components
// ----------------------------------------------------------------------
function CompanyAnalysisView({ function CompanyAnalysisView({
company, company,
dataSource, dataSource,
onBack, onDataReady,
onDataSourceChange, onAnalysisComplete,
oneTimeModel selectedModel,
currency,
setCurrency
}: { }: {
company: SearchResult, company: SearchResult
dataSource: string, dataSource: string
onBack: () => void, onDataReady: (id: number) => void
onDataSourceChange: (ds: string) => void, onAnalysisComplete: (id: number) => void
oneTimeModel?: string selectedModel?: string
currency: string
setCurrency: (c: string) => void
}) { }) {
const { const {
status, status,
loading, loading,
fetching, fetching,
updateStatus,
error, error,
fetchData, fetchData,
checkStatus checkStatus,
updateStatus
} = useFinancialData(company, dataSource) } = useFinancialData(company, dataSource)
const [companyId, setCompanyId] = useState<number | null>(null) const progress = updateStatus ? {
const [analysisId, setAnalysisId] = useState<number | null>(null) percentage: updateStatus.progress_percentage || 0,
message: updateStatus.progress_message || ""
} : null
// 当数据就绪时设置companyId
useEffect(() => { useEffect(() => {
if (status?.has_data && status.company_id) { if (status && status.has_data && status.company_id) {
setCompanyId(status.company_id) onDataReady(status.company_id)
} else {
setCompanyId(null)
} }
}, [status]) }, [status, onDataReady])
const handleAnalysisComplete = (id: number) => {
setAnalysisId(id)
}
const isUpdating = fetching && updateStatus
const progress = updateStatus?.progress_percentage || 0
const progressStatus = updateStatus?.progress_message || ""
const [currency, setCurrency] = useState("Auto")
return ( return (
<div className="space-y-6"> <div className="space-y-6">
{/* Header Controls */}
<HeaderPortal> <HeaderPortal>
<div className="flex items-center justify-end w-full gap-4 text-sm h-full"> <div className="flex items-center gap-2 mr-4 border-r pr-4">
{/* 0. Operation Buttons (Update Data) */} <span className="font-bold whitespace-nowrap">{company.company_name}</span>
<Button <Badge variant="outline" className="font-mono">{company.symbol}</Badge>
onClick={() => fetchData(true, currency)} <Badge className="text-xs">{company.market}</Badge>
disabled={fetching}
variant={!status?.has_data ? "default" : "outline"}
size="sm"
className="h-8"
>
{fetching ? (
<Loader2 className="h-3.5 w-3.5 animate-spin mr-2" />
) : (
<RefreshCw className="h-3.5 w-3.5 mr-2" />
)}
{status?.has_data ? "更新数据" : "获取数据"}
</Button>
{/* 0.5 Currency Selector */}
<div className="bg-muted/30 p-1 rounded-lg border flex items-center gap-1 h-8">
{["Auto", "CNY", "USD"].map((curr) => (
<button
key={curr}
onClick={() => setCurrency(curr)}
className={`
px-2 py-0.5 text-xs font-medium rounded-md transition-all
${currency === curr
? "bg-background text-primary shadow-sm border"
: "text-muted-foreground hover:bg-muted/50"}
`}
>
{curr}
</button>
))}
</div>
{/* 1. Status Display */}
<div className="flex items-center text-muted-foreground mr-auto">
{isUpdating ? (
<div className="flex items-center gap-2 text-xs font-mono bg-muted/50 rounded-full px-3 py-1 animate-pulse">
<span className="font-bold text-primary">{Math.round(progress)}%</span>
<span className="truncate max-w-[200px]">{progressStatus || "Processing..."}</span>
</div>
) : (
status?.has_data && status.last_update && (
<div className="flex items-center gap-1.5 text-xs opacity-80">
<CheckCircle2 className="h-3.5 w-3.5 text-green-500" />
<span>: {formatTimestamp(status.last_update.date)}</span>
</div>
)
)}
</div>
{/* 2. 公司基础信息 */}
<div className="flex items-center gap-3 border-l pl-4 border-r pr-4 h-8">
<span className="font-bold truncate max-w-[200px]">{company.company_name}</span>
<Badge variant="secondary" className="font-mono h-6">{company.market} {company.symbol}</Badge>
</div>
</div> </div>
<div className="flex items-center gap-2 mr-4">
<Button
variant="outline"
size="sm"
onClick={() => fetchData(true, currency)}
disabled={loading || fetching}
className="gap-2"
>
{(loading || fetching) ? <Loader2 className="h-4 w-4 animate-spin" /> : <RefreshCw className="h-4 w-4" />}
{(loading || fetching) ? "更新中..." : "更新数据"}
</Button>
</div>
<div className="flex items-center space-x-1 mr-6 border rounded-md p-1 bg-muted/20">
{["Auto", "CNY", "USD"].map((opt) => (
<button
key={opt}
onClick={() => setCurrency(opt)}
className={`
px-3 py-1 text-xs font-medium rounded-sm transition-all
${currency === opt
? "bg-background shadow-sm text-foreground"
: "text-muted-foreground hover:text-foreground hover:bg-muted/50"}
`}
>
{opt}
</button>
))}
</div>
{fetching && (
<div className="flex items-center gap-2 mr-4 min-w-[200px]">
<span className="text-xs text-muted-foreground whitespace-nowrap">
{progress?.message || "准备中..."}
</span>
<Progress value={progress?.percentage || 0} className="h-2 w-20" />
</div>
)}
{!fetching && !loading && <div className="text-xs text-muted-foreground flex items-center gap-1">
<CheckCircle2 className="w-3 h-3 text-green-500" /> : {status?.last_update?.date ? formatTimestamp(status.last_update.date) : "无记录"}
</div>}
</HeaderPortal> </HeaderPortal>
{/* 数据状态详情 (Card) */} {/* DataStatusCard usage removed because it duplicates logic and caused prop mismatch.
Status is now handled by HeaderPortal controls.
*/}
{error && (
<div className="p-4 border border-destructive/50 bg-destructive/10 rounded-lg text-destructive flex items-center gap-2">
<Loader2 className="h-4 w-4" /> {/* Reuse icon or AlertCircle */}
<span>{error}</span>
</div>
)}
{dataSource === 'Bloomberg' ? (
{/* 财务数据表格 */} status?.company_id && (
{status?.has_data && companyId && (
dataSource === 'Bloomberg' ? (
<BloombergView <BloombergView
companyId={companyId}
selectedCurrency={currency} selectedCurrency={currency}
userMarket={company.market} userMarket={company.market}
companyId={status.company_id}
lastUpdate={status.last_update?.date}
/> />
) : ( )
) : (
status?.company_id && (
<FinancialTables <FinancialTables
companyId={companyId} companyId={status.company_id}
dataSource={dataSource} dataSource={dataSource}
/> />
) )
)} )}
{/* AI 分析触发器 */}
{status?.has_data && companyId && !analysisId && (
<AnalysisTrigger
companyId={companyId}
dataSource={dataSource}
model={oneTimeModel}
onAnalysisComplete={handleAnalysisComplete}
/>
)}
{/* AI 分析报告 */}
{analysisId && (
<AnalysisReport analysisId={analysisId} />
)}
</div> </div>
) )
} }
function SearchStockWithSelection({ onSelect }: { onSelect: (c: SearchResult, s?: string) => void }) {
// 搜索组件的包装器,添加选择功能
function SearchStockWithSelection({ onSelect }: { onSelect: (company: SearchResult) => void }) {
return ( return (
<Card> <Card>
<CardHeader> <CardHeader>
<CardTitle></CardTitle> <CardTitle></CardTitle>
</CardHeader> </CardHeader>
<CardContent> <CardContent>
<SearchStock onCompanySelect={onSelect} /> <SearchStock onCompanySelect={onSelect} />

View File

@ -0,0 +1,41 @@
import { Home, LineChart, BarChart3, Search } from "lucide-react"
import { cn } from "@/lib/utils"
import { Button } from "@/components/ui/button"
interface AppSidebarProps {
activeTab: string
onTabChange: (tab: string) => void
className?: string
hasSelectedCompany: boolean
}
export function AppSidebar({ activeTab, onTabChange, className, hasSelectedCompany }: AppSidebarProps) {
const navItems = [
{ id: "home", label: "首页", icon: Home, disabled: false },
{ id: "financial", label: "财务数据", icon: BarChart3, disabled: !hasSelectedCompany },
{ id: "chart", label: "股价图", icon: LineChart, disabled: !hasSelectedCompany },
]
return (
<div className={cn("w-64 border-r bg-card flex flex-col p-4 gap-2", className)}>
{navItems.map((item) => (
<Button
key={item.id}
variant={activeTab === item.id ? "secondary" : "ghost"}
className={cn(
"justify-start gap-3 h-12 text-base font-normal",
activeTab === item.id && "bg-secondary font-medium",
activeTab !== item.id && "text-muted-foreground"
)}
onClick={() => !item.disabled && onTabChange(item.id)}
disabled={item.disabled}
>
<item.icon className="h-5 w-5" />
{item.label}
</Button>
))}
</div>
)
}

View File

@ -14,14 +14,17 @@ interface BloombergViewProps {
onBack?: () => void onBack?: () => void
selectedCurrency?: string selectedCurrency?: string
userMarket?: string userMarket?: string
lastUpdate?: string
} }
export function BloombergView({ companyId, onBack, selectedCurrency = "Auto", userMarket }: BloombergViewProps) { export function BloombergView({ companyId, onBack, selectedCurrency = "Auto", userMarket, lastUpdate }: BloombergViewProps) {
const [data, setData] = useState<FinancialDataResponse | null>(null) const [data, setData] = useState<FinancialDataResponse | null>(null)
const [loading, setLoading] = useState(true) const [loading, setLoading] = useState(true)
const [error, setError] = useState("") const [error, setError] = useState("")
const loadData = async () => { const loadData = async () => {
if (!companyId) return
setLoading(true) setLoading(true)
setError("") setError("")
try { try {
@ -39,7 +42,7 @@ export function BloombergView({ companyId, onBack, selectedCurrency = "Auto", us
useEffect(() => { useEffect(() => {
loadData() loadData()
}, [companyId]) }, [companyId, lastUpdate])
if (loading) { if (loading) {
return ( return (
@ -69,16 +72,25 @@ export function BloombergView({ companyId, onBack, selectedCurrency = "Auto", us
const mergedData = data.unified_data || [] const mergedData = data.unified_data || []
return ( return (
<div className="space-y-8"> <div className="space-y-6">
<div className="flex items-center justify-between"> <div className="flex flex-col gap-4">
<h2 className="text-2xl font-bold flex items-center gap-2"> <div className="flex items-center justify-between flex-wrap gap-4">
<DollarSign className="w-6 h-6" /> <div className="flex items-center gap-6">
Bloomberg <h2 className="text-2xl font-bold flex items-center gap-2 whitespace-nowrap">
</h2> <DollarSign className="w-6 h-6" />
<Button variant="outline" size="sm" onClick={loadData}>
<RefreshCw className="w-4 h-4 mr-2" /> </h2>
{/* Insert Inline Header Info here */}
</Button> <BasicInfoHeader data={mergedData} selectedCurrency={selectedCurrency} userMarket={userMarket} />
</div>
<div className="flex gap-2 ml-auto">
<Button variant="outline" size="sm" onClick={loadData}>
<RefreshCw className="w-4 h-4 mr-2" />
</Button>
</div>
</div>
</div> </div>
<RawDataTable title="财务数据总表" data={mergedData} selectedCurrency={selectedCurrency} userMarket={userMarket} /> <RawDataTable title="财务数据总表" data={mergedData} selectedCurrency={selectedCurrency} userMarket={userMarket} />
@ -86,6 +98,150 @@ export function BloombergView({ companyId, onBack, selectedCurrency = "Auto", us
) )
} }
// ---------------------------------------------------------------------------
// Basic Info Header Component
// ---------------------------------------------------------------------------
function BasicInfoHeader({ data, selectedCurrency = "Auto", userMarket }: { data: any[], selectedCurrency?: string, userMarket?: string }) {
if (!data || data.length === 0) return null
// 1. Determine Target Currency (Logic shared with Table)
let targetCurrency = selectedCurrency
if (targetCurrency === "Auto" && userMarket) {
const market = userMarket.toUpperCase()
if (market.includes("JP")) targetCurrency = "JPY"
else if (market.includes("VN")) targetCurrency = "VND"
else if (market.includes("CN")) targetCurrency = "CNY"
else if (market.includes("HK")) targetCurrency = "HKD"
else targetCurrency = "USD"
}
// 2. Find Latest Valid Data for each field
// We sort data by date descending to get latest first.
// Note: 'end_date' is the reporting period, 'update_date' is when it was fetched.
// Usually PE/PB/MarketCap are "current" values, so they might be associated with the latest reporting period or a special "current" row.
// Based on bloomberg logic, they are saved as time series. We take the latest available.
// Sort rows by date descending
const sortedRows = [...data].sort((a, b) => new Date(b.end_date).getTime() - new Date(a.end_date).getTime())
// Helper to find first non-null value
const findValue = (keys: string[]) => {
for (const row of sortedRows) {
// Check currency match if required (PE/PB/MarketCap are currency dependent usually, or at least MarketCap is)
// However, PE/PB are ratios.
// Strict currency check for everything to be safe?
if (targetCurrency !== 'Auto') {
if (row.currency && row.currency !== targetCurrency) continue
} else {
// If auto, try to match first row's currency if established, or just take any?
// Let's stick to the targetCurrency logic used in Table which resolved 'Auto' to a specific one if possible.
}
for (const key of keys) {
if (row[key] !== null && row[key] !== undefined && row[key] !== '') {
return { value: row[key], row }
}
}
}
return null
}
// Extract Fields
const companyName = findValue(['company_name'])?.value || '-'
// Find latest update_date from ALL rows matching currency
let maxUpdateDate = ''
for (const row of data) {
if (targetCurrency !== 'Auto' && row.currency && row.currency !== targetCurrency) continue
if (row.update_date && row.update_date > maxUpdateDate) {
maxUpdateDate = row.update_date
}
}
const updateDate = maxUpdateDate
// update_date is a timestamp string "2023-10-xx 10:00:00". User wants "Day only".
const displayDate = updateDate ? formatDate(updateDate) : '-'
const pe = findValue(['pe', 'pe_ratio'])?.value
const pb = findValue(['pb', 'pb_ratio'])?.value
const marketCapTuple = findValue(['market_cap'])
const marketCap = marketCapTuple?.value
const marketCapCurrency = marketCapTuple?.row?.currency || targetCurrency
const abroadRev = findValue(['rev_abroad', 'pct_revenue_from_foreign_sources'])?.value
const divYield = findValue(['dividend_yield', 'dividend_12_month_yield'])?.value
const ipoDateRaw = findValue(['ipo_date', 'IPO_date', 'eqy_init_po_dt'])?.value
const ipoDate = ipoDateRaw ? formatDate(ipoDateRaw) : '-'
// Formatters
const formatRatio = (val: any) => {
if (val === undefined || val === null) return '-'
const num = parseFloat(val)
if (isNaN(num)) return '-'
return num.toFixed(2)
}
const formatPercent = (val: any) => {
if (val === undefined || val === null) return '-'
const num = parseFloat(val)
if (isNaN(num)) return '-'
return num.toFixed(2) + '%'
}
const formatMoney = (val: any, currency: string) => {
if (val === undefined || val === null) return '-'
let num = parseFloat(val)
if (isNaN(num)) return '-'
// Backend now returns Market Cap in Millions for ALL currencies (via BDH).
// To convert Millions to "Yi" (100 Million), we divide by 100.
// This applies uniformly to JPY, USD, CNY, etc.
num = num / 100
return num.toLocaleString('en-US', { maximumFractionDigits: 2 }) + ' 亿'
}
return (
<div className="flex items-center gap-6 text-sm bg-muted/30 px-4 py-2 rounded-lg border">
{/* Group 1: Identity */}
<div className="flex flex-col gap-0.5 border-r pr-6">
<span className="font-bold text-lg text-primary truncate max-w-[200px]" title={companyName}>{companyName}</span>
<div className="flex gap-3 text-xs text-muted-foreground">
<span>IPO: {ipoDate}</span>
<span>: {displayDate}</span>
</div>
</div>
{/* Group 2: Key Ratios */}
<div className="flex items-center gap-6">
<div className="flex flex-col items-center">
<span className="text-muted-foreground text-xs scale-90">PE</span>
<span className="font-mono font-bold text-base">{formatRatio(pe)}</span>
</div>
<div className="flex flex-col items-center">
<span className="text-muted-foreground text-xs scale-90">PB</span>
<span className="font-mono font-bold text-base">{formatRatio(pb)}</span>
</div>
<div className="flex flex-col items-center">
<span className="text-muted-foreground text-xs scale-90"></span>
<span className="font-mono font-bold text-base">{formatPercent(divYield)}</span>
</div>
</div>
{/* Group 3: Market Size & Biz */}
<div className="flex items-center gap-6 border-l pl-6">
<div className="flex flex-col items-end">
<span className="text-muted-foreground text-xs scale-90"> ({marketCapCurrency})</span>
<span className="font-mono font-bold text-base text-blue-600 dark:text-blue-400">{formatMoney(marketCap, marketCapCurrency)}</span>
</div>
<div className="flex flex-col items-end">
<span className="text-muted-foreground text-xs scale-90"></span>
<span className="font-mono font-bold text-base">{formatPercent(abroadRev)}</span>
</div>
</div>
</div>
)
}
function RawDataTable({ data, title, selectedCurrency = "Auto", userMarket }: { data: any[], title: string, selectedCurrency?: string, userMarket?: string }) { function RawDataTable({ data, title, selectedCurrency = "Auto", userMarket }: { data: any[], title: string, selectedCurrency?: string, userMarket?: string }) {
if (!data || data.length === 0) { if (!data || data.length === 0) {
return ( return (
@ -418,7 +574,7 @@ function RawDataTable({ data, title, selectedCurrency = "Auto", userMarket }: {
} }
return ( return (
<TableCell key={date} className={`text-right px-4 font-mono ${highlightClass} ${textStyle}`}> <TableCell key={date} className={`text-right px-4 tabular-nums ${highlightClass} ${textStyle}`} style={{ fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace' }}>
{formatCellValue(indicator, value)} {formatCellValue(indicator, value)}
</TableCell> </TableCell>
) )

View File

@ -155,7 +155,7 @@ function FinancialTable({ data, title }: FinancialTableProps) {
{data.map((row, idx) => ( {data.map((row, idx) => (
<TableRow key={idx}> <TableRow key={idx}>
{columns.map((column) => ( {columns.map((column) => (
<TableCell key={column} className="font-mono text-right"> <TableCell key={column} className="text-right tabular-nums" style={{ fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace' }}>
{formatCellValue(column, row[column])} {formatCellValue(column, row[column])}
</TableCell> </TableCell>
))} ))}
@ -220,7 +220,7 @@ function TransposedFinancialTable({ data, title }: FinancialTableProps) {
</TableCell> </TableCell>
{/* 值 */} {/* 值 */}
{sortedData.map((row, rowIdx) => ( {sortedData.map((row, rowIdx) => (
<TableCell key={rowIdx} className="font-mono text-right px-4"> <TableCell key={rowIdx} className="text-right px-4 tabular-nums" style={{ fontFamily: 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace' }}>
{formatCellValue(indicator, row[indicator])} {formatCellValue(indicator, row[indicator])}
</TableCell> </TableCell>
))} ))}

View File

@ -1,13 +1,17 @@
"use client" "use client"
import { useEffect, useState } from "react" import { useEffect, useState } from "react"
import Link from "next/link"
import { getReports } from "@/lib/api" import { getReports } from "@/lib/api"
import { Badge } from "@/components/ui/badge" import { Badge } from "@/components/ui/badge"
import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card" import { Card, CardContent, CardHeader, CardTitle, CardDescription } from "@/components/ui/card"
import { Loader2 } from "lucide-react" import { Loader2 } from "lucide-react"
import type { SearchResult } from "@/lib/types"
export function HistoryList() { interface HistoryListProps {
onSelect?: (company: SearchResult, dataSource?: string) => void
}
export function HistoryList({ onSelect }: HistoryListProps) {
const [reports, setReports] = useState<any[]>([]) const [reports, setReports] = useState<any[]>([])
const [loading, setLoading] = useState(true) const [loading, setLoading] = useState(true)
@ -22,37 +26,47 @@ export function HistoryList() {
return ( return (
<div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3"> <div className="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
{reports.map((report: any) => ( {reports.map((report: any) => (
<Link key={report.id} href={`/analysis/${report.id}`}> <Card
<Card className="hover:shadow-lg transition-shadow cursor-pointer"> key={report.id}
<CardHeader> className="hover:shadow-lg transition-shadow cursor-pointer"
<CardTitle className="text-lg">{report.company_name}</CardTitle> onClick={() => {
<CardDescription> if (onSelect) {
{report.market} {report.symbol} onSelect({
</CardDescription> symbol: report.symbol,
</CardHeader> market: report.market,
<CardContent> company_name: report.company_name
<div className="flex items-center justify-between"> }, report.data_source)
<span className="text-sm text-muted-foreground"> }
{new Date(report.created_at).toLocaleString('zh-CN')} }}
</span> >
<Badge variant={ <CardHeader>
report.status === "completed" ? "default" : <CardTitle className="text-lg">{report.company_name}</CardTitle>
report.status === "in_progress" ? "secondary" : <CardDescription>
report.status === "failed" ? "destructive" : "outline" {report.market} {report.symbol}
}> </CardDescription>
{report.status === "completed" ? "已完成" : </CardHeader>
report.status === "in_progress" ? "进行中" : <CardContent>
report.status === "failed" ? "失败" : "待处理"} <div className="flex items-center justify-between">
</Badge> <span className="text-sm text-muted-foreground">
{new Date(report.created_at).toLocaleString('zh-CN')}
</span>
<Badge variant={
report.status === "completed" ? "default" :
report.status === "in_progress" ? "secondary" :
report.status === "failed" ? "destructive" : "outline"
}>
{report.status === "completed" ? "已完成" :
report.status === "in_progress" ? "进行中" :
report.status === "failed" ? "失败" : "待处理"}
</Badge>
</div>
{report.ai_model && (
<div className="mt-2 text-xs text-muted-foreground">
: {report.ai_model}
</div> </div>
{report.ai_model && ( )}
<div className="mt-2 text-xs text-muted-foreground"> </CardContent>
: {report.ai_model} </Card>
</div>
)}
</CardContent>
</Card>
</Link>
))} ))}
</div> </div>
) )

View File

@ -105,27 +105,27 @@ export function NavHeader() {
</Select> </Select>
<Select onValueChange={handleCompanyChange}> <Select onValueChange={handleCompanyChange}>
<SelectTrigger className="w-[240px] h-8 text-xs font-mono"> <SelectTrigger className="w-[120px] h-8 text-xs font-mono">
<SelectValue placeholder="选择最近浏览的代码..." /> <SelectValue placeholder="代码..." />
</SelectTrigger> </SelectTrigger>
<SelectContent className="z-[70]"> <SelectContent className="z-[70]">
{companies.map((c) => ( {companies.map((c) => (
<SelectItem key={`${c.symbol}:${c.market}`} value={`${c.symbol}:${c.market}`}> <SelectItem key={`${c.symbol}:${c.market}`} value={`${c.symbol}:${c.market}`}>
<span className="flex items-center gap-2 w-full"> <span className="flex items-center gap-2 w-full">
<span className="font-bold w-[60px] text-left">{c.symbol}</span> <span className="font-bold w-[50px] text-left">{c.symbol}</span>
<span className="truncate flex-1 text-left">{c.company_name}</span> <span className="truncate flex-1 text-left">{c.company_name}</span>
</span> </span>
</SelectItem> </SelectItem>
))} ))}
{companies.length === 0 && ( {companies.length === 0 && (
<div className="p-2 text-xs text-muted-foreground text-center"></div> <div className="p-2 text-xs text-muted-foreground text-center"></div>
)} )}
</SelectContent> </SelectContent>
</Select> </Select>
</div> </div>
<div className="w-[300px] ml-6"> <div className="w-[160px] ml-4">
<HeaderSearch defaultDataSource={dataSource} /> <HeaderSearch defaultDataSource={dataSource} />
</div> </div>

View File

@ -0,0 +1,83 @@
"use client"
import { useEffect, useRef, useState } from "react"
interface StockChartProps {
symbol: string
market: string
}
export function StockChart({ symbol, market }: StockChartProps) {
const containerRef = useRef<HTMLDivElement>(null)
useEffect(() => {
if (!containerRef.current) return
// Clear previous widget
containerRef.current.innerHTML = ""
// Create wrapper for widget
const widgetContainer = document.createElement("div")
widgetContainer.className = "tradingview-widget-container__widget h-full w-full"
containerRef.current.appendChild(widgetContainer)
const script = document.createElement("script")
script.src = "https://s3.tradingview.com/external-embedding/embed-widget-advanced-chart.js"
script.type = "text/javascript"
script.async = true
// Map Market/Symbol to TradingView format
let exchange = "NASDAQ"
let tvSymbol = symbol
if (market === "CN") {
if (symbol.startsWith("6")) exchange = "SSE"
else if (symbol.startsWith("0") || symbol.startsWith("3")) exchange = "SZSE"
else if (symbol.startsWith("4") || symbol.startsWith("8")) exchange = "BSE"
} else if (market === "HK") {
exchange = "HKEX"
// TradingView usually expects HK stocks without leading zeros if they are 4 digits, but let's check.
// Actually HKEX:700 works, HKEX:0700 might work too. Let's try to keep it safe.
tvSymbol = parseInt(symbol).toString()
} else if (market === "JP") {
exchange = "TSE"
} else if (market === "VN") {
exchange = "HOSE" // Primary VN exchange
} else {
// US
exchange = "NASDAQ" // Default, could be NYSE
// Basic heuristic for US
// If 4 chars or more, likely Nasdaq, <=3 likely NYSE? Not 100% accurate but acceptable default.
}
const fullSymbol = `${exchange}:${tvSymbol}`
script.innerHTML = JSON.stringify({
"autosize": true,
"symbol": fullSymbol,
"interval": "D",
"timezone": "Asia/Shanghai",
"theme": "light",
"style": "1",
"locale": "zh_CN",
"enable_publishing": false,
"allow_symbol_change": true,
"calendar": false,
"support_host": "https://www.tradingview.com"
})
containerRef.current.appendChild(script)
}, [symbol, market])
return (
<div className="h-[calc(100vh-100px)] w-full bg-background rounded-lg border overflow-hidden p-1">
<div className="tradingview-widget-container h-full w-full" ref={containerRef}>
<div className="tradingview-widget-copyright text-xs text-center text-muted-foreground p-2">
TradingView Chart by <a href="https://cn.tradingview.com/" rel="noopener nofollow" target="_blank">TradingView</a>
</div>
</div>
</div>
)
}