FA3-Datafetch/src/analysis/vn_analyzer.py

117 lines
5.4 KiB
Python

from .cn_analyzer import CN_Analyzer
import pandas as pd
class VN_Analyzer(CN_Analyzer):
def __init__(self):
super().__init__()
self.market = 'VN'
self.mapping = {
'income': {
'revenue': 'revenue',
'net_income': 'net_income',
'gross_profit': 'gross_profit',
'total_profit': 'total_profit',
'sga_exp': 'sga_exp'
},
'balance': {
'total_equity': 'total_equity',
'total_assets': 'total_assets',
'total_liabilities': 'total_liabilities',
'current_assets': 'current_assets',
'current_liabilities': 'current_liabilities',
'cash': 'cash',
'receivables': 'receivables',
'inventory': 'inventory',
'fixed_assets': 'fixed_assets',
'goodwill': 'goodwill',
'short_term_debt': 'short_term_debt',
'long_term_debt': 'long_term_debt'
},
'cashflow': {
'ocf': 'ocf',
'capex': 'capex',
'dividends': 'dividends'
}
}
def _post_process_columns(self, df, type):
if market_type := self.mapping.get(type):
for col in market_type.values():
if col in df.columns:
df[col] = pd.to_numeric(df[col], errors='coerce')
df = super()._post_process_columns(df, type)
if type == 'balance':
if 'long_term_investments' in df.columns:
df['lt_invest'] = df['long_term_investments']
if 'long_term_debt' not in df.columns: df['long_term_debt'] = 0
if 'long_term_borrowings' in df.columns:
df['long_term_debt'] = df['long_term_debt'].fillna(0) + df['long_term_borrowings'].fillna(0)
return df
def calculate_indicators(self, df_merged, market_metrics, historical_metrics):
if 'revenue' in df_merged.columns and 'gross_profit' in df_merged.columns:
df_merged['cogs'] = df_merged['revenue'] - df_merged['gross_profit']
df_merged = super().calculate_indicators(df_merged, market_metrics, historical_metrics)
has_sga = False
if 'sga_exp' in df_merged.columns and 'revenue' in df_merged.columns:
if df_merged['sga_exp'].notna().any() and (df_merged['sga_exp'] != 0).any():
df_merged['SgaRatio'] = self._safe_div(df_merged['sga_exp'], df_merged['revenue'])
has_sga = True
if not has_sga:
sga_sum = 0
if 'selling_exp' in df_merged.columns: sga_sum = sga_sum + df_merged['selling_exp'].fillna(0)
if 'admin_exp' in df_merged.columns: sga_sum = sga_sum + df_merged['admin_exp'].fillna(0)
if 'revenue' in df_merged.columns:
df_merged['SgaRatio'] = self._safe_div(sga_sum, df_merged['revenue'])
if 'income_tax' in df_merged.columns and 'net_income' in df_merged.columns:
ebt_approx = df_merged['net_income'] + df_merged['income_tax']
df_merged['TaxRate'] = self._safe_div(df_merged['income_tax'], ebt_approx)
if 'GrossMargin' in df_merged.columns and 'NetMargin' in df_merged.columns:
other_ratio = df_merged['GrossMargin'] - df_merged['NetMargin']
if 'SgaRatio' in df_merged.columns:
other_ratio = other_ratio - df_merged['SgaRatio'].fillna(0)
if 'RDRatio' in df_merged.columns:
other_ratio = other_ratio - df_merged['RDRatio'].fillna(0)
df_merged['OtherExpenseRatio'] = other_ratio
if 'MarketCap' in df_merged.columns:
if 'net_income' in df_merged.columns:
calculated_pe = self._safe_div(df_merged['MarketCap'], df_merged['net_income'])
if 'PE' not in df_merged.columns:
df_merged['PE'] = calculated_pe
else:
cond_pe = (df_merged['PE'] != 0) & df_merged['PE'].notna()
df_merged['PE'] = df_merged['PE'].where(cond_pe, calculated_pe)
if 'total_equity' in df_merged.columns:
calculated_pb = self._safe_div(df_merged['MarketCap'], df_merged['total_equity'])
if 'PB' not in df_merged.columns:
df_merged['PB'] = calculated_pb
else:
cond_pb = (df_merged['PB'] != 0) & df_merged['PB'].notna()
df_merged['PB'] = df_merged['PB'].where(cond_pb, calculated_pb)
if 'dividends' in df_merged.columns:
calculated_yield = self._safe_div(df_merged['dividends'], df_merged['MarketCap']) * 100
if 'DividendYield' not in df_merged.columns:
df_merged['DividendYield'] = calculated_yield
else:
df_merged['DividendYield'] = df_merged['DividendYield'].fillna(calculated_yield)
if 'employee_count' in df_merged.columns:
df_merged['Employees'] = df_merged['employee_count']
if 'revenue' in df_merged.columns:
df_merged['RevenuePerEmp'] = self._safe_div(df_merged['revenue'], df_merged['employee_count'])
if 'net_income' in df_merged.columns:
df_merged['ProfitPerEmp'] = self._safe_div(df_merged['net_income'], df_merged['employee_count'])
return df_merged