{"record":{"id":"45adad0406d89def","repo":"we-promise/sure","slug":"no-prices-found-for-security-symbol-on-date-d-45adad","errorCode":null,"errorMessage":"No prices found for security #{symbol} on date #{date}","messagePattern":"No prices found for security #(.+?) on date #(.+?)","errorType":"exception","errorClass":"Provider::Eodhd::InvalidSecurityPriceError","httpStatus":null,"severity":"warning","filePath":"app/models/provider/eodhd.rb","lineNumber":193,"sourceCode":"\n      SecurityInfo.new(\n        symbol: symbol,\n        name: general.dig(\"Name\"),\n        links: general.dig(\"WebURL\"),\n        logo_url: general.dig(\"LogoURL\"),\n        description: general.dig(\"Description\"),\n        kind: general.dig(\"Type\"),\n        exchange_operating_mic: exchange_operating_mic\n      )\n    end\n  end\n\n  def fetch_security_price(symbol:, exchange_operating_mic: nil, date:)\n    with_provider_response do\n      historical_data = fetch_security_prices(symbol:, exchange_operating_mic:, start_date: date, end_date: date)\n\n      raise historical_data.error if historical_data.error.present?\n      raise InvalidSecurityPriceError, \"No prices found for security #{symbol} on date #{date}\" if historical_data.data.blank?\n\n      historical_data.data.first\n    end\n  end\n\n  def fetch_security_prices(symbol:, exchange_operating_mic: nil, start_date:, end_date:)\n    with_provider_response do\n      enforce_daily_limit!\n      throttle_request\n\n      ticker = eodhd_symbol(symbol, exchange_operating_mic)\n\n      response = client.get(\"#{base_url}/api/eod/#{CGI.escape(ticker)}\") do |req|\n        req.params[\"api_token\"] = api_key\n        req.params[\"fmt\"] = \"json\"\n        req.params[\"from\"] = start_date.to_s\n        req.params[\"to\"] = end_date.to_s\n      end","sourceCodeStart":175,"sourceCodeEnd":211,"githubUrl":"https://github.com/we-promise/sure/blob/e69894adb92547273377398c15f45c979cd9416a/app/models/provider/eodhd.rb#L175-L211","documentation":"Raised as Provider::Eodhd::InvalidSecurityPriceError when fetch_security_price requests a single day ('GET /api/eod/<ticker>' with from=to=date) and the successful response contains zero price rows. The upstream call itself succeeded — this error means EODHD returned an empty array for that ticker/date, which happens for non-trading days or symbols the exchange has no data for on that date. It signals 'no data', not a transport or auth failure.","triggerScenarios":"Calling fetch_security_price(symbol:, date:) where date falls on a weekend or market holiday, the symbol/exchange MIC maps to an EODHD ticker with no quotation that day (delisted security, IPO later than the date), or the exchange was closed (e.g. asking for a US equity price on a Saturday). Any date prior to the security's listing also triggers it.","commonSituations":"Backfilling historical prices over calendar date ranges that include weekends/holidays without skipping them, requesting prices for delisted tickers, timezone misalignment between the app's Date.current and the exchange's trading day, and new securities with no trading history yet.","solutions":["Check whether the requested date is a weekend or market holiday for that exchange; if so, request the most recent prior trading day instead","Verify the ticker exists on EODHD for that date: curl 'https://eodhd.com/api/eod/AAPL.US?api_token=TOKEN&from=2024-01-01&to=2024-01-02&fmt=json'","Confirm the exchange_operating_mic maps to the right EODHD suffix (eodhd_symbol translation) so you are not querying the wrong exchange","For backfills, iterate over trading days only (e.g. use a market calendar) rather than every calendar day","If the security is delisted or listed later than the date, handle 'no price' as expected and skip rather than treat as an outage"],"exampleFix":"# before: blows up on weekends/holidays\nprice = provider.fetch_security_price(symbol: \"AAPL.US\", date: date)\n\n# after: roll back to the previous trading day (Sat/Sun only; add a holiday calendar for full correctness)\nrequest_date = date\nwhile request_date.saturday? || request_date.sunday?\n  request_date = request_date.prev_day\nend\nprice = provider.fetch_security_price(symbol: \"AAPL.US\", date: request_date)","handlingStrategy":"validation","validationCode":"# Skip non-trading days before calling fetch_security_price\nTRADING_CENTERS_HOLIDAYS = {} # populate from a market calendar gem/source\n\ndef tradable_date?(date, market)\n  return false if date.saturday? || date.sunday?\n  !TRADING_CENTERS_HOLIDAYS.dig(market, date)\nend\n\nreturn unless tradable_date?(date, \"US\")","typeGuard":null,"tryCatchPattern":"begin\n  price = provider.fetch_security_price(symbol: sym, date: date)\nrescue Provider::Eodhd::InvalidSecurityPriceError\n  # expected for weekends/holidays/delisted — record absence, do not alert\n  mark_price_missing(sym, date)\nend","preventionTips":["Iterate trading days (market calendar), not calendar days, when backfilling prices","For delisted securities, store a data-end date and stop requesting prices past it","Treat InvalidSecurityPriceError as expected 'no data', distinct from network/auth failures in alerting","Cache per symbol/date lookups so the same missing day is not re-requested on every valuation"],"tags":["eodhd","no-data","historical-prices","trading-day","securities"],"backgroundTag":"empty-api-response","analyzedSha":"e69894adb92547273377398c15f45c979cd9416a","analyzedAt":"2026-08-21T18:22:41.165Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}