Package: artesian-sdk
Artesian.SDKThis Library provides read access to the Artesian APIGetting StartedInstallationYou can install the package directly frompip.pipinstallartesian-sdkAlternatively, to install this package go to therelease page.How to useThe Artesian.SDK instance can be configured using API-Key authenticationfromArtesianimportArtesianConfigcfg=ArtesianConfig("https://arkive.artesian.cloud/{tenantName}/","{api-key}")BREAKING CHANGES: Upgrade v2->v3The following breaking changes has been introduced in v3 respect to v2.Python Version >=3.8Python >=3.8 isrequired.
Python 3.7 is not supported due missing 'typing' features.SubPackagingWith Artesian-SDK v3 we introduced SubPkg to split the different part of the library. The new SubPkg are:Artesian.Query: contains all classes for querying Artesian data.Artesian.GMEPublicOffers: contains all classes for querying GME Public Offers(NEW)Artesian.MarketData: contains all classes to interact with the MarketData registry of Artesian. Register a new MarketData, change its Tags, etc. See documentation below.To upgrade is enough to prefix the QueryService with 'Query.' or import it from Artesian.Query.Were was used:fromArtesianimport*cfg=ArtesianConfig("https://arkive.artesian.cloud/{tenantName}/","{api-key}")qs=QueryService(cfg)now you have to:fromArtesianimportArtesianConfigfromArtesian.QueryimportQueryServicecfg=ArtesianConfig("https://arkive.artesian.cloud/{tenantName}/","{api-key}")qs=QueryService(cfg)Enum entries CasingTo align the casing of the entries of the Enum, we adopted PascalCase to align it with the Artesian API.Where before was used.inGranularity(Granularity.HOUR)\now is.inGranularity(Granularity.Hour)\MarketData QueryServiceUsing the ArtesianConfigcfgwe create an instance of the QueryService which is used to create Actual, Versioned and Market Assessment time series queriesActual Time Series ExtractionfromArtesianimportArtesianConfig,GranularityfromArtesian.QueryimportQueryService,RelativeIntervalcfg=ArtesianConfig("https://arkive.artesian.cloud/{tenantName}/","{api-key}")qs=QueryService(cfg)data=qs.createActual()\.forMarketData([100011484,100011472,100011477,100011490,100011468,100011462,100011453])\.inAbsoluteDateRange("2018-01-01","2018-01-02")\.inTimeZone("UTC")\.inGranularity(Granularity.Hour)\.execute()print(data)To construct an Actual Time Series Extraction the following must be provided.Actual QueryDescriptionMarket Data IDProvide a market data id or set of market data id's to queryTime GranularitySpecify the granularity typeTime Extraction WindowAn extraction time window for data to be queriedGo to Time Extraction window sectionVersioned Time Series ExtractionfromArtesianimportArtesianConfig,GranularityfromArtesian.QueryimportQueryService,RelativeIntervalqs=QueryService(cfg)q=qs.createVersioned()\.forMarketData([100042422,100042283,100042285,100042281,100042287,100042291,100042289])\.inAbsoluteDateRange("2018-01-01","2018-01-02")\.inTimeZone("UTC")\.inGranularity(Granularity.Hour)print(q)ret=q.forMUV().execute()print(ret)ret=q.forLastNVersions(2).execute()print(ret)ret=q.forLastOfDays("2019-03-12","2019-03-16").execute()print(ret)ret=q.forLastOfDays("P0Y0M-2D","P0Y0M2D").execute()print(ret)ret=q.forLastOfDays("P0Y0M-2D").execute()print(ret)ret=q.forLastOfMonths("2019-03-12","2019-03-16").execute()print(ret)ret=q.forLastOfMonths("P0Y-1M0D","P0Y1M0D").execute()print(ret)ret=q.forLastOfMonths("P0Y-1M0D").execute()print(ret)ret=q.forVersion("2019-03-12T14:30:00").execute()print(ret)ret=q.forMostRecent("2019-03-12","2019-03-16").execute()print(ret)ret=q.forMostRecent("2019-03-12T12:30:05","2019-03-16T18:42:30").execute()print(ret)ret=q.forMostRecent("P0Y0M-2D","P0Y0M2D").execute()print(ret)ret=q.forMostRecent("P0Y0M-2D").execute()print(ret)ret=q.forMostRecent("2019-03-12","2019-03-16").execute()print(ret)ret=q.forMostRecent("P0Y-1M0D","P0Y1M0D").execute()print(ret)ret=q.forMostRecent("P0Y-1M0D").execute()print(ret)To construct a Versioned Time Series Extraction the following must be provided.Versioned QueryDescriptionMarket Data IDProvide a market data id or set of market data id's to queryTime GranularitySpecify the granularity typeVersioned Time Extraction WindowVersioned extraction time windowTime Extraction WindowAn extraction time window for data to be queriedGo to Time Extraction window sectionMarket Assessment Time Series ExtractionfromArtesianimportArtesianConfigfromArtesian.QueryimportQueryService,RelativeIntervalqs=QueryService(cfg)data=qs.createMarketAssessment()\.forMarketData([100000032,100000043])\.forProducts(["D+1","Feb-18"])\.inAbsoluteDateRange("2018-01-01","2018-01-02")\.execute()print(data)To construct a Market Assessment Time Series Extraction the following must be provided.Mas QueryDescriptionMarket Data IDProvide a market data id or set of market data id's to queryProductProvide a product or set of productsTime Extraction WindowAn extraction time window for data to be queriedGo to Time Extraction window sectionBid Ask Time Series ExtractionfromArtesianimportArtesianConfigfromArtesian.QueryimportQueryService,RelativeIntervalqs=QueryService(cfg)data=qs.createBidAsk()\.forMarketData([100000032,100000043])\.forProducts(["D+1","Feb-18"])\.inAbsoluteDateRange("2018-01-01","2018-01-02")\.execute()print(data)To construct a Bid Ask Time Series Extraction the following must be provided.Mas QueryDescriptionMarket Data IDProvide a market data id or set of market data id's to queryProductProvide a product or set of productsTime Extraction WindowAn extraction time window for data to be queriedGo to Time Extraction window sectionAuction Time Series ExtractionfromArtesianimportArtesianConfigfromArtesian.QueryimportQueryService,RelativeIntervalqs=QueryService(cfg)data=qs.createAuction()\.forMarketData([100011484,100011472,100011477,100011490,100011468,100011462,100011453])\.inAbsoluteDateRange("2018-01-01","2018-01-02")\.inTimeZone("UTC")\.execute()print(data)To construct an Auction Time Series Extraction the following must be provided.Auction QueryDescriptionMarket Data IDProvide a market data id or set of market data id's to queryTime Extraction WindowAn extraction time window for data to be queriedGo to Time Extraction window sectionExtraction WindowsExtraction window types for queries.Date Range.inAbsoluteDateRange("2018-08-01","2018-08-10")Relative Interval.inRelativeInterval(RelativeInterval.RollingWeek)Period.inRelativePeriod("P5D")Period Range.inRelativePeriodRange("P-3D","P10D")Filler StrategyAll extraction types (Actual,Versioned, Market Assessment and BidAsk) have an optional filler strategy.varversionedSeries=qs.createVersioned()\.forMarketData([100000001])\.forLastNVersions(1)\.inGranularity(Granularity.Day)\.inAbsoluteDateRange(newDate("2018-1-1"),newDate("2018-1-10"))\.withFillLatestValue("P5D")\.execute()Use 'Null' to fill the missing timepoint with 'None' values..withFillNull()Use 'None' to not fill at all: timepoints are not returned if not present..withFillNone()Custom Value can be provided for each MarketDataType.Custom Value for Actual extraction type..withFillCustomValue(123)Custom Value for BidAsk extraction type..withFillCustomValue(bestBidPrice=15.0,bestAskPrice=20.0,bestBidQuantity=30.0,bestAskQuantity=40.0,lastPrice=50.0,lastQuantity=60.0)Custom Value for Market Assessment extraction type..withFillCustomValue(settlement=10.0,open=20.0,close=30.0,high=40.0,low=50.0,volumePaid=60.0,volueGiven=70.0,volume=80.0)Custom Value for Versioned extraction type..withFillCustomValue(123)Latest Value to propagate the latest value, not older than a certain threshold only if there is a value at the end of the period..withFillLatestValue("P5D").withFillLatestValue("P5D","False")Latest Value to propagate the latest value, not older than a certain threshold even if there's no value at the end..withFillLatestValue("P5D","True")GME Public OfferArtesian support Query over GME Public Offers which comes in a custom and dedicated format.Extract GME Public OfferfromArtesian.GMEPublicOffersimportGMEPublicOfferService,Market,Purpose,Status,Zone,Scope,UnitType,GenerationType,BATypeqs=GMEPublicOfferService(cfg)data=qs.createQuery()\.forDate("2020-04-01")\.forMarket([Market.MGP])\.forStatus(Status.ACC)\.forPurpose(Purpose.BID)\.forZone([Zone.NORD])\.withPagination(1,100)\.execute()print(data)To construct a GME Public Offer Extraction the following must be provided.GME Public Offer QueryDescriptionTime Extraction WindowAn extraction time window for data to be queriedMarketProvide a market or set of markets to queryStatusProvide a status or set of statuses to queryPurposeProvide a purpose or set of purposes to queryZoneProvide a zone to queryExtraction OptionsExtraction options for GME Public Offer queries.Date.forDate("2020-04-01")Purpose.forPurpose(Purpose.BID)Status.forStatus(Status.ACC)Operator.forOperator(["Operator_1","Operator_2"])Unit.forUnit(["UP_1","UP_2"])Market.forMarket([Market.MGP])Scope.forScope([Scope.ACC,Scope.RS])BAType.forBAType([BAType.NETT,BAType.NERV])Zone.forZone([Zone.NORD])UnitType.forUnitType([UnitType.UCV,UnitType.UPV])Generation Type.forGenerationType(GenerationType.GAS)Pagination.withPagination(1,10)Write Data in ArtesianUsing the MarketDataService is possible to register MarketData and write curves into it using the UpsertData method.Depending on the Type of the MarketData, the UpsertData should be composed as per example below.Write Data in an Actual Time SeriesfromArtesianimportArtesianConfig,Granularity,MarketDatafromArtesian.MarketDataimportAggregationRulefromdatetimeimportdatetimefromdateutilimporttzcfg=ArtesianConfg()mkservice=MarketData.MarketDataService(cfg)mkdid=MarketData.MarketDataIdentifier('PROVIDER','MARKETDATANAME')mkd=MarketData.MarketDataEntityInput(providerName=mkdid.provider,marketDataName=mkdid.name,originalGranularity=Granularity.Day,type=MarketData.MarketDataType.ActualTimeSerie,originalTimezone="CET",aggregationRule=AggregationRule.AverageAndReplicate,tags={'TestSDKPython':['PythonValue2']})registered=mkservice.readMarketDataRegistryByName(mkdid.provider,mkdid.name)if(registeredisNone):registered=mkservice.registerMarketData(mkd)data=MarketData.UpsertData(mkdid,'CET',rows={datetime(2020,1,1):42.0,datetime(2020,1,2):43.0,},downloadedAt=datetime(2020,1,3).replace(tzinfo=tz.UTC))mkservice.upsertData(data)In case we want to write an hourly (or lower) time series the timezone for the upsert data must be UTC:mkservice=MarketData.MarketDataService(cfg)mkdid=MarketData.MarketDataIdentifier('PROVIDER','MARKETDATANAME')mkd=MarketData.MarketDataEntityInput(providerName=mkdid.provider,marketDataName=mkdid.name,originalGranularity=Granularity.Hour,type=MarketData.MarketDataType.ActualTimeSerie,originalTimezone="CET",aggregationRule=AggregationRule.AverageAndReplicate,tags={'TestSDKPython':['PythonValue2']})registered=mkservice.readMarketDataRegistryByName(mkdid.provider,mkdid.name)if(registeredisNone):registered=mkservice.registerMarketData(mkd)data=MarketData.UpsertData(mkdid,'UTC',rows={datetime(2020,1,1,5,0,0):42.0,datetime(2020,1,2,6,0,0):43.0,datetime(2020,1,2,7,0,0):44.0,datetime(2020,1,2,8,0,0):45.0,datetime(2020,1,2,9,0,0):46.0,},downloadedAt=datetime(2020,1,3).replace(tzinfo=tz.UTC))mkservice.upsertData(data)Write Data in a Versioned Time SeriesfromArtesianimportArtesianConfig,Granularity,MarketDatafromArtesian.MarketDataimportAggregationRulefromdatetimeimportdatetimefromdateutilimporttzcfg=ArtesianConfg()mkservice=MarketData.MarketDataService(cfg)mkdid=MarketData.MarketDataIdentifier('PROVIDER','MARKETDATANAME')mkd=MarketData.MarketDataEntityInput(providerName=mkdid.provider,marketDataName=mkdid.name,originalGranularity=Granularity.Day,type=MarketData.MarketDataType.VersionedTimeSerie,originalTimezone="CET",aggregationRule=AggregationRule.AverageAndReplicate,tags={'TestSDKPython':['PythonValue2']})registered=mkservice.readMarketDataRegistryByName(mkdid.provider,mkdid.name)if(registeredisNone):registered=mkservice.registerMarketData(mkd)data=MarketData.UpsertData(mkdid,'CET',rows={datetime(2020,1,1):42.0,datetime(2020,1,2):43.0,},version=datetime(2020,1,3,12,0),downloadedAt=datetime(2020,1,3).replace(tzinfo=tz.UTC))mkservice.upsertData(data)Write Data in a Market Assessment Time SeriesfromArtesianimportArtesianConfig,Granularity,MarketDatafromdatetimeimportdatetimefromdateutilimporttzcfg=ArtesianConfg()mkservice=MarketData.MarketDataService(cfg)mkdid=MarketData.MarketDataIdentifier('PROVIDER','MARKETDATANAME')mkd=MarketData.MarketDataEntityInput(providerName=mkdid.provider,marketDataName=mkdid.name,originalGranularity=Granularity.Day,type=MarketData.MarketDataType.MarketAssessment,originalTimezone="CET",tags={'TestSDKPython':['PythonValue2']})registered=mkservice.readMarketDataRegistryByName(mkdid.provider,mkdid.name)if(registeredisNone):registered=mkservice.registerMarketData(mkd)marketAssessment=MarketData.UpsertData(MarketData.MarketDataIdentifier('PROVIDER','MARKETDATANAME'),'CET',marketAssessment={datetime(2020,1,1):{"Feb-20":MarketData.MarketAssessmentValue(open=10.0,close=11.0),"Mar-20":MarketData.MarketAssessmentValue(open=20.0,close=21.0)},datetime(2020,1,2):{"Feb-20":MarketData.MarketAssessmentValue(open=11.0,close=12.0),"Mar-20":MarketData.MarketAssessmentValue(open=21.0,close=22.0)}},downloadedAt=datetime(2020,1,3).replace(tzinfo=tz.UTC))mkservice.upsertData(marketAssessment)Write Data in a Bid Ask Time SeriesfromArtesianimportArtesianConfig,Granularity,MarketDatafromdatetimeimportdatetimefromdateutilimporttzcfg=ArtesianConfg()mkservice=MarketData.MarketDataService(cfg)mkdid=MarketData.MarketDataIdentifier('PROVIDER','MARKETDATANAME')mkd=MarketData.MarketDataEntityInput(providerName=mkdid.provider,marketDataName=mkdid.name,originalGranularity=Granularity.Day,type=MarketData.MarketDataType.BidAsk,originalTimezone="CET",tags={'TestSDKPython':['PythonValue2']})registered=mkservice.readMarketDataRegistryByName(mkdid.provider,mkdid.name)if(registeredisNone):registered=mkservice.registerMarketData(mkd)bidAsk=MarketData.UpsertData(MarketData.MarketDataIdentifier('PROVIDER','MARKETDATANAME'),'CET',bidAsk={datetime(2020,1,1):{"Feb-20":MarketData.BidAskValue(bestBidPrice=15.0,lastQuantity=14.0),"Mar-20":MarketData.BidAskValue(bestBidPrice=25.0,lastQuantity=24.0)},datetime(2020,1,2):{"Feb-20":MarketData.BidAskValue(bestBidPrice=15.0,lastQuantity=14.0),"Mar-20":MarketData.BidAskValue(bestBidPrice=25.0,lastQuantity=24.0)}},downloadedAt=datetime(2020,1,3).replace(tzinfo=tz.UTC))mkservice.upsertData(bidAsk)Write Data in an Auction Time SeriesfromArtesianimportArtesianConfig,Granularity,MarketDatafromdatetimeimportdatetimefromdateutilimporttzcfg=ArtesianConfg()mkservice=MarketData.MarketDataService(cfg)mkdid=MarketData.MarketDataIdentifier('PROVIDER','MARKETDATANAME')mkd=MarketData.MarketDataEntityInput(providerName=mkdid.provider,marketDataName=mkdid.name,originalGranularity=Granularity.Day,type=MarketData.MarketDataType.Auction,originalTimezone="CET",tags={'TestSDKPython':['PythonValue2']})registered=mkservice.readMarketDataRegistryByName(mkdid.provider,mkdid.name)if(registeredisNone):registered=mkservice.registerMarketData(mkd)auctionRows=MarketData.UpsertData(MarketData.MarketDataIdentifier('PROVIDER','MARKETDATANAME'),'CET',auctionRows={datetime(2020,1,1):MarketData.AuctionBids(datetime(2020,1,1),bid=[MarketData.AuctionBidValue(11.0,12.0),MarketData.AuctionBidValue(13.0,14.0),],offer=[MarketData.AuctionBidValue(21.0,22.0),MarketData.AuctionBidValue(23.0,24.0),])},downloadedAt=datetime(2020,1,3).replace(tzinfo=tz.UTC))mkservice.upsertData(auctionRows)Delete MarketData in ArtesianUsing the MarketDataService is possible to delete MarketData and its curves.fromArtesianimportArtesianConfigfromArtesian.MarketDataimportMarketDataServicecfg=ArtesianConfg()mkservice=MarketDataService(cfg)mkservice.deleteMarketData(100042422)Query written Versions or ProductsUsing MarketDataService is possible to query all the Versions and all the Products curves which has been written in a MarketData.fromArtesian.MarketDataimportMarketDataServicemds=MarketDataService(cfg)To list MarketData curvespage=1pageSize=100res=mds.readCurveRange(100042422,page,pageSize,versionFrom="2016-12-20",versionTo="2019-03-12")Search the MarketData collection with faceted resultsUsing MarketDataService is possible to query and search the MarketData collection with faceted results. Supports paging, filtering and free text.fromArtesian.MarketDataimportMarketDataServicemds=MarketDataService(cfg)To list MarketData curvespage=1pageSize=100searchText="Riconsegnato_"filters={"ProviderName":["SNAM","France"]}sorts=["MarketDataId asc"]doNotLoadAdditionalInfo=Trueres=mds.searchFacet(page,pageSize,searchText,filters,sorts,doNotLoadAdditionalInfo)Jupyter SupportArtesian SDK uses asyncio internally, this causes a conflict with Jupyter. You can work around this issue by add the following at the beginning of the notebook.!pipinstallnest_asyncioimportnest_asyncionest_asyncio.apply()Issue #3397 with workaroundLinksGithubArk EnergyArtesian Portal