simfin-1.0.0: src/SimFin/Free.hs
{-|
Module : SimFin.Free
Description : SimFin Free API.
Copyright : (c) Owen Shepherd, 2022
License : MIT
Maintainer : owen@owen.cafe
-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
module SimFin.Free
( SimFinContext(..)
, Industry(..)
, CompanyListingRow(..)
, CompanyInfoRow(..)
, GeneralBalanceSheetRow(..)
, BankBalanceSheetRow(..)
, InsuranceBalanceSheetRow(..)
, GeneralProfitAndLossRow(..)
, BankProfitAndLossRow(..)
, InsuranceProfitAndLossRow(..)
, GeneralCashFlowRow(..)
, BankCashFlowRow(..)
, InsuranceCashFlowRow(..)
, DerivedRow(..)
, PricesRow(..)
, PricesQueryFree
, StatementQueryFree(..)
, StockRef(..)
, FiscalPeriod(..)
, ApiError(..)
, ApiResult
, createDefaultContext
, fetchCompanyList
, fetchCompanyInfo
, fetchBalanceSheet
, fetchProfitAndLoss
, fetchCashFlow
, fetchDerived
, fetchPrices
) where
import Control.Monad.Catch
import Control.Monad.IO.Class
import Data.Functor.Syntax
import Data.Maybe (listToMaybe)
import SimFin.Common
import SimFin.Internal
import SimFin.Types.BalanceSheet
import SimFin.Types.CompanyInfo
import SimFin.Types.CompanyListing
import SimFin.Types.CashFlow
import SimFin.Types.Derived
import SimFin.Types.FiscalPeriod
import SimFin.Types.Industry
import SimFin.Types.Prices
import SimFin.Types.PricesQuery
import SimFin.Types.ProfitAndLoss
import SimFin.Types.StatementQuery
import SimFin.Types.StockRef
import SimFin.Util
------
-- General Company Info
------
-- | Fetch general company information. See the [SimFin docs](https://simfin.com/api/v2/documentation/#tag/Company/paths/~1companies~1general/get).
fetchCompanyInfo
:: (MonadThrow m, MonadIO m)
=> SimFinContext
-> StockRef
-> m (ApiResult (Maybe CompanyInfoRow))
fetchCompanyInfo ctx refs = do
rows :: ApiResult [CompanyInfoRow] <- performRequest ctx "companies/general"
$ stockRefsToQueryParams $ pure refs
pure $ listToMaybe <$> rows
------
-- Balance Sheets
------
-- | Fetch a company's balance sheet statement. As this is the free API version, only one statement
-- is returned. The returned statement's data is dependent on the company type.
-- See the [SimFin docs](https://simfin.com/api/v2/documentation/#tag/Company/paths/~1companies~1statements/get).
fetchBalanceSheet
:: (MonadThrow m, MonadIO m)
=> SimFinContext
-> StatementQueryFree
-> m (ApiResult (Maybe IndustryBalanceSheet))
fetchBalanceSheet ctx query = do
nested :: ApiResult [IndustryBalanceSheets] <- performRequest ctx "companies/statements"
$ ("statement", Just "bs") : statementQueryFreeToQueryParams query
pure $ listToMaybe . invertIndustries <$> nested
------
-- P&L
------
-- | Fetch a company's profit and loss statement. As this is the free API version, only one statement
-- is returned. The returned statement's data is dependent on the company type.
-- See the [SimFin docs](https://simfin.com/api/v2/documentation/#tag/Company/paths/~1companies~1statements/get).
fetchProfitAndLoss
:: (MonadThrow m, MonadIO m)
=> SimFinContext
-> StatementQueryFree
-> m (ApiResult (Maybe IndustryProfitAndLoss))
fetchProfitAndLoss ctx query = do
nested :: ApiResult [IndustryProfitsAndLosses] <- performRequest ctx "companies/statements"
$ ("statement", Just "pl") : statementQueryFreeToQueryParams query
pure $ listToMaybe . invertIndustries <$> nested
-----
-- Cash Flows
------
-- | Fetch a company's cash flow statement. As this is the free API version, only one statement
-- is returned. The returned statement's data is dependent on the company type.
-- See the [SimFin docs](https://simfin.com/api/v2/documentation/#tag/Company/paths/~1companies~1statements/get).
fetchCashFlow
:: (MonadThrow m, MonadIO m)
=> SimFinContext
-> StatementQueryFree
-> m (ApiResult (Maybe IndustryCashFlow))
fetchCashFlow ctx query = do
nested :: ApiResult [IndustryCashFlows] <- performRequest ctx "companies/statements"
$ ("statement", Just "cf") : statementQueryFreeToQueryParams query
pure $ listToMaybe . invertIndustries <$> nested
------
-- Derived
------
-- | Fetch a company's derived figures. As this is the free API version, only one set
-- of data is returned.
-- See the [SimFin docs](https://simfin.com/api/v2/documentation/#tag/Company/paths/~1companies~1statements/get).
fetchDerived
:: forall m a. (Read a, RealFrac a, MonadThrow m, MonadIO m)
=> SimFinContext
-> StatementQueryFree
-> m (ApiResult (Maybe (DerivedRow a)))
fetchDerived ctx query = do
nested :: ApiResult [DerivedRowsKeyed a] <- performRequest ctx "companies/statements"
(("statement", Just "derived") : statementQueryFreeToQueryParams query)
pure $ listToMaybe . mconcat . fmap unDerivedRows <$> nested
------
-- Prices
------
-- | Fetch a company's historical share prices. See the [SimFin docs](https://simfin.com/api/v2/documentation/#tag/Company/paths/~1companies~1prices/get).
fetchPrices
:: (Read a, RealFrac a, MonadThrow m, MonadIO m)
=> SimFinContext
-> PricesQueryFree
-> m (ApiResult [PricesRow a])
fetchPrices ctx query =
mconcat . fmap unKeyPrices <$$> performRequest ctx "companies/prices"
(pricesQueryFreeToQueryParams query)