Building a Go Yahoo Finance Library with Claude Code #3

The third post in a series about building a Go version of the Yahoo Finance library based on Python’s yfinance, utilizing Claude Code.

Author Avatar

wonjoon

  ยท  5 min read

Does it match yfinance? #

The reason I’m implementing go-yfinance is simply that there isn’t a Yahoo Finance library written in Go. It might seem primitive, but until recently, there were cases where a server was implemented using the Python yfinance library just to receive results via API calls. Of course, even back then, it would have been possible to create a library converted to Go. However, analyzing and implementing it one by one would have taken quite a long time.

Now, with AI, work that would have taken months can be done in days. The go-yfinance project I’m currently working on is no exception. I’m training Claude Code with the already excellent yfinance library, checking if it can be converted to Go, and proceeding step by step.

Today, I guided it to implement ‘up to a practical level (~Phase 4)’ and wrote a blog post about it. But suddenly, a question arose.


๐Ÿ‘จ๐Ÿปโ€๐Ÿ’ป: Do the methods, parameters, and return values provided by go-yfinance match those supported by yfinance?


This was actually a quite crucial part. My goal is to allow developers familiar with yfinance to use functions in the same way even when using Go. I believed there should be no hassle of having to relearn what methods exist, how to call them, or what the results would look like when calling a method.

So, before implementing the remaining Phases, I asked Claude Code.


๐Ÿ‘จ๐Ÿปโ€๐Ÿ’ป: Please verify if the structure of methods, parameters, and result values provided by the currently written go-yfinance is identical to those provided by python’s yfinance. To minimize user confusion, everything should be the same except for the language difference. Please review if everything is identical, excluding only case sensitivity due to Public/Private method differences which are characteristics of the language. ultrathink.


Analysis Results: Python yfinance vs. Go go-yfinance #

Fortunately, most parts were confirmed to match, but there were some discrepancies.

Method Name Mismatches #

FeaturePython yfinanceGo go-yfinanceRecommended Fix
Historyticker.history(...)ticker.History(params)โœ… OK (Case difference only)
Financials (income)ticker.income_stmt / get_income_stmt(freq="quarterly")ticker.IncomeStatement(freq)โš ๏ธ Python uses income_stmt
Financials (balance)ticker.balance_sheet / get_balance_sheet()ticker.BalanceSheet(freq)โš ๏ธ Python uses balance_sheet
Financials (cashflow)ticker.cash_flow / get_cash_flow()ticker.CashFlow(freq)โš ๏ธ Python uses cash_flow
Options listticker.options (property, tuple)ticker.Options() (method, []time.Time)โš ๏ธ Python uses property
Option chainticker.option_chain(date)ticker.OptionChain(date)โœ… OK
Price targetticker.analyst_price_targetsticker.PriceTarget()โš ๏ธ Name mismatch
Recommendationsticker.recommendationsticker.Recommendations()โœ… OK
EPS Trendticker.eps_trendticker.EPSTrend()โš ๏ธ Underscore vs CamelCase
EPS Revisionsticker.eps_revisionsticker.EPSRevisions()โš ๏ธ Underscore vs CamelCase
Earnings Estimateticker.earnings_estimateticker.EarningsEstimates()โš ๏ธ Singular vs Plural
Revenue Estimateticker.revenue_estimateticker.RevenueEstimates()โš ๏ธ Singular vs Plural
Earnings Historyticker.earnings_historyticker.EarningsHistory()โœ… OK
Growth Estimatesticker.growth_estimatesticker.GrowthEstimates()โœ… OK

Parameter Name Mismatches #

History Method

Python ParameterGo ParameterMismatch
periodPeriodโœ… OK
intervalIntervalโœ… OK
startStartโœ… OK
endEndโœ… OK
prepostPrePostโœ… OK
auto_adjustAutoAdjustโš ๏ธ Python: snake_case
actionsActionsโœ… OK
repairRepairโœ… OK
keepnaKeepNAโš ๏ธ Python: keepna (lowercase)
back_adjustโŒ Noneโš ๏ธ Missing in Go
roundingโŒ Noneโš ๏ธ Missing in Go
timeoutโŒ Noneโš ๏ธ Missing in Go (Set via Config)
raise_errorsโŒ Noneโš ๏ธ Go uses error return

Financials Method

Python ParameterGo ParameterMismatch
freq=“yearly”freq=“annual”โš ๏ธ “yearly” vs “annual”
freq=“quarterly”freq=“quarterly”โœ… OK
freq=“trailing”freq=“trailing”โœ… OK
pretty=TrueโŒ Noneโš ๏ธ Missing in Go
as_dict=FalseโŒ Noneโš ๏ธ Go returns struct

Return Value Structure Mismatches #

History Return Value

PythonGoMismatch
pd.DataFrame[]models.Barโš ๏ธ DataFrame vs Slice
Columns: Open, High, Low, Close, Adj Close, VolumeFields: Open, High, Low, Close, AdjClose, Volumeโš ๏ธ Adj Close vs AdjClose
Columns: Dividends, Stock SplitsFields: Dividends, Splitsโš ๏ธ Stock Splits vs Splits
Index: DatetimeIndexField: Date time.Timeโš ๏ธ Index vs Field

Options Return Value

PythonGoMismatch
tuple of date strings[]time.Timeโš ๏ธ string vs time.Time
OptionChain.calls โ†’ pd.DataFrameOptionChain.Calls โ†’ []Optionโš ๏ธ DataFrame vs Slice

Financials Return Value

PythonGoMismatch
pd.DataFrame (rows=fields, cols=dates)FinancialStatement (map[field][]items)โš ๏ธ Different structure
Index: camelCase field namesMap keys: CamelCaseโœ… OK
Columns: pd.DatetimeIndexDates []time.Timeโš ๏ธ Different access method

FastInfo Return Value

Python KeyGo FieldMismatch
currencyCurrencyโœ… OK
quoteTypeQuoteTypeโœ… OK
lastPriceLastPriceโœ… OK
previousClosePreviousCloseโœ… OK
regularMarketPreviousCloseRegularMarketPreviousCloseโœ… OK
fiftyDayAverageFiftyDayAverageโœ… OK
twoHundredDayAverageTwoHundredDayAverageโœ… OK
tenDayAverageVolumeTenDayAverageVolumeโœ… OK
threeMonthAverageVolumeThreeMonthAverageVolumeโœ… OK
marketCapMarketCapโœ… OK
yearHighYearHighโœ… OK
yearLowYearLowโœ… OK
yearChangeYearChangeโœ… OK

Planning Corrections for Mismatches #

Claude Code prioritized the mismatched parts and listed them in order of importance.

High Priority (API Compatibility)

  • Financials freq parameter: Need to unify “yearly” โ†’ “annual”

    • Python: get_income_stmt(freq="yearly") is the default
    • Go: Currently uses “annual”
    • Recommendation: Map “yearly” to “annual” in Go as well
  • Method Name Consistency

    • PriceTarget() โ†’ AnalystPriceTargets() (Matches Python)
    • EarningsEstimates() โ†’ EarningsEstimate() (Singular)
    • RevenueEstimates() โ†’ RevenueEstimate() (Singular)

Medium Priority (Convenience)

  • Add History Parameters
    • Add BackAdjust bool
    • Add Rounding bool
  • Bar Field Names
    • Consider adding adj_close or adjclose to JSON tags for AdjClose
    • Consider adding StockSplits (alias) for Splits

Low Priority (Language Conventions)

  • Maintain Go Language Conventions
    • Keep CamelCase method names (Go Standard)
    • Keep using Methods instead of Properties (Go Standard)
    • Keep returning structs (Go has no DataFrame)

I confirmed that while core features mostly match, parameter values (freq=“yearly” vs “annual”) and some method names were inconsistent. Also, since the DataFrame structure provided by Python cannot be used in Go, I had to use Struct/Slice structures instead.

CategoryMatchMismatchNeeds Fix
Method Names863 Recommended
Parameter Names661 Mandatory
Return Value Structure-4 types differentInevitable due to Go characteristics
Field NamesMostly match2-3Optional

Implementation Results #

Summary of Changes #

ChangeFileDescription
Support freq="yearly"financials.goMaps “yearly” to “annual” to match Python yfinance
AnalystPriceTargets()analysis.goMatches Python’s analyst_price_targets
EarningsEstimate()analysis.goMatches Python’s earnings_estimate (Singular)
RevenueEstimate()analysis.goMatches Python’s revenue_estimate (Singular)
Add Testsfinancials_test.goAdded TestNormalizeFrequency

Backward Compatibility #

Existing methods were kept as deprecated aliases to ensure they continue to work.

  • PriceTarget() โ†’ Calls AnalystPriceTargets()
  • EarningsEstimates() โ†’ Calls EarningsEstimate()
  • RevenueEstimates() โ†’ Calls RevenueEstimate()