_QUERY1_URL_ = 'https://query1.finance.yahoo.com'
_BASE_URL_ = 'https://query2.finance.yahoo.com'
_ROOT_URL_ = 'https://finance.yahoo.com'

_SENTINEL_ = object()

period_default = '1mo if start & end None'

fundamentals_keys = {
    'financials': ["TaxEffectOfUnusualItems", "TaxRateForCalcs", "NormalizedEBITDA", "NormalizedDilutedEPS",
                   "NormalizedBasicEPS", "TotalUnusualItems", "TotalUnusualItemsExcludingGoodwill",
                   "NetIncomeFromContinuingOperationNetMinorityInterest", "ReconciledDepreciation",
                   "ReconciledCostOfRevenue", "EBITDA", "EBIT", "NetInterestIncome", "InterestExpense",
                   "InterestIncome", "ContinuingAndDiscontinuedDilutedEPS", "ContinuingAndDiscontinuedBasicEPS",
                   "NormalizedIncome", "NetIncomeFromContinuingAndDiscontinuedOperation", "TotalExpenses",
                   "RentExpenseSupplemental", "ReportedNormalizedDilutedEPS", "ReportedNormalizedBasicEPS",
                   "TotalOperatingIncomeAsReported", "DividendPerShare", "DilutedAverageShares", "BasicAverageShares",
                   "DilutedEPS", "DilutedEPSOtherGainsLosses", "TaxLossCarryforwardDilutedEPS",
                   "DilutedAccountingChange", "DilutedExtraordinary", "DilutedDiscontinuousOperations",
                   "DilutedContinuousOperations", "BasicEPS", "BasicEPSOtherGainsLosses", "TaxLossCarryforwardBasicEPS",
                   "BasicAccountingChange", "BasicExtraordinary", "BasicDiscontinuousOperations",
                   "BasicContinuousOperations", "DilutedNIAvailtoComStockholders", "AverageDilutionEarnings",
                   "NetIncomeCommonStockholders", "OtherunderPreferredStockDividend", "PreferredStockDividends",
                   "NetIncome", "MinorityInterests", "NetIncomeIncludingNoncontrollingInterests",
                   "NetIncomeFromTaxLossCarryforward", "NetIncomeExtraordinary", "NetIncomeDiscontinuousOperations",
                   "NetIncomeContinuousOperations", "EarningsFromEquityInterestNetOfTax", "TaxProvision",
                   "PretaxIncome", "OtherIncomeExpense", "OtherNonOperatingIncomeExpenses", "SpecialIncomeCharges",
                   "GainOnSaleOfPPE", "GainOnSaleOfBusiness", "OtherSpecialCharges", "WriteOff",
                   "ImpairmentOfCapitalAssets", "RestructuringAndMergernAcquisition", "SecuritiesAmortization",
                   "EarningsFromEquityInterest", "GainOnSaleOfSecurity", "NetNonOperatingInterestIncomeExpense",
                   "TotalOtherFinanceCost", "InterestExpenseNonOperating", "InterestIncomeNonOperating",
                   "OperatingIncome", "OperatingExpense", "OtherOperatingExpenses", "OtherTaxes",
                   "ProvisionForDoubtfulAccounts", "DepreciationAmortizationDepletionIncomeStatement",
                   "DepletionIncomeStatement", "DepreciationAndAmortizationInIncomeStatement", "Amortization",
                   "AmortizationOfIntangiblesIncomeStatement", "DepreciationIncomeStatement", "ResearchAndDevelopment",
                   "SellingGeneralAndAdministration", "SellingAndMarketingExpense", "GeneralAndAdministrativeExpense",
                   "OtherGandA", "InsuranceAndClaims", "RentAndLandingFees", "SalariesAndWages", "GrossProfit",
                   "CostOfRevenue", "TotalRevenue", "ExciseTaxes", "OperatingRevenue", "LossAdjustmentExpense",
                   "NetPolicyholderBenefitsAndClaims", "PolicyholderBenefitsGross", "PolicyholderBenefitsCeded",
                   "OccupancyAndEquipment", "ProfessionalExpenseAndContractServicesExpense", "OtherNonInterestExpense"],
    'balance-sheet': ["TreasurySharesNumber", "PreferredSharesNumber", "OrdinarySharesNumber", "ShareIssued", "NetDebt",
                      "TotalDebt", "TangibleBookValue", "InvestedCapital", "WorkingCapital", "NetTangibleAssets",
                      "CapitalLeaseObligations", "CommonStockEquity", "PreferredStockEquity", "TotalCapitalization",
                      "TotalEquityGrossMinorityInterest", "MinorityInterest", "StockholdersEquity",
                      "OtherEquityInterest", "GainsLossesNotAffectingRetainedEarnings", "OtherEquityAdjustments",
                      "FixedAssetsRevaluationReserve", "ForeignCurrencyTranslationAdjustments",
                      "MinimumPensionLiabilities", "UnrealizedGainLoss", "TreasuryStock", "RetainedEarnings",
                      "AdditionalPaidInCapital", "CapitalStock", "OtherCapitalStock", "CommonStock", "PreferredStock",
                      "TotalPartnershipCapital", "GeneralPartnershipCapital", "LimitedPartnershipCapital",
                      "TotalLiabilitiesNetMinorityInterest", "TotalNonCurrentLiabilitiesNetMinorityInterest",
                      "OtherNonCurrentLiabilities", "LiabilitiesHeldforSaleNonCurrent", "RestrictedCommonStock",
                      "PreferredSecuritiesOutsideStockEquity", "DerivativeProductLiabilities", "EmployeeBenefits",
                      "NonCurrentPensionAndOtherPostretirementBenefitPlans", "NonCurrentAccruedExpenses",
                      "DuetoRelatedPartiesNonCurrent", "TradeandOtherPayablesNonCurrent",
                      "NonCurrentDeferredLiabilities", "NonCurrentDeferredRevenue",
                      "NonCurrentDeferredTaxesLiabilities", "LongTermDebtAndCapitalLeaseObligation",
                      "LongTermCapitalLeaseObligation", "LongTermDebt", "LongTermProvisions", "CurrentLiabilities",
                      "OtherCurrentLiabilities", "CurrentDeferredLiabilities", "CurrentDeferredRevenue",
                      "CurrentDeferredTaxesLiabilities", "CurrentDebtAndCapitalLeaseObligation",
                      "CurrentCapitalLeaseObligation", "CurrentDebt", "OtherCurrentBorrowings", "LineOfCredit",
                      "CommercialPaper", "CurrentNotesPayable", "PensionandOtherPostRetirementBenefitPlansCurrent",
                      "CurrentProvisions", "PayablesAndAccruedExpenses", "CurrentAccruedExpenses", "InterestPayable",
                      "Payables", "OtherPayable", "DuetoRelatedPartiesCurrent", "DividendsPayable", "TotalTaxPayable",
                      "IncomeTaxPayable", "AccountsPayable", "TotalAssets", "TotalNonCurrentAssets",
                      "OtherNonCurrentAssets", "DefinedPensionBenefit", "NonCurrentPrepaidAssets",
                      "NonCurrentDeferredAssets", "NonCurrentDeferredTaxesAssets", "DuefromRelatedPartiesNonCurrent",
                      "NonCurrentNoteReceivables", "NonCurrentAccountsReceivable", "FinancialAssets",
                      "InvestmentsAndAdvances", "OtherInvestments", "InvestmentinFinancialAssets",
                      "HeldToMaturitySecurities", "AvailableForSaleSecurities",
                      "FinancialAssetsDesignatedasFairValueThroughProfitorLossTotal", "TradingSecurities",
                      "LongTermEquityInvestment", "InvestmentsinJointVenturesatCost",
                      "InvestmentsInOtherVenturesUnderEquityMethod", "InvestmentsinAssociatesatCost",
                      "InvestmentsinSubsidiariesatCost", "InvestmentProperties", "GoodwillAndOtherIntangibleAssets",
                      "OtherIntangibleAssets", "Goodwill", "NetPPE", "AccumulatedDepreciation", "GrossPPE", "Leases",
                      "ConstructionInProgress", "OtherProperties", "MachineryFurnitureEquipment",
                      "BuildingsAndImprovements", "LandAndImprovements", "Properties", "CurrentAssets",
                      "OtherCurrentAssets", "HedgingAssetsCurrent", "AssetsHeldForSaleCurrent", "CurrentDeferredAssets",
                      "CurrentDeferredTaxesAssets", "RestrictedCash", "PrepaidAssets", "Inventory",
                      "InventoriesAdjustmentsAllowances", "OtherInventories", "FinishedGoods", "WorkInProcess",
                      "RawMaterials", "Receivables", "ReceivablesAdjustmentsAllowances", "OtherReceivables",
                      "DuefromRelatedPartiesCurrent", "TaxesReceivable", "AccruedInterestReceivable", "NotesReceivable",
                      "LoansReceivable", "AccountsReceivable", "AllowanceForDoubtfulAccountsReceivable",
                      "GrossAccountsReceivable", "CashCashEquivalentsAndShortTermInvestments",
                      "OtherShortTermInvestments", "CashAndCashEquivalents", "CashEquivalents", "CashFinancial",
                      "CashCashEquivalentsAndFederalFundsSold"],
    'cash-flow': ["ForeignSales", "DomesticSales", "AdjustedGeographySegmentData", "FreeCashFlow",
                  "RepurchaseOfCapitalStock", "RepaymentOfDebt", "IssuanceOfDebt", "IssuanceOfCapitalStock",
                  "CapitalExpenditure", "InterestPaidSupplementalData", "IncomeTaxPaidSupplementalData",
                  "EndCashPosition", "OtherCashAdjustmentOutsideChangeinCash", "BeginningCashPosition",
                  "EffectOfExchangeRateChanges", "ChangesInCash", "OtherCashAdjustmentInsideChangeinCash",
                  "CashFlowFromDiscontinuedOperation", "FinancingCashFlow", "CashFromDiscontinuedFinancingActivities",
                  "CashFlowFromContinuingFinancingActivities", "NetOtherFinancingCharges", "InterestPaidCFF",
                  "ProceedsFromStockOptionExercised", "CashDividendsPaid", "PreferredStockDividendPaid",
                  "CommonStockDividendPaid", "NetPreferredStockIssuance", "PreferredStockPayments",
                  "PreferredStockIssuance", "NetCommonStockIssuance", "CommonStockPayments", "CommonStockIssuance",
                  "NetIssuancePaymentsOfDebt", "NetShortTermDebtIssuance", "ShortTermDebtPayments",
                  "ShortTermDebtIssuance", "NetLongTermDebtIssuance", "LongTermDebtPayments", "LongTermDebtIssuance",
                  "InvestingCashFlow", "CashFromDiscontinuedInvestingActivities",
                  "CashFlowFromContinuingInvestingActivities", "NetOtherInvestingChanges", "InterestReceivedCFI",
                  "DividendsReceivedCFI", "NetInvestmentPurchaseAndSale", "SaleOfInvestment", "PurchaseOfInvestment",
                  "NetInvestmentPropertiesPurchaseAndSale", "SaleOfInvestmentProperties",
                  "PurchaseOfInvestmentProperties", "NetBusinessPurchaseAndSale", "SaleOfBusiness",
                  "PurchaseOfBusiness", "NetIntangiblesPurchaseAndSale", "SaleOfIntangibles", "PurchaseOfIntangibles",
                  "NetPPEPurchaseAndSale", "SaleOfPPE", "PurchaseOfPPE", "CapitalExpenditureReported",
                  "OperatingCashFlow", "CashFromDiscontinuedOperatingActivities",
                  "CashFlowFromContinuingOperatingActivities", "TaxesRefundPaid", "InterestReceivedCFO",
                  "InterestPaidCFO", "DividendReceivedCFO", "DividendPaidCFO", "ChangeInWorkingCapital",
                  "ChangeInOtherWorkingCapital", "ChangeInOtherCurrentLiabilities", "ChangeInOtherCurrentAssets",
                  "ChangeInPayablesAndAccruedExpense", "ChangeInAccruedExpense", "ChangeInInterestPayable",
                  "ChangeInPayable", "ChangeInDividendPayable", "ChangeInAccountPayable", "ChangeInTaxPayable",
                  "ChangeInIncomeTaxPayable", "ChangeInPrepaidAssets", "ChangeInInventory", "ChangeInReceivables",
                  "ChangesInAccountReceivables", "OtherNonCashItems", "ExcessTaxBenefitFromStockBasedCompensation",
                  "StockBasedCompensation", "UnrealizedGainLossOnInvestmentSecurities", "ProvisionandWriteOffofAssets",
                  "AssetImpairmentCharge", "AmortizationOfSecurities", "DeferredTax", "DeferredIncomeTax",
                  "DepreciationAmortizationDepletion", "Depletion", "DepreciationAndAmortization",
                  "AmortizationCashFlow", "AmortizationOfIntangibles", "Depreciation", "OperatingGainsLosses",
                  "PensionAndEmployeeBenefitExpense", "EarningsLossesFromEquityInvestments",
                  "GainLossOnInvestmentSecurities", "NetForeignCurrencyExchangeGainLoss", "GainLossOnSaleOfPPE",
                  "GainLossOnSaleOfBusiness", "NetIncomeFromContinuingOperations",
                  "CashFlowsfromusedinOperatingActivitiesDirect", "TaxesRefundPaidDirect", "InterestReceivedDirect",
                  "InterestPaidDirect", "DividendsReceivedDirect", "DividendsPaidDirect", "ClassesofCashPayments",
                  "OtherCashPaymentsfromOperatingActivities", "PaymentsonBehalfofEmployees",
                  "PaymentstoSuppliersforGoodsandServices", "ClassesofCashReceiptsfromOperatingActivities",
                  "OtherCashReceiptsfromOperatingActivities", "ReceiptsfromGovernmentGrants", "ReceiptsfromCustomers"]}

_PRICE_COLNAMES_ = ['Open', 'High', 'Low', 'Close', 'Adj Close']

quote_summary_valid_modules = (
    "summaryProfile",  # contains general information about the company
    "summaryDetail",  # prices + volume + market cap + etc
    "assetProfile",  # summaryProfile + company officers
    "fundProfile",
    "price",  # current prices
    "quoteType",  # quoteType
    "esgScores",  # Environmental, social, and governance (ESG) scores, sustainability and ethical performance of companies
    "incomeStatementHistory",
    "incomeStatementHistoryQuarterly",
    "balanceSheetHistory",
    "balanceSheetHistoryQuarterly",
    "cashFlowStatementHistory",
    "cashFlowStatementHistoryQuarterly",
    "defaultKeyStatistics",  # KPIs (PE, enterprise value, EPS, EBITA, and more)
    "financialData",  # Financial KPIs (revenue, gross margins, operating cash flow, free cash flow, and more)
    "calendarEvents",  # future earnings date
    "secFilings",  # SEC filings, such as 10K and 10Q reports
    "upgradeDowngradeHistory",  # upgrades and downgrades that analysts have given a company's stock
    "institutionOwnership",  # institutional ownership, holders and shares outstanding
    "fundOwnership",  # mutual fund ownership, holders and shares outstanding
    "majorDirectHolders",
    "majorHoldersBreakdown",
    "insiderTransactions",  # insider transactions, such as the number of shares bought and sold by company executives
    "insiderHolders",  # insider holders, such as the number of shares held by company executives
    "netSharePurchaseActivity",  # net share purchase activity, such as the number of shares bought and sold by company executives
    "earnings",  # earnings history
    "earningsHistory",
    "earningsTrend",  # earnings trend
    "industryTrend",
    "indexTrend",
    "sectorTrend",
    "recommendationTrend",
    "futuresChain",
)

# map last updated as of 2025.12.19
SECTOR_INDUSTY_MAPPING = {
    'Basic Materials': {'Specialty Chemicals',
                        'Gold',
                        'Building Materials',
                        'Copper',
                        'Steel',
                        'Agricultural Inputs',
                        'Chemicals',
                        'Other Industrial Metals & Mining',
                        'Lumber & Wood Production',
                        'Aluminum',
                        'Other Precious Metals & Mining',
                        'Coking Coal',
                        'Paper & Paper Products',
                        'Silver'},
    'Communication Services': {'Advertising Agencies',
                                'Broadcasting',
                                'Electronic Gaming & Multimedia',
                                'Entertainment',
                                'Internet Content & Information',
                                'Publishing',
                                'Telecom Services'},
    'Consumer Cyclical': {'Apparel Manufacturing',
                            'Apparel Retail',
                            'Auto & Truck Dealerships',
                            'Auto Manufacturers',
                            'Auto Parts',
                            'Department Stores',
                            'Footwear & Accessories',
                            'Furnishings, Fixtures & Appliances',
                            'Gambling',
                            'Home Improvement Retail',
                            'Internet Retail',
                            'Leisure',
                            'Lodging',
                            'Luxury Goods',
                            'Packaging & Containers',
                            'Personal Services',
                            'Recreational Vehicles',
                            'Residential Construction',
                            'Resorts & Casinos',
                            'Restaurants',
                            'Specialty Retail',
                            'Textile Manufacturing',
                            'Travel Services'},
    'Consumer Defensive': {'Beverages—Brewers',
                            'Beverages—Non-Alcoholic',
                            'Beverages—Wineries & Distilleries',
                            'Confectioners',
                            'Discount Stores',
                            'Education & Training Services',
                            'Farm Products',
                            'Food Distribution',
                            'Grocery Stores',
                            'Household & Personal Products',
                            'Packaged Foods',
                            'Tobacco'},
    'Energy': {'Oil & Gas Drilling',
                'Oil & Gas E&P',
                'Oil & Gas Equipment & Services',
                'Oil & Gas Integrated',
                'Oil & Gas Midstream',
                'Oil & Gas Refining & Marketing',
                'Thermal Coal',
                'Uranium'},
    'Financial Services': {'Asset Management',
                            'Banks—Diversified',
                            'Banks—Regional',
                            'Capital Markets',
                            'Credit Services',
                            'Financial Conglomerates',
                            'Financial Data & Stock Exchanges',
                            'Insurance Brokers',
                            'Insurance—Diversified',
                            'Insurance—Life',
                            'Insurance—Property & Casualty',
                            'Insurance—Reinsurance',
                            'Insurance—Specialty',
                            'Mortgage Finance',
                            'Shell Companies'},
    'Healthcare': {'Biotechnology',
                    'Diagnostics & Research',
                    'Drug Manufacturers—General',
                    'Drug Manufacturers—Specialty & Generic',
                    'Health Information Services',
                    'Healthcare Plans',
                    'Medical Care Facilities',
                    'Medical Devices',
                    'Medical Instruments & Supplies',
                    'Medical Distribution',
                    'Pharmaceutical Retailers'},
    'Industrials': {'Aerospace & Defense',
                    'Airlines',
                    'Airports & Air Services',
                    'Building Products & Equipment',
                    'Business Equipment & Supplies',
                    'Conglomerates',
                    'Consulting Services',
                    'Electrical Equipment & Parts',
                    'Engineering & Construction',
                    'Farm & Heavy Construction Machinery',
                    'Industrial Distribution',
                    'Infrastructure Operations',
                    'Integrated Freight & Logistics',
                    'Marine Shipping',
                    'Metal Fabrication',
                    'Pollution & Treatment Controls',
                    'Railroads',
                    'Rental & Leasing Services',
                    'Security & Protection Services',
                    'Specialty Business Services',
                    'Specialty Industrial Machinery',
                    'Staffing & Employment Services',
                    'Tools & Accessories',
                    'Trucking',
                    'Waste Management'},
    'Real Estate': {'Real Estate—Development',
                    'Real Estate Services',
                    'Real Estate—Diversified',
                    'REIT—Healthcare Facilities',
                    'REIT—Hotel & Motel',
                    'REIT—Industrial',
                    'REIT—Office',
                    'REIT—Residential',
                    'REIT—Retail',
                    'REIT—Mortgage',
                    'REIT—Specialty',
                    'REIT—Diversified'},
    'Technology': {'Communication Equipment',
                    'Computer Hardware',
                    'Consumer Electronics',
                    'Electronic Components',
                    'Electronics & Computer Distribution',
                    'Information Technology Services',
                    'Scientific & Technical Instruments',
                    'Semiconductor Equipment & Materials',
                    'Semiconductors',
                    'Software—Application',
                    'Software—Infrastructure',
                    'Solar'},
    'Utilities': {'Utilities—Diversified',
                    'Utilities—Independent Power Producers',
                    'Utilities—Regulated Electric',
                    'Utilities—Regulated Gas',
                    'Utilities—Regulated Water',
                    'Utilities—Renewable'},
}
SECTOR_INDUSTY_MAPPING_LC = {}
for k in SECTOR_INDUSTY_MAPPING.keys():
    k2 = k.lower().replace('& ', '').replace('- ', '').replace(', ', ' ').replace(' ', '-')
    SECTOR_INDUSTY_MAPPING_LC[k2] = []
    for v in SECTOR_INDUSTY_MAPPING[k]:
        v2 = v.lower().replace('& ', '').replace('- ', '').replace(', ', ' ').replace(' ', '-')
        SECTOR_INDUSTY_MAPPING_LC[k2].append(v2)

# _MIC_TO_YAHOO_SUFFIX maps Market Identifier Codes (MIC) to Yahoo Finance market suffixes.
# c.f. :
# https://help.yahoo.com/kb/finance-for-web/SLN2310.html;_ylt=AwrJKiCZFo9g3Y8AsDWPAwx.;_ylu=Y29sbwMEcG9zAzEEdnRpZAMEc2VjA3Ny?locale=en_US
# https://www.iso20022.org/market-identifier-codes

_MIC_TO_YAHOO_SUFFIX = {
    'XCBT': 'CBT', 'XCME': 'CME', 'IFUS': 'NYB', 'CECS': 'CMX', 'XNYM': 'NYM', 'XNYS': '', 'XNAS': '',  # United States
    'XBUE': 'BA',  # Argentina
    'XVIE': 'VI',  # Austria
    'XASX': 'AX', 'XAUS': 'XA',  # Australia
    'XBRU': 'BR',  # Belgium
    'BVMF': 'SA',  # Brazil
    'CNSX': 'CN', 'NEOE': 'NE', 'XTSE': 'TO', 'XTSX': 'V',  # Canada
    'XSGO': 'SN',  # Chile
    'XSHG': 'SS', 'XSHE': 'SZ',  # China
    'XBOG': 'CL',  # Colombia
    'XPRA': 'PR',  # Czech Republic
    'XCSE': 'CO',  # Denmark
    'XCAI': 'CA',  # Egypt
    'XTAL': 'TL',  # Estonia
    'CEUX': 'XD', 'XEUR': 'NX',  # Europe (Cboe Europe, Euronext)
    'XHEL': 'HE',  # Finland
    'XPAR': 'PA',  # France
    'XBER': 'BE', 'XBMS': 'BM', 'XDUS': 'DU', 'XFRA': 'F', 'XHAM': 'HM', 'XHAN': 'HA', 'XMUN': 'MU', 'XSTU': 'SG', 'XETR': 'DE',  # Germany
    'XATH': 'AT',  # Greece
    'XHKG': 'HK',  # Hong Kong
    'XBUD': 'BD',  # Hungary
    'XICE': 'IC',  # Iceland
    'XBOM': 'BO', 'XNSE': 'NS',  # India
    'XIDX': 'JK',  # Indonesia
    'XDUB': 'IR',  # Ireland
    'XTAE': 'TA',  # Israel
    'MTAA': 'MI', 'EUTL': 'TI',  # Italy
    'XTKS': 'T',  # Japan
    'XKFE': 'KW',  # Kuwait
    'XRIS': 'RG',  # Latvia
    'XVIL': 'VS',  # Lithuania
    'XKLS': 'KL',  # Malaysia
    'XMEX': 'MX',  # Mexico
    'XAMS': 'AS',  # Netherlands
    'XNZE': 'NZ',  # New Zealand
    'XOSL': 'OL',  # Norway
    'XPHS': 'PS',  # Philippines
    'XWAR': 'WA',  # Poland
    'XLIS': 'LS',  # Portugal
    'XQAT': 'QA',  # Qatar
    'XBSE': 'RO',  # Romania
    'XSES': 'SI',  # Singapore
    'XJSE': 'JO',  # South Africa
    'XKRX': 'KS', 'KQKS': 'KQ',  # South Korea
    'BMEX': 'MC',  # Spain
    'XSAU': 'SR',  # Saudi Arabia
    'XSTO': 'ST',  # Sweden
    'XSWX': 'SW',  # Switzerland
    'ROCO': 'TWO', 'XTAI': 'TW',  # Taiwan
    'XBKK': 'BK',  # Thailand
    'XIST': 'IS',  # Turkey
    'XDFM': 'AE',  # UAE
    'AQXE': 'AQ', 'XCHI': 'XC', 'XLON': 'L', 'ILSE': 'IL',  # United Kingdom
    'XCAR': 'CR',  # Venezuela
    'XSTC': 'VN'  # Vietnam
}

def merge_two_level_dicts(dict1, dict2):
    result = dict1.copy()
    for key, value in dict2.items():
        if key in result:
            # If both are sets, merge them
            if isinstance(value, set) and isinstance(result[key], set):
                result[key] = result[key] | value
            # If both are dicts, merge their contents
            elif isinstance(value, dict) and isinstance(result[key], dict):
                result[key] = {
                    k: (result[key].get(k, set()) | v if isinstance(v, set) 
                        else v) if k in result[key]
                    else v
                    for k, v in value.items()
                }
        else:
            result[key] = value
    return result

EQUITY_SCREENER_EQ_MAP = {
    "exchange": {
        'ae': {'DFM'},
        'ar': {'BUE'},
        'at': {'VIE'},
        'au': {'ASX', 'CXA'},
        'be': {'BRU'},
        'br': {'SAO'},
        'ca': {'CNQ', 'NEO', 'TOR', 'VAN'},
        'ch': {'EBS'},
        'cl': {'SGO'},
        'cn': {'SHH', 'SHZ'},
        'co': {'BVC'},
        'cz': {'PRA'},
        'de': {'BER', 'DUS', 'EUX', 'FRA', 'HAM', 'HAN', 'GER', 'MUN', 'STU'},
        'dk': {'CPH'},
        'ee': {'TAL'},
        'eg': {'CAI'},
        'es': {'MAD', 'MCE'},
        'fi': {'HEL'},
        'fr': {'ENX', 'PAR'},
        'gb': {'AQS', 'CXE', 'IOB', 'LSE'},
        'gr': {'ATH'},
        'hk': {'HKG'},
        'hu': {'BUD'},
        'id': {'JKT'},
        'ie': {'ISE'},
        'il': {'TLV'},
        'in': {'BSE', 'NSI'},
        'is': {'ICE'},
        'it': {'MDD', 'MIL', 'TLO'},
        'jp': {'FKA', 'JPX', 'OSA', 'SAP'},
        'kr': {'KOE', 'KSC'},
        'kw': {'KUW'},
        'lk': {'CSE'},
        'lt': {'LIT'},
        'lv': {'RIS'},
        'mx': {'MEX'},
        'my': {'KLS'},
        'nl': {'AMS', 'DXE'},
        'no': {'OSL'},
        'nz': {'NZE'},
        'pe': {},
        'ph': {'PHP', 'PHS'},
        'pk': {'KAR'},
        'pl': {'WSE'},
        'pt': {'LIS'},
        'qa': {'DOH'},
        'ro': {'BVB'},
        'ru': {'MCX'},
        'sa': {'SAU'},
        'se': {'STO'},
        'sg': {'SES'},
        'sr': {},
        'th': {'SET'},
        'tr': {'IST'},
        'tw': {'TAI', 'TWO'},
        'us': {'ASE', 'BTS', 'CXI', 'NAE', 'NCM', 'NGM', 'NMS', 'NYQ', 'OEM', 'OQB', 'OQX', 'PCX', 'PNK', 'YHD'},
        've': {'CCS'},
        'vn': {'VSE'},
        'za': {'JNB'}
    },
    "sector": {
        "Basic Materials", "Industrials", "Communication Services", "Healthcare",
        "Real Estate", "Technology", "Energy", "Utilities", "Financial Services",
        "Consumer Defensive", "Consumer Cyclical"
    },
    "industry": SECTOR_INDUSTY_MAPPING,
    "peer_group": {
        "US Fund Equity Energy",
        "US CE Convertibles",
        "EAA CE UK Large-Cap Equity",
        "EAA CE Other",
        "US Fund Financial",
        "India CE Multi-Cap",
        "US Fund Foreign Large Blend",
        "US Fund Consumer Cyclical",
        "EAA Fund Global Equity Income",
        "China Fund Sector Equity Financial and Real Estate",
        "US Fund Equity Precious Metals",
        "EAA Fund RMB Bond - Onshore",
        "China Fund QDII Greater China Equity",
        "US Fund Large Growth",
        "EAA Fund Germany Equity",
        "EAA Fund Hong Kong Equity",
        "EAA CE UK Small-Cap Equity",
        "US Fund Natural Resources",
        "US CE Preferred Stock",
        "India Fund Sector - Financial Services",
        "US Fund Diversified Emerging Mkts",
        "EAA Fund South Africa & Namibia Equity",
        "China Fund QDII Sector Equity",
        "EAA CE Sector Equity Biotechnology",
        "EAA Fund Switzerland Equity",
        "US Fund Large Value",
        "EAA Fund Asia ex-Japan Equity",
        "US Fund Health",
        "US Fund China Region",
        "EAA Fund Emerging Europe ex-Russia Equity",
        "EAA Fund Sector Equity Industrial Materials",
        "EAA Fund Japan Large-Cap Equity",
        "EAA Fund EUR Corporate Bond",
        "US Fund Technology",
        "EAA CE Global Large-Cap Blend Equity",
        "Mexico Fund Mexico Equity",
        "US Fund Trading--Leveraged Equity",
        "EAA Fund Sector Equity Consumer Goods & Services",
        "US Fund Large Blend",
        "EAA Fund Global Flex-Cap Equity",
        "EAA Fund EUR Aggressive Allocation - Global",
        "EAA Fund China Equity",
        "EAA Fund Global Large-Cap Growth Equity",
        "US CE Options-based",
        "EAA Fund Sector Equity Financial Services",
        "EAA Fund Europe Large-Cap Blend Equity",
        "EAA Fund China Equity - A Shares",
        "EAA Fund USD Corporate Bond",
        "EAA Fund Eurozone Large-Cap Equity",
        "China Fund Aggressive Allocation Fund",
        "EAA Fund Sector Equity Technology",
        "EAA Fund Global Emerging Markets Equity",
        "EAA Fund EUR Moderate Allocation - Global",
        "EAA Fund Other Bond",
        "EAA Fund Denmark Equity",
        "EAA Fund US Large-Cap Blend Equity",
        "India Fund Large-Cap",
        "Paper & Forestry",
        "Containers & Packaging",
        "US Fund Miscellaneous Region",
        "Energy Services",
        "EAA Fund Other Equity",
        "Homebuilders",
        "Construction Materials",
        "China Fund Equity Funds",
        "Steel",
        "Consumer Durables",
        "EAA Fund Global Large-Cap Blend Equity",
        "Transportation Infrastructure",
        "Precious Metals",
        "Building Products",
        "Traders & Distributors",
        "Electrical Equipment",
        "Auto Components",
        "Construction & Engineering",
        "Aerospace & Defense",
        "Refiners & Pipelines",
        "Diversified Metals",
        "Textiles & Apparel",
        "Industrial Conglomerates",
        "Household Products",
        "Commercial Services",
        "Food Retailers",
        "Semiconductors",
        "Media",
        "Automobiles",
        "Consumer Services",
        "Technology Hardware",
        "Transportation",
        "Telecommunication Services",
        "Oil & Gas Producers",
        "Machinery",
        "Retailing",
        "Healthcare",
        "Chemicals",
        "Food Products",
        "Diversified Financials",
        "Real Estate",
        "Insurance",
        "Utilities",
        "Pharmaceuticals",
        "Software & Services",
        "Banks"
    }
}
EQUITY_SCREENER_EQ_MAP['region'] = EQUITY_SCREENER_EQ_MAP['exchange'].keys()
ordered_keys = ['region'] + [k for k in EQUITY_SCREENER_EQ_MAP.keys() if k != 'region']
EQUITY_SCREENER_EQ_MAP = {k:EQUITY_SCREENER_EQ_MAP[k] for k in ordered_keys}
FUND_SCREENER_EQ_MAP = {
    "exchange": {
        'ae': {'DFM'},
        'ar': {'BUE'},
        'at': {'VIE'},
        'au': {'ASX','CXA'},
        'be': {'BRU'},
        'br': {'SAO'},
        'ca': {'CNQ','NEO','TOR','VAN'},
        'ch': {'EBS'},
        'cl': {'SGO'},
        'co': {'BVC'},
        'cn': {'SHH','SHZ'},
        'cz': {'PRA'},
        'de': {'BER','DUS','EUX','FRA','GER','HAM','HAN','MUN','STU',},
        'dk': {'CPH'},
        'ee': {'TAL'},
        'eg': {'CAI'},
        'es': {'BAR','MAD','MCE'},
        'fi': {'HEL'},
        'fr': {'ENX','PAR'},
        'gb': {'CXE','IOB','LSE'},
        'gr': {'ATH'},
        'hk': {'HKG'},
        'hu': {'BUD'},
        'id': {'JKT'},
        'ie': {'ISE'},
        'il': {'TLV'},
        'in': {'BSE','NSI'},
        'is': {'ICE'},
        'it': {'MIL'},
        'jp': {'FKA','JPX','OSA','SAP'},
        'kr': {'KOE','KSC'},
        'kw': {'KUW'},
        'lk': {'CSE'},
        'lt': {'LIT'},
        'lv': {'RIS'},
        'mx': {'MEX'},
        'my': {'KLS'},
        'nl': {'AMS'},
        'no': {'OSL'},
        'nz': {'NZE'},
        'pe': {''},
        'ph': {'PHP', 'PHS'},
        'pk': {'KAR'},
        'pl': {'WSE'},
        'pt': {'LIS'},
        'qa': {'DOH'},
        'ro': {'BVB'},
        'ru': {'MCX'},
        'sa': {'SAU'},
        'se': {'STO'},
        'sg': {'SES'},
        'sr': {''},
        'th': {'SET'},
        'tr': {'IST'},
        'tw': {'TAI','TWO'},
        'us': {'ASE','NAS','NCM','NGM','NMS','NYQ','OEM','OGM','OQB','PNK','WCB',},
        've': {'CCS'},
        'vn': {'VSE'},
        'za': {'JNB'}
    }
}
COMMON_SCREENER_FIELDS = {
    "price":{
        "eodprice",
        "intradaypricechange",
        "intradayprice"
    },
    "eq_fields": {
        "exchange"}, 
}
FUND_SCREENER_FIELDS = {
    "eq_fields": {
        "categoryname",
        "performanceratingoverall",
        "initialinvestment", 
        "annualreturnnavy1categoryrank", 
        "riskratingoverall"}
}
FUND_SCREENER_FIELDS = merge_two_level_dicts(FUND_SCREENER_FIELDS, COMMON_SCREENER_FIELDS)
EQUITY_SCREENER_FIELDS = {
    "eq_fields": {
        "region",
        "sector",
        "peer_group",
        "industry"}, 
    "price":{
        "lastclosemarketcap.lasttwelvemonths",
        "percentchange",
        "lastclose52weekhigh.lasttwelvemonths",
        "fiftytwowkpercentchange",
        "lastclose52weeklow.lasttwelvemonths",
        "intradaymarketcap"},
    "trading":{
        "beta",
        "avgdailyvol3m",
        "pctheldinsider",
        "pctheldinst",
        "dayvolume",
        "eodvolume"},
    "short_interest":{
        "short_percentage_of_shares_outstanding.value",
        "short_interest.value",
        "short_percentage_of_float.value",
        "days_to_cover_short.value",
        "short_interest_percentage_change.value"},
    "valuation":{
        "bookvalueshare.lasttwelvemonths",
        "lastclosemarketcaptotalrevenue.lasttwelvemonths",
        "lastclosetevtotalrevenue.lasttwelvemonths",
        "pricebookratio.quarterly",
        "peratio.lasttwelvemonths",
        "lastclosepricetangiblebookvalue.lasttwelvemonths",
        "lastclosepriceearnings.lasttwelvemonths",
        "pegratio_5y"},
    "profitability":{
        "consecutive_years_of_dividend_growth_count",
        "returnonassets.lasttwelvemonths",
        "returnonequity.lasttwelvemonths",
        "forward_dividend_per_share",
        "forward_dividend_yield",
        "returnontotalcapital.lasttwelvemonths"},
    "leverage":{
        "lastclosetevebit.lasttwelvemonths",
        "netdebtebitda.lasttwelvemonths",
        "totaldebtequity.lasttwelvemonths",
        "ltdebtequity.lasttwelvemonths",
        "ebitinterestexpense.lasttwelvemonths",
        "ebitdainterestexpense.lasttwelvemonths",
        "lastclosetevebitda.lasttwelvemonths",
        "totaldebtebitda.lasttwelvemonths"},
    "liquidity":{
        "quickratio.lasttwelvemonths",
        "altmanzscoreusingtheaveragestockinformationforaperiod.lasttwelvemonths",
        "currentratio.lasttwelvemonths",
        "operatingcashflowtocurrentliabilities.lasttwelvemonths"},
    "income_statement":{
        "totalrevenues.lasttwelvemonths",
        "netincomemargin.lasttwelvemonths",
        "grossprofit.lasttwelvemonths",
        "ebitda1yrgrowth.lasttwelvemonths",
        "dilutedepscontinuingoperations.lasttwelvemonths",
        "quarterlyrevenuegrowth.quarterly",
        "epsgrowth.lasttwelvemonths",
        "netincomeis.lasttwelvemonths",
        "ebitda.lasttwelvemonths",
        "dilutedeps1yrgrowth.lasttwelvemonths",
        "totalrevenues1yrgrowth.lasttwelvemonths",
        "operatingincome.lasttwelvemonths",
        "netincome1yrgrowth.lasttwelvemonths",
        "grossprofitmargin.lasttwelvemonths",
        "ebitdamargin.lasttwelvemonths",
        "ebit.lasttwelvemonths",
        "basicepscontinuingoperations.lasttwelvemonths",
        "netepsbasic.lasttwelvemonths"
        "netepsdiluted.lasttwelvemonths"},
    "balance_sheet":{
        "totalassets.lasttwelvemonths",
        "totalcommonsharesoutstanding.lasttwelvemonths",
        "totaldebt.lasttwelvemonths",
        "totalequity.lasttwelvemonths",
        "totalcurrentassets.lasttwelvemonths",
        "totalcashandshortterminvestments.lasttwelvemonths",
        "totalcommonequity.lasttwelvemonths",
        "totalcurrentliabilities.lasttwelvemonths",
        "totalsharesoutstanding"},
    "cash_flow":{
        "forward_dividend_yield",
        "leveredfreecashflow.lasttwelvemonths",
        "capitalexpenditure.lasttwelvemonths",
        "cashfromoperations.lasttwelvemonths",
        "leveredfreecashflow1yrgrowth.lasttwelvemonths",
        "unleveredfreecashflow.lasttwelvemonths",
        "cashfromoperations1yrgrowth.lasttwelvemonths"},
    "esg":{
        "esg_score",
        "environmental_score",
        "governance_score",
        "social_score",
        "highest_controversy"}
}
EQUITY_SCREENER_FIELDS = merge_two_level_dicts(EQUITY_SCREENER_FIELDS, COMMON_SCREENER_FIELDS)
ETF_SCREENER_EQ_MAP = {
    "exchange": {
        'ae': {'DFM'},
        'ar': {'BUE'},
        'at': {'VIE'},
        'au': {'ASX', 'CXA'},
        'be': {'BRU'},
        'br': {'SAO'},
        'ca': {'CNQ', 'NEO', 'TOR', 'VAN'},
        'ch': {'EBS'},
        'cl': {'SGO'},
        'cn': {'SHH', 'SHZ'},
        'co': {'BVC'},
        'cz': {'PRA'},
        'de': {'BER', 'DUS', 'EUX', 'FRA', 'HAM', 'HAN', 'GER', 'MUN', 'STU'},
        'dk': {'CPH'},
        'ee': {'TAL'},
        'eg': {'CAI'},
        'es': {'MAD', 'MCE'},
        'fi': {'HEL'},
        'fr': {'ENX', 'PAR'},
        'gb': {'AQS', 'CXE', 'IOB', 'LSE'},
        'gr': {'ATH'},
        'hk': {'HKG'},
        'hu': {'BUD'},
        'id': {'JKT'},
        'ie': {'ISE'},
        'il': {'TLV'},
        'in': {'BSE', 'NSI'},
        'is': {'ICE'},
        'it': {'MDD', 'MIL', 'TLO'},
        'jp': {'FKA', 'JPX', 'OSA', 'SAP'},
        'kr': {'KOE', 'KSC'},
        'kw': {'KUW'},
        'lk': {'CSE'},
        'lt': {'LIT'},
        'lv': {'RIS'},
        'mx': {'MEX'},
        'my': {'KLS'},
        'nl': {'AMS', 'DXE'},
        'no': {'OSL'},
        'nz': {'NZE'},
        'pe': {},
        'ph': {'PHP', 'PHS'},
        'pk': {'KAR'},
        'pl': {'WSE'},
        'pt': {'LIS'},
        'qa': {'DOH'},
        'ro': {'BVB'},
        'ru': {'MCX'},
        'sa': {'SAU'},
        'se': {'STO'},
        'sg': {'SES'},
        'sr': {},
        'th': {'SET'},
        'tr': {'IST'},
        'tw': {'TAI', 'TWO'},
        'us': {'ASE', 'BTS', 'CXI', 'NAE', 'NCM', 'NGM', 'NMS', 'NYQ', 'OEM', 'OQB', 'OQX', 'PCX', 'PNK', 'YHD'},
        've': {'CCS'},
        'vn': {'VSE'},
        'za': {'JNB'}
    },
    "categoryname": {
        "Allocation--15% to 30% Equity",
        "Allocation--30% to 50% Equity",
        "Allocation--50% to 70% Equity",
        "Allocation--70% to 85% Equity",
        "Allocation--85%+ Equity",
        "Bank Loan",
        "Bear Market",
        "China Region",
        "Commodities Agriculture",
        "Commodities Broad Basket",
        "Convertibles",
        "Corporate Bond",
        "Diversified Emerging Mkts",
        "Diversified Pacific/Asia",
        "Emerging Markets Bond",
        "Emerging-Markets Local-Currency Bond",
        "Energy Limited Partnership",
        "Equity Energy",
        "Equity Precious Metals",
        "Europe Stock",
        "Financial",
        "Foreign Large Blend",
        "Foreign Large Growth",
        "Foreign Large Value",
        "Foreign Small/Mid Blend",
        "Foreign Small/Mid Growth",
        "Foreign Small/Mid Value",
        "Global Real Estate",
        "Health",
        "High Yield Bond",
        "High Yield Muni",
        "Inflation-Protected Bond",
        "Infrastructure",
        "Intermediate Government",
        "Intermediate-Term Bond",
        "Japan Stock",
        "Large Blend",
        "Large Growth",
        "Large Value",
        "Long Government",
        "Long-Short Credit",
        "Long-Short Equity",
        "Long-Term Bond",
        "Managed Futures",
        "Market Neutral",
        "Mid-Cap Blend",
        "Mid-Cap Growth",
        "Mid-Cap Value",
        "Miscellaneous Region",
        "Multialternative",
        "Multicurrency",
        "Multisector Bond",
        "Muni California Intermediate",
        "Muni California Long",
        "Muni Massachusetts",
        "Muni Minnesota",
        "Muni National Interm",
        "Muni National Long",
        "Muni National Short",
        "Muni New Jersey",
        "Muni New York Intermediate",
        "Muni New York Long",
        "Muni Ohio",
        "Muni Pennsylvania",
        "Muni Single State Interm",
        "Muni Single State Long",
        "Muni Single State Short",
        "Natural Resources",
        "Nontraditional Bond",
        "Option Writing",
        "Other",
        "Other Allocation",
        "Pacific/Asia ex-Japan Stk",
        "Preferred Stock",
        "Real Estate",
        "Short Government",
        "Short-Term Bond",
        "Small Blend",
        "Small Growth",
        "Small Value",
        "Tactical Allocation",
        "Target-Date 2000-2010",
        "Target-Date 2015",
        "Target-Date 2020",
        "Target-Date 2025",
        "Target-Date 2030",
        "Target-Date 2035",
        "Target-Date 2040",
        "Target-Date 2045",
        "Target-Date 2050",
        "Target-Date 2055",
        "Target-Date 2060+",
        "Target-Date Retirement",
        "Technology",
        "Trading - Leveraged/Inverse Commodities",
        "Trading - Leveraged/Inverse Equity",
        "Trading--Inverse Equity",
        "Trading--Leveraged Equity",
        "Ultrashort Bond",
        "Utilities",
        "World Allocation",
        "World Bond",
        "World Stock"
    },
    "fundfamilyname": {
        "ALPS",
        "AMG Funds",
        "AQR Funds",
        "Aberdeen",
        "Alger",
        "AllianceBernstein",
        "Allianz Funds",
        "American Beacon",
        "American Century Investments",
        "American Funds",
        "Aquila",
        "Artisan",
        "BMO Funds",
        "BNY Mellon Funds",
        "Baird",
        "Barclays Funds",
        "Barings Funds",
        "Baron Capital Group",
        "BlackRock",
        "Brown Advisory Funds",
        "Calamos",
        "Calvert Investments",
        "Catalyst Mutual Funds",
        "Cohen & Steers",
        "Columbia",
        "Commerz Funds Solutions SA",
        "Commerzbank AG, Frankfurt am Main",
        "Davis Funds",
        "Delaware Investments",
        "Deutsche Asset Management",
        "Deutsche Bank AG",
        "Diamond Hill Funds",
        "Dimensional Fund Advisors",
        "Direxion Funds",
        "DoubleLine",
        "Dreyfus",
        "Dunham Funds",
        "Eagle Funds",
        "Eaton Vance",
        "Federated",
        "Fidelity Investments",
        "First Investors",
        "First Trust",
        "Flexshares Trust",
        "Franklin Templeton Investments",
        "GMO",
        "Gabelli",
        "Global X Funds",
        "Goldman Sachs",
        "Great-West Funds",
        "Guggenheim Investments",
        "GuideStone Funds",
        "HSBC",
        "Hancock Horizon",
        "Harbor",
        "Hartford Mutual Funds",
        "Henderson Global",
        "Hennessy",
        "Highland Funds",
        "ICON Funds",
        "Invesco",
        "Ivy Funds",
        "JPMorgan",
        "Janus",
        "John Hancock",
        "Lazard",
        "Legg Mason",
        "Lord Abbett",
        "MFS",
        "Madison Funds",
        "MainStay",
        "Manning & Napier",
        "Market Vectors",
        "MassMutual",
        "Matthews Asia Funds",
        "Morgan Stanley",
        "Nationwide",
        "Natixis Funds",
        "Neuberger Berman",
        "Northern Funds",
        "Nuveen",
        "OppenheimerFunds",
        "PNC Funds",
        "Pacific funds series trust",
        "Pax World",
        "Paydenfunds",
        "Pimco",
        "Pioneer Investments",
        "PowerShares",
        "Principal Funds",
        "ProFunds",
        "ProShares",
        "Prudential Investments",
        "Putnam",
        "RBC Global Asset Management.",
        "RidgeWorth",
        "Royce",
        "Russell",
        "Rydex Funds",
        "SEI",
        "SPDR State Street Global Advisors",
        "Salient Funds",
        "Saratoga",
        "Schwab Funds",
        "Sentinel",
        "Shelton Capital Management",
        "State Farm",
        "State Street Global Advisors (Chicago)",
        "Sterling Capital Funds",
        "SunAmerica",
        "T. Rowe Price",
        "TCW",
        "TIAA-CREF Asset Management",
        "Teton Westwood Funds",
        "Thornburg",
        "Thrivent",
        "Timothy Plan",
        "Touchstone",
        "Transamerica",
        "UBS",
        "UBS Group AG",
        "USAA",
        "VALIC",
        "Vanguard",
        "Vantagepoint Funds",
        "Victory",
        "Virtus",
        "Voya",
        "Waddell & Reed",
        "Wasatch",
        "Wells Fargo Funds",
        "William Blair",
        "WisdomTree",
        "iShares"
    },
    "morningstar_economic_moat": {
        "Wide",
        "Narrow",
        "None"
    },
    "morningstar_stewardship": {
        "Exemplary",
        "Standard",
        "Poor"
    },
    "morningstar_uncertainty": {
        "Low",
        "Medium",
        "High",
        "Very High",
        "Extreme"
    },
    "morningstar_moat_trend": {
        "Stable",
        "Positive",
        "Negative"
    },
    "morningstar_rating_change": {
        "Upgrade",
        "Downgrade"
    }
}
ETF_SCREENER_FIELDS = {
    "eq_fields": {
        "categoryname",
        "fundfamilyname",
        "region",
        "primary_sector",
        "morningstar_economic_moat",
        "morningstar_stewardship",
        "morningstar_uncertainty",
        "morningstar_moat_trend",
        "morningstar_rating_change"},
    "fundamentals": {
        "fundnetassets",
        "ticker"},
    "feesandexpenses": {
        "annualreportgrossexpenseratio",
        "annualreportnetexpenseratio",
        "turnoverratio"},
    "historicalperformance": {
        "annualreturnnavy1",
        "annualreturnnavy1categoryrank",
        "annualreturnnavy3",
        "annualreturnnavy5"},
    "keystats": {
        "avgdailyvol3m",
        "dayvolume",
        "eodvolume",
        "fiftytwowkpercentchange",
        "percentchange"},
    "morningstar_rating": {
        "morningstar_last_close_price_to_fair_value",
        "morningstar_rating",
        "morningstar_rating_updated_time"},
    "portfoliostatistics": {
        "marketcapitalvaluelong"},
    "purchasedetails": {
        "initialinvestment"},
    "trailingperformance": {
        "performanceratingoverall",
        "quarterendtrailingreturnytd",
        "riskratingoverall",
        "trailing_3m_return",
        "trailing_ytd_return"}
}
ETF_SCREENER_FIELDS = merge_two_level_dicts(ETF_SCREENER_FIELDS, COMMON_SCREENER_FIELDS)

USER_AGENTS = [
    # Chrome
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36",
    "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36",

    # Firefox
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:135.0) Gecko/20100101 Firefox/135.0",
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 14.7; rv:135.0) Gecko/20100101 Firefox/135.0",
    "Mozilla/5.0 (X11; Linux i686; rv:135.0) Gecko/20100101 Firefox/135.0",

    # Safari
    "Mozilla/5.0 (Macintosh; Intel Mac OS X 14_7_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.3 Safari/605.1.15",

    # Edge
    "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36 Edg/131.0.2903.86"
]
