feat(rubick): rename project and add production release bundle

This commit is contained in:
Muhammad Firas 2026-03-06 03:12:28 +07:00
commit fab6cf26eb
No known key found for this signature in database
33 changed files with 11554 additions and 0 deletions

550
msn/msn_types.go Normal file
View file

@ -0,0 +1,550 @@
package msn
// MSN API Constants
const (
MSNAssetsBaseURL = "https://assets.msn.com/service/"
MSNAPIBaseURL = "https://api.msn.com/msn/v0/pages/finance/"
BingAPIBaseURL = "https://services.bingapis.com/contentservices-finance.hedgefunddataprovider/api/v1/"
// Public API key from MSN Money website
MSNAPIKey = "0QfOX3Vn51YCzitbLaRkTTBadtWpgTN8NZLW0C1SEM"
)
// ScreenerRequest is the POST body for Finance/Screener
// Uses the actual MSN API format with predefined filter keys
type ScreenerRequest struct {
Filter []ScreenerFilterItem `json:"filter"`
Order ScreenerOrder `json:"order"`
ReturnValueType []string `json:"returnValueType"`
ScreenerType string `json:"screenerType"`
Limit int `json:"limit"`
}
// ScreenerFilterItem represents a filter condition in the screener
type ScreenerFilterItem struct {
Key string `json:"key"` // e.g., "st_list_topperfs", "st_reg_id"
KeyGroup string `json:"keyGroup"` // e.g., "st_list_", "st_reg_"
IsRange bool `json:"isRange"`
}
// ScreenerOrder represents sort order for screener results
type ScreenerOrder struct {
Key string `json:"key"` // e.g., "st_1yr_asc_order"
Dir string `json:"dir"` // "asc" or "desc"
}
// ScreenerResponse from Finance/Screener
type ScreenerResponse struct {
Value []ScreenerStock `json:"value"`
Total int `json:"total"`
Count int `json:"count"`
MatchIDs []string `json:"matchIds"`
Equity []ScreenerStock `json:"equity"`
Quote []QuoteData `json:"quote"`
}
// ScreenerStock is a stock from screener results
type ScreenerStock struct {
ID string `json:"id"`
InstrumentID string `json:"instrumentId,omitempty"`
Symbol string `json:"symbol"`
ShortName string `json:"shortName"`
DisplayName string `json:"displayName,omitempty"`
ExchangeID string `json:"exchangeId"`
ExchangeCode string `json:"exchangeCode,omitempty"`
Country string `json:"country,omitempty"`
Sector string `json:"sector,omitempty"`
Industry string `json:"industry,omitempty"`
Price float64 `json:"price"`
PriceChange float64 `json:"priceChange"`
PriceChangePct float64 `json:"priceChangePercent"`
MarketCap float64 `json:"marketCap"`
Volume float64 `json:"accumulatedVolume"`
Price52wHigh float64 `json:"price52wHigh"`
Price52wLow float64 `json:"price52wLow"`
Return1Year float64 `json:"return1Year"`
ReturnYTD float64 `json:"returnYTD"`
}
// QuoteResponse from Finance/Quotes
type QuoteResponse []QuoteData
// QuoteData represents real-time quote data
type QuoteData struct {
ID string `json:"id"`
InstrumentID string `json:"instrumentId"`
Symbol string `json:"symbol"`
ShortName string `json:"shortName"`
DisplayName string `json:"displayName"`
Price float64 `json:"price"`
PriceChange float64 `json:"priceChange"`
PriceChangePct float64 `json:"priceChangePercent"`
PriceDayOpen float64 `json:"priceDayOpen"`
PriceDayHigh float64 `json:"priceDayHigh"`
PriceDayLow float64 `json:"priceDayLow"`
PricePreviousClose float64 `json:"pricePreviousClose"`
PriceClose float64 `json:"priceClose"`
Price52wHigh float64 `json:"price52wHigh"`
Price52wLow float64 `json:"price52wLow"`
AccumulatedVolume float64 `json:"accumulatedVolume"`
AverageVolume float64 `json:"averageVolume"`
MarketCap float64 `json:"marketCap"`
MarketCapCurrency string `json:"marketCapCurrency"`
ExchangeID string `json:"exchangeId"`
ExchangeCode string `json:"exchangeCode"`
ExchangeName string `json:"exchangeName"`
Currency string `json:"currency"`
Country string `json:"country"`
Market string `json:"market"`
TimeLastTraded string `json:"timeLastTraded"`
TimeLastUpdated string `json:"timeLastUpdated"`
// Historical price changes
PriceChange1Week float64 `json:"priceChange1Week"`
PriceChange1Month float64 `json:"priceChange1Month"`
PriceChange3Month float64 `json:"priceChange3Month"`
PriceChange6Month float64 `json:"priceChange6Month"`
PriceChangeYTD float64 `json:"priceChangeYTD"`
PriceChange1Year float64 `json:"priceChange1Year"`
// Historical returns (percentage)
Return1Week float64 `json:"return1Week"`
Return1Month float64 `json:"return1Month"`
Return3Month float64 `json:"return3Month"`
Return6Month float64 `json:"return6Month"`
ReturnYTD float64 `json:"returnYTD"`
Return1Year float64 `json:"return1Year"`
}
// QuoteSummaryResponse from Finance/QuoteSummary
type QuoteSummaryResponse []struct {
Quotes []QuoteData `json:"quotes"`
Exchanges []ExchangeData `json:"exchanges"`
Details []QuoteDetail `json:"quoteDetails"`
ChartData []ChartResponse `json:"charts"`
}
// ExchangeData from Finance/Exchanges
type ExchangeData struct {
ID string `json:"id"`
Name string `json:"name"`
Country string `json:"country"`
Timezone string `json:"timeZone"`
}
// QuoteDetail provides extended quote information
type QuoteDetail struct {
ID string `json:"id"`
Beta float64 `json:"beta"`
TrailingPE float64 `json:"trailingPE"`
ForwardPE float64 `json:"forwardPE"`
PriceToBook float64 `json:"priceToBook"`
PriceToSales float64 `json:"priceToSales"`
EnterpriseValue float64 `json:"enterpriseValue"`
EBITDA float64 `json:"ebitda"`
Revenue float64 `json:"revenue"`
GrossProfit float64 `json:"grossProfit"`
FreeCashFlow float64 `json:"freeCashFlow"`
DebtToEquity float64 `json:"debtToEquity"`
QuickRatio float64 `json:"quickRatio"`
CurrentRatio float64 `json:"currentRatio"`
ReturnOnEquity float64 `json:"returnOnEquity"`
ReturnOnAssets float64 `json:"returnOnAssets"`
ProfitMargin float64 `json:"profitMargin"`
OperatingMargin float64 `json:"operatingMargin"`
GrossMargin float64 `json:"grossMargin"`
}
// ChartResponse from Finance/Charts
type ChartResponse struct {
ID string `json:"_p"`
ChartType string `json:"chartType"` // "1D1M", "1M", "3M", "1Y", "3Y"
Symbol string `json:"symbol"`
Series ChartSeriesData `json:"series"`
Points []ChartPoint `json:"-"` // Computed from Series
}
// ChartSeriesData is the raw series data from the API
type ChartSeriesData struct {
TimeStamps []string `json:"timeStamps"`
Prices []float64 `json:"prices"`
OpenPrices []float64 `json:"openPrices"`
PricesHigh []float64 `json:"pricesHigh"`
PricesLow []float64 `json:"pricesLow"`
Volumes []float64 `json:"volumes"`
StartTime string `json:"startTime"`
EndTime string `json:"endTime"`
PriceHigh float64 `json:"priceHigh"`
PriceLow float64 `json:"priceLow"`
}
// ToChartPoints converts the series data into chart points
func (c *ChartResponse) ToChartPoints() []ChartPoint {
if len(c.Series.TimeStamps) == 0 {
return nil
}
points := make([]ChartPoint, len(c.Series.TimeStamps))
for i, ts := range c.Series.TimeStamps {
point := ChartPoint{Time: ts}
if i < len(c.Series.Prices) {
point.Price = c.Series.Prices[i]
point.Close = c.Series.Prices[i]
}
if i < len(c.Series.OpenPrices) {
point.Open = c.Series.OpenPrices[i]
}
if i < len(c.Series.PricesHigh) {
point.High = c.Series.PricesHigh[i]
}
if i < len(c.Series.PricesLow) {
point.Low = c.Series.PricesLow[i]
}
if i < len(c.Series.Volumes) {
point.Volume = int64(c.Series.Volumes[i])
}
points[i] = point
}
return points
}
// ChartPoint is a single data point in a chart
type ChartPoint struct {
Time string `json:"time"`
Price float64 `json:"price"`
Open float64 `json:"open"`
High float64 `json:"high"`
Low float64 `json:"low"`
Close float64 `json:"close"`
Volume int64 `json:"volume"`
}
// EquityResponse from Finance/Equities
type EquityResponse []EquityData
// EquityData represents company information
type EquityData struct {
ID string `json:"id"`
Symbol string `json:"symbol"`
ShortName string `json:"shortName"`
LongName string `json:"longName"`
Description string `json:"description"`
Sector string `json:"sector"`
Industry string `json:"industry"`
Website string `json:"website"`
Employees int `json:"fullTimeEmployees"`
Address string `json:"address"`
City string `json:"city"`
Country string `json:"country"`
Phone string `json:"phone"`
Officers []Officer `json:"officers"`
}
// Officer represents a company executive
type Officer struct {
Name string `json:"name"`
Title string `json:"title"`
Age int `json:"age"`
YearBorn int `json:"yearBorn"`
TotalPay int64 `json:"totalPay"`
}
// FinancialStatementsResponse from Finance/Equities/financialstatements
// Response is an array of FinancialStatement objects
type FinancialStatementsResponse []FinancialStatement
// FinancialStatement represents comprehensive financial data
type FinancialStatement struct {
UnderlyingInstrument InstrumentInfo `json:"underlyingInstrument"`
BalanceSheets *BalanceSheet `json:"balanceSheets"`
CashFlow *CashFlowData `json:"cashFlow"`
IncomeStatements *IncomeStatement `json:"incomeStatements"`
}
// InstrumentInfo contains basic stock information
type InstrumentInfo struct {
InstrumentID string `json:"instrumentId"`
DisplayName string `json:"displayName"`
ShortName string `json:"shortName"`
ExchangeID string `json:"exchangeId"`
ExchangeCode string `json:"exchangeCode"`
SecurityType string `json:"securityType"`
Symbol string `json:"symbol"`
}
// BalanceSheet represents balance sheet data
type BalanceSheet struct {
CurrentAssets map[string]float64 `json:"currentAssets"`
LongTermAssets map[string]float64 `json:"longTermAssets"`
CurrentLiabilities map[string]float64 `json:"currentLiabilities"`
Equity map[string]float64 `json:"equity"`
Currency string `json:"currency"`
Source string `json:"source"`
SourceDate string `json:"sourceDate"`
ReportDate string `json:"reportDate"`
EndDate string `json:"endDate"`
}
// CashFlowData represents cash flow statement
type CashFlowData struct {
Financing map[string]float64 `json:"financing"`
Investing map[string]float64 `json:"investing"`
Operating map[string]float64 `json:"operating"`
Currency string `json:"currency"`
Source string `json:"source"`
EndDate string `json:"endDate"`
}
// IncomeStatement represents income statement data
type IncomeStatement struct {
Revenue map[string]float64 `json:"revenue"`
Expenses map[string]float64 `json:"expenses"`
Currency string `json:"currency"`
Source string `json:"source"`
EndDate string `json:"endDate"`
}
// KeyRatiosResponse from api.msn.com keyratios
type KeyRatiosResponse []KeyRatios
// KeyRatios represents financial ratios with historical data
type KeyRatios struct {
StockID string `json:"stockId"`
ExchangeID string `json:"exchangeId"`
Market string `json:"market"`
Industry string `json:"industry"`
DisplayName string `json:"displayName"`
ShortName string `json:"shortName"`
Symbol string `json:"symbol"`
IndustryMetrics []IndustryMetric `json:"industryMetrics"`
}
// IndustryMetric represents financial metrics for a specific year
type IndustryMetric struct {
Year string `json:"year"`
FiscalPeriodType string `json:"fiscalPeriodType"`
RevenuePerShare float64 `json:"revenuePerShare"`
EarningsPerShare float64 `json:"earningsPerShare"`
FreeCashFlowPerShare float64 `json:"freeCashFlowPerShare"`
DividendPerShare float64 `json:"dividendPerShare"`
BookValuePerShare float64 `json:"bookValuePerShare"`
RevenueGrowthRate float64 `json:"revenueGrowthRate"`
EarningsGrowthRate float64 `json:"earningsGrowthRate"`
GrossMargin float64 `json:"grossMargin"`
OperatingMargin float64 `json:"operatingMargin"`
NetMargin float64 `json:"netMargin"`
ROE float64 `json:"roe"`
ROIC float64 `json:"roic"`
ROA float64 `json:"returnOnAssetCurrent"`
DebtToEquityRatio float64 `json:"debtToEquityRatio"`
DebtToEBITDA float64 `json:"debtToEbitda"`
FinancialLeverage float64 `json:"financialLeverage"`
QuickRatio float64 `json:"quickRatio"`
CurrentRatio float64 `json:"currentRatio"`
AssetTurnover float64 `json:"assetTurnover"`
InventoryTurnover float64 `json:"inventoryTurnover"`
ReceivableTurnover float64 `json:"receivableTurnover"`
PayoutRatio float64 `json:"payoutRatio"`
PriceToSalesRatio float64 `json:"priceToSalesRatio"`
PriceToEarningsRatio float64 `json:"priceToEarningsRatio"`
PriceToCashFlowRatio float64 `json:"priceToCashFlowRatio"`
PriceToBookRatio float64 `json:"priceToBookRatio"`
EVToEBITDA float64 `json:"evEbitda"`
}
// EarningsAPIResponse represents the actual API response from Finance/Events/Earnings
type EarningsAPIResponse struct {
History struct {
Quarterly map[string]EarningsData `json:"quarterly"`
Annual map[string]EarningsData `json:"annual"`
} `json:"History"`
InstrumentID string `json:"InstrumentId"`
Symbol string `json:"Symbol"`
}
// EarningsData represents a single earnings report from the API
type EarningsData struct {
EpsActual float64 `json:"EpsActual"`
EpsSurprise float64 `json:"EpsSurprise"`
EpsSurprisePercent float64 `json:"EpsSurprisePercent"`
EpsForecast float64 `json:"EpsForecast"`
RevenueActual float64 `json:"RevenueActual"`
RevenueSurprise float64 `json:"RevenueSurprise"`
RevenueForecast float64 `json:"RevenueForecast"`
EarningReleaseDate string `json:"EarningReleaseDate"`
CiqFiscalPeriodType string `json:"CiqFiscalPeriodType"` // e.g., "Q42025", "Q12026"
CalendarPeriodType string `json:"CalendarPeriodType"`
}
// EarningsEvent represents a normalized earnings event for storage
type EarningsEvent struct {
ID string `json:"id"`
EventDate string `json:"eventDate"`
FiscalYear int `json:"fiscalYear"`
FiscalQuarter int `json:"fiscalQuarter"`
EPSEstimate float64 `json:"epsEstimate"`
EPSActual float64 `json:"epsActual"`
EPSSurprise float64 `json:"epsSurprise"`
EPSSurprisePct float64 `json:"epsSurprisePercent"`
RevenueEstimate float64 `json:"revenueEstimate"`
RevenueActual float64 `json:"revenueActual"`
RevenueSurprise float64 `json:"revenueSurprise"`
}
// SentimentResponse from Finance/SentimentBrowser
type SentimentResponse []SentimentData
// SentimentData represents market sentiment for a stock
type SentimentData struct {
DisplayName string `json:"displayName"`
Market string `json:"market"`
InstrumentID string `json:"instrumentId"`
Symbol string `json:"symbol"`
SentimentStatistics []SentimentStatistic `json:"sentimentStatistics"`
}
// SentimentStatistic represents sentiment data for a time period
type SentimentStatistic struct {
StartTime int64 `json:"startTime"`
EndTime int64 `json:"endTime"`
TimeRangeName string `json:"timeRangeName"`
TimeRangeEnum string `json:"timeRangeEnum"`
Bullish int `json:"bullish"`
Bearish int `json:"bearish"`
Neutral int `json:"neutral"`
BullishPercent float64 `json:"bullishPercent"`
BearishPercent float64 `json:"bearishPercent"`
NeutralPercent float64 `json:"neutralPercent"`
Scenario string `json:"scenairo"` // Note: API has typo "scenairo"
}
// InsightsResponse from api.msn.com insights
type InsightsResponse []InsightData
// InsightData represents AI-generated stock insights
type InsightData struct {
ID string `json:"id"`
Summary string `json:"summary"`
Highlights []string `json:"highlights"`
Risks []string `json:"risks"`
LastUpdated string `json:"lastUpdated"`
}
// NewsFeedResponse from MSN/Feed/me
type NewsFeedResponse struct {
Value []NewsItem `json:"value"`
SubCards []NewsItem `json:"subCards"`
}
// NewsItem represents a news article
type NewsItem struct {
ID string `json:"id"`
Type string `json:"type"`
Title string `json:"title"`
URL string `json:"url"`
Description string `json:"abstract"`
Provider *NewsProvider `json:"provider"`
PublishTime string `json:"publishedDateTime"`
Images []NewsImage `json:"images"`
ReadTimeMin int `json:"readTimeMin"`
}
// NewsProvider represents a news provider
type NewsProvider struct {
ID string `json:"id"`
Name string `json:"name"`
}
// NewsImage represents a news article image
type NewsImage struct {
URL string `json:"url"`
Width int `json:"width"`
Height int `json:"height"`
}
// Holder represents an institutional holder
type Holder struct {
Name string `json:"investorName"`
Type string `json:"investorType"`
SharesHeld int64 `json:"sharesHeld"`
SharesChange int64 `json:"sharesChange"`
SharesPct float64 `json:"sharesPercent"`
Value float64 `json:"value"`
ReportDate string `json:"reportDate"`
}
// OwnershipResponse from Bing API
type OwnershipResponse struct {
Records []Holder `json:"records"`
SecurityOwnerships []Holder `json:"securityOwnerships"`
Total int `json:"total"`
}
// OwnershipData aggregates all ownership information
type OwnershipData struct {
TopHolders []Holder `json:"top_holders"`
TopBuyers []Holder `json:"top_buyers"`
TopSellers []Holder `json:"top_sellers"`
NewHolders []Holder `json:"new_holders"`
ExitedHolders []Holder `json:"exited_holders"`
}
// StockData is the complete stock information output
type StockData struct {
ID string `json:"id"`
Ticker string `json:"ticker"`
Name string `json:"name"`
Exchange string `json:"exchange"`
Sector string `json:"sector"`
Industry string `json:"industry"`
// Real-time data
Quote *QuoteData `json:"quote,omitempty"`
// Historical Charts
Charts map[string][]ChartPoint `json:"charts,omitempty"`
// Fundamentals
Financials *FinancialData `json:"financials,omitempty"`
KeyRatios *KeyRatios `json:"key_ratios,omitempty"`
// Company Info
Company *EquityData `json:"company,omitempty"`
// Events
Earnings []EarningsEvent `json:"earnings,omitempty"`
// Analysis
Sentiment *SentimentData `json:"sentiment,omitempty"`
Insights *InsightData `json:"insights,omitempty"`
// Ownership (Bing API)
Ownership *OwnershipData `json:"ownership,omitempty"`
// News
News []NewsItem `json:"news,omitempty"`
// Metadata
FetchedAt string `json:"fetched_at"`
FetchStatus map[string]string `json:"fetch_status"`
}
// FinancialData aggregates all financial statements
type FinancialData struct {
Statements []FinancialStatement `json:"statements,omitempty"`
}
// ScreenerOutput is the JSON output for screener command
type ScreenerOutput struct {
Filter string `json:"filter"`
Region string `json:"region"`
GeneratedAt string `json:"generated_at"`
Total int `json:"total"`
Stocks []ScreenerStock `json:"stocks"`
}
// FetchOutput is the JSON output for fetch command
type FetchOutput struct {
GeneratedAt string `json:"generated_at"`
Total int `json:"total"`
Stocks []StockData `json:"stocks"`
}