Package: pstock-python
PstockDisclaimerYou should refer to Yahoo!'s terms of use(here,here, andhere)for
details on your rights to use the actual data downloaded. Remember - the
project is intended for personal use only.Pstockis an open source tool/project that is not affiliated in any way to yahoo-finance. Nothing in this project should be considered investment advice.Documentation:https://obendidi.github.io/pstockSource Code:https://github.com/obendidi/pstockPstockDisclaimerRequirementsInstallationQuickstartUser GuideAssetsTrendsEarningsIncome StatementNewsBars (Historical price data)BarsMultiSans-I/O protocolContributorsPstockisyetanother python unoficial API for getting yahoo-finance data.The key features are:Async firstData validation using pydanticFully typed, with great editor supportEasily extensible: Parse the yahoo-finance quote dict and extract any type of info you want.Follows the Sans-IO design pattern: Use your favourite http library (sync/async) and letpstockparse your response to getAssetsorBarsRequirementsPython 3.8+ (support for 3.6/3.7 may be added later, contributions are welcome)Pstock depends mainly on:pydantic: For data validationpandas: For structuring data in nice dataframeshttpx: For the main async IO interfaceInstallation$pipinstallpstock-python---> 100%QuickstartDownload an asset:importasynciofrompstockimportAssetasset=asyncio.run(Asset.get("TSLA"))print(asset)# symbol='TSLA' name='Tesla, Inc.' asset_type='EQUITY' currency='USD' latest_price=920.0 sector='Consumer Cyclical' industry='Auto Manufacturers'Download a list of assets:importasynciofrompstockimportAssetassets=asyncio.run(Assets.get(["TSLA","AAPL","GME"]))print(assets)# __root__=[Asset(symbol='TSLA', name='Tesla, Inc.', asset_type='EQUITY', currency='USD', latest_price=918.97, sector='Consumer Cyclical', industry='Auto Manufacturers'), Asset(symbol='AAPL', name='Apple Inc.', asset_type='EQUITY', currency='USD', latest_price=172.345, sector='Technology', industry='Consumer Electronics'), Asset(symbol='GME', name='GameStop Corp.', asset_type='EQUITY', currency='USD', latest_price=125.0, sector='Consumer Cyclical', industry='Specialty Retail')]print(assets[0])# Asset(symbol='TSLA', name='Tesla, Inc.', asset_type='EQUITY', currency='USD', latest_price=918.97, sector='Consumer Cyclical', industry='Auto Manufacturers')print(assets.df)nameasset_typecurrency...earningstrendsincome_statementsymbol...AAPLAppleInc.EQUITYUSD...[{'quarter':'1Q2021','estimate':0.99,'actu...  [{'date': 2021-11-17, 'strong_buy': 13, 'buy':...  [{'date': 2021-09-25, 'ebit': 108949000000.0, ...GMEGameStopCorp.EQUITYUSD...[{'quarter':'1Q2021','estimate':1.35,'actu...  [{'date': 2021-11-17, 'strong_buy': 2, 'buy': ...  [{'date': 2021-01-30, 'ebit': -249300000.0, 't...TSLATesla,Inc.EQUITYUSD...[{'quarter':'1Q2021','estimate':0.79,'actu...  [{'date': 2021-11-17, 'strong_buy': 4, 'buy': ...  [{'date': 2021-12-31, 'ebit': 6523000000.0, 't...Download historical bars:importasynciofrompstockimportBarsbars=asyncio.run(Bars.get("TSLA"))print(bars)# __root__=[Bar(date=datetime.datetime(2010, 7, 1, 4, 0, tzinfo=datetime.timezone.utc), open=5.0, high=5.184000015258789, low=2.996000051498413, close=3.98799991607666, adj_close=3.98799991607666, volume=322879000.0, interval=Duration(months=1)), Bar(date=datetime.datetime(2010, 8, 1, 4, 0, tzinfo=datetime.timezone.utc), open=4.099999904632568, high=4.435999870300293, low=3.4779999256134033, close=3.8959999084472656, adj_close=3.8959999084472656, volume=75191000.0, interval=Duration(months=1)), Bar(date=datetime.datetime(2010, 9, 1, 4, 0, tzinfo=datetime.timezone.utc), open=3.9240000247955322, high=4.631999969482422, low=3.9000000953674316, close=4.081999778747559, adj_close=4.081999778747559, volume=90229500.0, interval=Duration(months=1)), Bar(date=datetime.datetime(2010, 10, 1, 4, 0, tzinfo=datetime.timezone.utc), open=4.138000011444092, high=4.374000072479248, low=4.0, close=4.368000030517578, adj_close=4.368000030517578, volume=32739000.0, interval=Duration(months=1)), ....]print(bars.df)openhighlowcloseadj_closevolumeintervaldate2010-07-015.0000005.1840002.9960003.9880003.988000322879000.030days2010-08-014.1000004.4360003.4780003.8960003.89600075191000.030days2010-09-013.9240004.6320003.9000004.0820004.08200090229500.030days2010-10-014.1380004.3740004.0000004.3680004.36800032739000.030days2010-11-014.3880007.2000004.2100007.0660007.066000141575500.030days........................2021-11-011145.0000001243.489990978.5999761144.7600101144.760010648671800.030days2021-12-011160.6999511172.839966886.1199951056.7800291056.780029509945100.030days2022-01-011147.7500001208.000000792.010010936.719971936.719971638471400.030days2022-02-01935.210022947.770020850.700012875.760010875.760010223112600.030days2022-02-15900.000000923.000000893.377380922.429993922.42999319085243.030days[141rowsx7columns]Download stock news:importasynciofrompstockimportNewsnews=asyncio.run(News.get("TSLA"))print(news.df)titleurlsummarydate2022-02-1512:11:46+00:00Retailinvestor:'I'mbeingcarefuljustinca...https://finance.yahoo.com/news/retail-investor...Someretailinvestorsarebeingmorecautious...2022-02-1512:23:00+00:00Tesla’sElonMuskGaveAway$5.7Billion.But...https://finance.yahoo.com/m/d342cd56-d5bb-3957...TeslaCEOElonMuskgaveawaymorethan5mill...2022-02-1513:07:02+00:00CompanyNewsforFeb15,2022https://finance.yahoo.com/news/company-news-fe...CompaniesInTheNewsAre:IFS,OLK,THS,TSLA.....2022-02-1519:23:43+00:00Australia's Syrah Resources to expand Louisian...  https://finance.yahoo.com/news/australias-syra...  Australian industrial materials firm Syrah Res...2022-02-1520:31:30+00:00BiggestCompaniesintheWorldbyMarketCaphttps://finance.yahoo.com/m/8aead0a5-ef35-3d90...Theworld's biggest companies by market cap op...User GuideAssetsAnAssetinpstockterms is any ticker symbol supported by yahoo-finance. If the asset exists in yahoo-finance, you should be able to get it's quote summary  usingpstock.importasynciofrompstockimportAssetasset=asyncio.run(Asset.get("TSLA"))print(asset)# symbol='TSLA' name='Tesla, Inc.' asset_type='EQUITY' currency='USD' latest_price=920.0 sector='Consumer Cyclical' industry='Auto Manufacturers'AnAssetwill always have a:symbol: The ticker symbol of the assetname: The long/short name of the asset (depending on which is found, the long name takes priority)asset_type: Type of the asset, can be one of:EQUITY,CURRENCY,CRYPTOCURRENCY,ETF,FUTURE,INDEXcurrency: Currency of the asset,USDfor US stockslatest_price: Latest price of the asset known by yahoo-finance, takes into account the pre-post market prices. Can benumpy.nanif no proce data is found.Note: if anasset_typeexists in yahoo-finance but is not one of the above, feel free to open an issue or PR. In the meantime you can subclass theAssetobject and override the type ofasset_typeand add the missing asset typeThe other fields are optional and can be filled depending on theasset_type, currently there are only fields for theEQUITY(stocks) asset_type:sectorindustrytrendsearningsincome_statementIn addition to getting data about a singleAsset, there is also the possibily to query multiple assets at the same time usingAssets. The main benefit is that it provides the ability to directly convert the resulting list of assets into a pandas dataframe.importasynciofrompstockimportAssetassets=asyncio.run(Assets.get(["TSLA","AAPL","GME"]))print(assets.df)nameasset_typecurrency...earningstrendsincome_statementsymbol...AAPLAppleInc.EQUITYUSD...[{'quarter':'1Q2021','estimate':0.99,'actu...  [{'date': 2021-11-17, 'strong_buy': 13, 'buy':...  [{'date': 2021-09-25, 'ebit': 108949000000.0, ...GMEGameStopCorp.EQUITYUSD...[{'quarter':'1Q2021','estimate':1.35,'actu...  [{'date': 2021-11-17, 'strong_buy': 2, 'buy': ...  [{'date': 2021-01-30, 'ebit': -249300000.0, 't...TSLATesla,Inc.EQUITYUSD...[{'quarter':'1Q2021','estimate':0.79,'actu...  [{'date': 2021-11-17, 'strong_buy': 4, 'buy': ...  [{'date': 2021-12-31, 'ebit': 6523000000.0, 't...Note 1:Assetsis also a pydantic model that will validate data that it pulls from yahoo-finance.Note 2: The generated pandas Dataframe is cached into a private._dfattribute and is computed only the first time it is accessed via the property.df.Note 3: Most if not all data objects inpstockhave a.dfproperty, and it's the recommended way to view and manipulate data when possible.Note 4:Assets,Bars,Earnings,News, ... can also be iterated over and support indexing and behave like atyping.List[Asset],typing.List[Bar], ...TrendsThere are 2 ways to get the trends of a symbol.viaAsset:importasynciofrompstockimportAssetasset=asyncio.run(Asset.get("TSLA"))print(asset.trends.df)strong_buybuyholdsellstrong_sellscorerecomendationdate2021-11-17448602.73HOLD2021-12-1711613602.39BUY2022-01-1611613602.39BUY2022-02-15448602.73HOLDDirectly viaTrendsimportasynciofrompstockimportTrendstrends=asyncio.run(Trends.get("TSLA"))print(trends.df)strong_buybuyholdsellstrong_sellscorerecomendationdate2021-11-17448602.73HOLD2021-12-1711613602.39BUY2022-01-1611613602.39BUY2022-02-15448602.73HOLDEarningsThere are 2 ways to get the earnings of a symbol.viaAsset:importasynciofrompstockimportAssetasset=asyncio.run(Asset.get("TSLA"))print(asset.earnings.df)estimateactualstatusrevenueearningsquarter1Q20210.790.93Beat1.038900e+104.380000e+082Q20210.981.45Beat1.195800e+101.142000e+093Q20211.591.86Beat1.375700e+101.618000e+094Q20212.372.54Beat1.771900e+102.321000e+091Q20222.25NaNNoneNaNNaNDirectly viaEarningsimportasynciofrompstockimportEarningsearnings=asyncio.run(Earnings.get("TSLA"))print(earnings.df)estimateactualstatusrevenueearningsquarter1Q20210.790.93Beat1.038900e+104.380000e+082Q20210.981.45Beat1.195800e+101.142000e+093Q20211.591.86Beat1.375700e+101.618000e+094Q20212.372.54Beat1.771900e+102.321000e+091Q20222.25NaNNoneNaNNaNNote: The last earning haveNaN/Nonevalues since we only have analysts estimates and revenue isn't reported yet. The specific earnings call date can be extracted from theQuoteSummary.Income StatementThere are 2 ways to get the income statement of a symbol.Note: The current extracted statement is very limited/minimaliste, contributions are welcome to extract more data from theQuoteSummary.viaAsset:importasynciofrompstockimportAssetasset=asyncio.run(Asset.get("TSLA"))print(asset.income_statement.df)ebittotal_revenuegross_profitdate2018-12-31-2.530000e+082.146100e+104.042000e+092019-12-318.000000e+072.457800e+104.069000e+092020-12-311.951000e+093.153600e+106.630000e+092021-12-316.523000e+095.382300e+101.360600e+10Note:asset.income_statementcan beNonefor all assets that are not of typeEQUITY.Directly viaIncomeStatementsimportasynciofrompstockimportIncomeStatementsincome_statement=asyncio.run(IncomeStatements.get("TSLA"))print(income_statement.df)ebittotal_revenuegross_profitdate2018-12-31-2.530000e+082.146100e+104.042000e+092019-12-318.000000e+072.457800e+104.069000e+092020-12-311.951000e+093.153600e+106.630000e+092021-12-316.523000e+095.382300e+101.360600e+10Note: You can also useQuarterlyIncomeStatementsfor (as the name says) quarterly income stamenets.NewsGettings yahoo-finance news about a symbol also follows the same pattern.importasynciofrompstockimportNewsnews=asyncio.run(News.get("TSLA"))print(news.df)titleurlsummarydate2022-02-1512:11:46+00:00Retailinvestor:'I'mbeingcarefuljustinca...https://finance.yahoo.com/news/retail-investor...Someretailinvestorsarebeingmorecautious...2022-02-1512:23:00+00:00Tesla’sElonMuskGaveAway$5.7Billion.But...https://finance.yahoo.com/m/d342cd56-d5bb-3957...TeslaCEOElonMuskgaveawaymorethan5mill...2022-02-1513:07:02+00:00CompanyNewsforFeb15,2022https://finance.yahoo.com/news/company-news-fe...CompaniesInTheNewsAre:IFS,OLK,THS,TSLA.....2022-02-1519:23:43+00:00Australia's Syrah Resources to expand Louisian...  https://finance.yahoo.com/news/australias-syra...  Australian industrial materials firm Syrah Res...2022-02-1520:31:30+00:00BiggestCompaniesintheWorldbyMarketCaphttps://finance.yahoo.com/m/8aead0a5-ef35-3d90...Theworld's biggest companies by market cap op...Bars (Historical price data)ABarinpstockis a pydantic model with the following fields:classBar(BaseModel):date:datetimeopen:floathigh:floatlow:floatclose:floatadj_close:floatvolume:floatinterval:timedeltaNote: Theintervalis the time between baropenandclose.To getBarsthere are a couple of arguments that can be specified:interval: one of1m,2m,5m,15m,30m,1h,1d,5d,1mo,3mo, defaults toNoneperiod: one of1d,5d,1mo,3mo,6mo,1y,2y,5y,10y,ytd,max, defaults toNonestart: Anydate/datetimesupported by pydnatic, defaults toNoneend: Anydate/datetimesupported by pydnatic, defaults toNoneevents: one ofdiv,split,div,splits, defaults todiv,splitsinclude_prepost: Bool, include Pre and Post market bars, default toFalseBy default, if no argument is provided, theperiodis set tomaxand the interval to3mo, example:Note: It is possible for yahoo-finance to return bars of different interval than what was specified in the request (example below, requested3mointerval bars, got an interval of1mobecauseTSLAis a relatively new stock and it's max period is around ~10 years by the time of writing).importasynciofrompstockimportBarsbars=asyncio.run(Bars.get("TSLA"))print(bars.df)openhighlowcloseadj_closevolumeintervaldate2010-07-015.0000005.1840002.9960003.9880003.988000322879000.030days2010-08-014.1000004.4360003.4780003.8960003.89600075191000.030days2010-09-013.9240004.6320003.9000004.0820004.08200090229500.030days2010-10-014.1380004.3740004.0000004.3680004.36800032739000.030days2010-11-014.3880007.2000004.2100007.0660007.066000141575500.030days........................2021-11-011145.0000001243.489990978.5999761144.7600101144.760010648671800.030days2021-12-011160.6999511172.839966886.1199951056.7800291056.780029509945100.030days2022-01-011147.7500001208.000000792.010010936.719971936.719971638471400.030days2022-02-01935.210022947.770020850.700012875.760010875.760010223112600.030days2022-02-15900.000000923.000000893.377380922.429993922.42999319085243.030days[141rowsx7columns]Note 1: Yahoo-finance limits theintervalof data we can fetch based on how old the data is. For example we can't get1mbars for a period (or start/end) older than 7 days.Example of an interval error ...importasynciofrompstockimportBarsbars=asyncio.run(Bars.get("TSLA",period="1mo",interval="1m"))print(bars.df)Traceback(mostrecentcalllast):File"pstock/bar.py",line243,in<module>bars=asyncio.run(Bars.get("TSLA",period="1mo",interval="1m"))File"user/.pyenv/versions/3.8.12/lib/python3.8/asyncio/runners.py",line44,inrunreturnloop.run_until_complete(main)File"user/.pyenv/versions/3.8.12/lib/python3.8/asyncio/base_events.py",line616,inrun_until_completereturnfuture.result()File"pstock/bar.py",line196,ingetreturncls.load(response=response)File"pstock/bar.py",line169,inloadreturncls.parse_obj(get_ohlc_from_chart(data))File"user/git/pstock/pstock/utils/chart.py",line18,inget_ohlc_from_chartraiseValueError(f"Yahoo-finance responded with an error:\n{error}")ValueError:Yahoo-financerespondedwithanerror:{'code':'Unprocessable Entity','description':'1m data not available for startTime=1642289894 and endTime=1644968294. Only 7 days worth of 1m granularity data are allowed to be fetched per request.'}Note2By leaving theintervalparameter empty (=None),pstockautomatically tries to find the lowestintervalpossible based on how old the data requested is.importasynciofrompstockimportBarsbars=asyncio.run(Bars.get("TSLA",period="1mo"))print(bars.df)# Automatically finds that the lowest interval for a period of `1mo` is `2m`openhighlowcloseadj_closevolumeintervaldate2022-01-1814:30:00+00:001028.0000001030.0000001023.0000001023.9835821023.9835821125597.00days00:02:002022-01-1814:32:00+00:001023.2301031032.0000001023.2301031029.8079831029.807983228889.00days00:02:002022-01-1814:34:00+00:001029.9499511029.9499511023.7000121025.0000001025.000000248188.00days00:02:002022-01-1814:36:00+00:001024.3199461025.9998781018.0000001021.0000001021.000000289773.00days00:02:002022-01-1814:38:00+00:001021.6699221024.0000001018.4400021020.1500241020.150024183713.00days00:02:00........................2022-02-1520:52:00+00:00919.640015920.989990919.171570919.179993919.179993189152.00days00:02:002022-02-1520:54:00+00:00919.320007920.770020918.869995920.075012920.075012178398.00days00:02:002022-02-1520:56:00+00:00920.010010921.000000919.859985920.940002920.940002207078.00days00:02:002022-02-1520:58:00+00:00920.900024923.000000920.750000922.260010922.260010382232.00days00:02:002022-02-1521:00:00+00:00922.429993922.429993922.429993922.429993922.4299930.00days00:02:00[4093rowsx7columns]Note3Instead of usingperiodit is also possible to set a specificstartand optioallyendvalue. Ifendis not set, it defaults to current UTC time.BarsMultiSometimes we'll want to get bars for multiple symbols at the same time.importasynciofrompstockimportBarsMultibars=asyncio.run(BarsMulti.get(["TSLA","AAPL"],period="5d",interval="1d"))print(bars.df)TSLAAAPLopenhighlowcloseadj_closevolumeintervalopenhighlowcloseadj_closevolumeintervaldate2022-02-09935.000000946.270020920.000000932.000000932.00000017419800.01days176.050003176.649994174.899994176.279999176.27999971285000.01days2022-02-10908.369995943.809998896.700012904.549988904.54998822042300.01days174.139999175.479996171.550003172.119995172.11999590865900.01days2022-02-11909.630005915.960022850.700012860.000000860.00000026492700.01days172.330002173.080002168.039993168.639999168.63999998566000.01days2022-02-14861.570007898.880005853.150024875.760010875.76001022515100.01days167.369995169.580002166.559998168.880005168.88000586062800.01days2022-02-15900.000000923.000000893.377380922.429993922.42999319085243.01days170.970001172.949997170.250000172.789993172.78999362512704.01daysNoteBars of a specific symbol can be accessed by using the sumbol as key:bars["TSLA"].df == bars.df["TSLA"] == Bars.get("TSLA").dfSans-I/O protocolAn I/O-free protocol implementation (colloquially referred to as a “sans-IO” implementation) is an implementation of a network protocol that contains no code that does any form of network I/O or any form of asynchronous flow control. Put another way, a sans-IO protocol implementation is one that is defined entirely in terms of synchronous functions returning synchronous results, and that does not block or wait for any form of I/O.
............
By keeping async flow control and I/O out of your protocol implementation, it provides the ability to use that implementation across all forms of flow control. This means that the core of the protocol implementation is divorced entirely from the way I/O is done or the way the API is designed.->https://sans-io.readthedocs.ioAlthoughpstockprovides an async IO interface to get data from yahoo-finance, It is still extremly easy to use it with other http libraries or other ways to get data.A simple example is using the popularrequestslibrary:importrequestsfrompstockimportAsset,rdm_user_agent_valueurl=Asset.uri("TSLA")headers={"User-Agent":rdm_user_agent_value()}response=requests.get(url,headers=headers)asset=Asset.load(response=response)Theresponseobject can be anstrorbytescontent of the response. Or it can even be the whole response object (should have a.read()method that returns content).The same can be done for generatingBarsimportrequestsfrompstockimportBars,rdm_user_agent_valueurl=Bars.uri("TSLA",interval="1m",period="1d")headers={"User-Agent":rdm_user_agent_value()}response=requests.get(url,headers=headers)bars=Bars.load(response=response)ContributorsFeel free to contribute !