Skip to main content

Library provides read access to the Artesian API

Project description

Artesian.SDK

This Library provides read access to the Artesian API

Getting Started

Installation

You can install the package directly from pip.

pip install artesian-sdk

Alternatively, to install this package go to the release page .

How to use

The Artesian.SDK instance can be configured using API-Key authentication

from Artesian import ArtesianConfig

cfg = ArtesianConfig("https://arkive.artesian.cloud/{tenantName}/", "{api-key}")

BREAKING CHANGES: Upgrade v2->v3

The following breaking changes has been introduced in v3 respect to v2.

Python Version >=3.8

Python >=3.8 is required. Python 3.7 is not supported due missing 'typing' features.

SubPackaging

With 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:

from Artesian import *

cfg = ArtesianConfig("https://arkive.artesian.cloud/{tenantName}/", "{api-key}")
qs = QueryService(cfg)

now you have to:

from Artesian import ArtesianConfig
from Artesian.Query import QueryService

cfg = ArtesianConfig("https://arkive.artesian.cloud/{tenantName}/", "{api-key}")
qs = QueryService(cfg)

Enum entries Casing

To 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 QueryService

Using the ArtesianConfig cfg we create an instance of the QueryService which is used to create Actual, Versioned and Market Assessment time series queries

Actual Time Series Extraction

from Artesian import ArtesianConfig, Granularity
from Artesian.Query import QueryService, RelativeInterval

cfg = 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 QueryDescription
Market Data IDProvide a market data id or set of market data id's to query
Time GranularitySpecify the granularity type
Time Extraction WindowAn extraction time window for data to be queried

Go to Time Extraction window section

Versioned Time Series Extraction

from Artesian import ArtesianConfig, Granularity
from Artesian.Query import QueryService, RelativeInterval

qs = 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 QueryDescription
Market Data IDProvide a market data id or set of market data id's to query
Time GranularitySpecify the granularity type
Versioned Time Extraction WindowVersioned extraction time window
Time Extraction WindowAn extraction time window for data to be queried

Go to Time Extraction window section

Market Assessment Time Series Extraction

from Artesian import ArtesianConfig
from Artesian.Query import QueryService, RelativeInterval

qs = 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 QueryDescription
Market Data IDProvide a market data id or set of market data id's to query
ProductProvide a product or set of products
Time Extraction WindowAn extraction time window for data to be queried

Go to Time Extraction window section

Bid Ask Time Series Extraction

from Artesian import ArtesianConfig
from Artesian.Query import QueryService, RelativeInterval

qs = 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 QueryDescription
Market Data IDProvide a market data id or set of market data id's to query
ProductProvide a product or set of products
Time Extraction WindowAn extraction time window for data to be queried

Go to Time Extraction window section

Auction Time Series Extraction

from Artesian import ArtesianConfig
from Artesian.Query import QueryService, RelativeInterval

qs = 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 QueryDescription
Market Data IDProvide a market data id or set of market data id's to query
Time Extraction WindowAn extraction time window for data to be queried

Go to Time Extraction window section

Extraction Windows

Extraction 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 Strategy

All extraction types (Actual,Versioned, Market Assessment and BidAsk) have an optional filler strategy.

var versionedSeries = qs
  .createVersioned() \
  .forMarketData([100000001]) \
  .forLastNVersions(1) \
  .inGranularity(Granularity.Day) \
  .inAbsoluteDateRange(new Date("2018-1-1"), new Date("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")

Query written Versions or Products

Using MarketDataService is possible to query all the Versions and all the Products curves which has been written in a MarketData.

from Artesian.MarketData import MarketDataService

mds = MarketDataService(cfg)

To list MarketData curves

page = 1
pageSize = 100
res = mds.readCurveRange(100042422, page, pageSize, versionFrom="2016-12-20" , versionTo="2019-03-12")

Search the MarketData collection with faceted results

Using MarketDataService is possible to query and search the MarketData collection with faceted results. Supports paging, filtering and free text.

from Artesian.MarketData import MarketDataService

mds = MarketDataService(cfg)

To list MarketData curves

page = 1
pageSize = 100
searchText = "Riconsegnato_"
filters = {"ProviderName": ["SNAM", "France"]}
sorts=["MarketDataId asc"]
doNotLoadAdditionalInfo=True
res = mds.searchFacet(page, pageSize, searchText, filters, sorts, doNotLoadAdditionalInfo)

GME Public Offer

Artesian support Query over GME Public Offers which comes in a custom and dedicated format.

Extract GME Public Offer

from Artesian.GMEPublicOffers import GMEPublicOfferService, Market, Purpose, Status, Zone, Scope, UnitType, GenerationType, BAType

qs = 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 QueryDescription
Time Extraction WindowAn extraction time window for data to be queried
MarketProvide a market or set of markets to query
StatusProvide a status or set of statuses to query
PurposeProvide a purpose or set of purposes to query
ZoneProvide a zone to query

Extraction Options

Extraction 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 Artesian

Using 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 Series

from Artesian import ArtesianConfig, Granularity, MarketData
from Artesian.MarketData import AggregationRule
from datetime import datetime
from dateutil import tz

cfg = 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 (registered is None):
  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 (registered is None):
  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 Series

from Artesian import ArtesianConfig, Granularity, MarketData
from Artesian.MarketData import AggregationRule
from datetime import datetime
from dateutil import tz

cfg = 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 (registered is None):
  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 Series

from Artesian import ArtesianConfig, Granularity, MarketData
from datetime import datetime
from dateutil import tz

cfg = 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 (registered is None):
  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 Series

from Artesian import ArtesianConfig,Granularity,MarketData
from datetime import datetime
from dateutil import tz

cfg = 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 (registered is None):
  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 Series

from Artesian import ArtesianConfig,Granularity,MarketData
from datetime import datetime
from dateutil import tz

cfg = 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 (registered is None):
  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 Data in Artesian

Using the MarketDataService is possible to delete MarketData and its curves.

Delete MarketData in Artesian

Using the MarketDataService is possible to delete MarketData and its curves.

from Artesian import ArtesianConfig
from Artesian.MarketData import MarketDataService

cfg = ArtesianConfg()
mkservice = MarketDataService(cfg)

mkservice.deleteMarketData(100042422)

Depending on the Type of the MarketData, the DeletData should be composed as per example below.

Delete Data in an Actual Time Series

from Artesian import ArtesianConfig, Granularity, MarketData
from Artesian.MarketData import AggregationRule
from datetime import datetime
from dateutil import tz

cfg = ArtesianConfg()

mkservice = MarketData.MarketDataService(cfg)

mkdid = MarketData.MarketDataIdentifier('PROVIDER', 'MARKETDATANAME')
deleteData = MarketData.DeleteData(
    ID=mkdid,
    timezone='CET',
    rangeStart=datetime(2020, 1, 1, 6),
    rangeEnd=datetime(2020, 1, 1, 18),
)

mkdservice.deleteData(deleteData)

Delete Data in an Versioned Time Series

from Artesian import ArtesianConfig, Granularity, MarketData
from Artesian.MarketData import AggregationRule
from datetime import datetime
from dateutil import tz

cfg = ArtesianConfg()

mkservice = MarketData.MarketDataService(cfg)

mkdid = MarketData.MarketDataIdentifier('PROVIDER', 'MARKETDATANAME')
deleteData = MarketData.DeleteData(
    ID=mkdid,
    timezone='CET',
    rangeStart=datetime(2020, 1, 1, 0),
    rangeEnd=datetime(2020, 1, 7, 0),
    version=datetime(2020, 1, 1, 0)
)

mkdservice.deleteData(deleteData)

Delte Data in a Market Assessment Time Series

from Artesian import ArtesianConfig, Granularity, MarketData
from datetime import datetime
from dateutil import tz

cfg = ArtesianConfg()
mkservice = MarketData.MarketDataService(cfg)

mkdid = MarketData.MarketDataIdentifier('PROVIDER', 'MARKETDATANAME')
deleteData = MarketData.DeleteData(
    ID= mkdid,
    timezone='CET',
    rangeStart=datetime(2020, 1, 1, 0),
    rangeEnd=datetime(2020, 1, 3, 0),
    product=["Feb-20"]
)

mkdservice.deleteData(deleteData)

Delte Data in a Bid Ask Time Series

from Artesian import ArtesianConfig, Granularity, MarketData
from datetime import datetime
from dateutil import tz

cfg = ArtesianConfg()
mkservice = MarketData.MarketDataService(cfg)

mkdid = MarketData.MarketDataIdentifier('PROVIDER', 'MARKETDATANAME')
deleteData = MarketData.DeleteData(
    ID= mkdid,
    timezone='CET',
    rangeStart=datetime(2020, 1, 1, 0),
    rangeEnd=datetime(2020, 1, 3, 0),
    product=["Feb-20"]
)

mkdservice.deleteData(deleteData)

Delete Data in an Auction Time Series

from Artesian import ArtesianConfig, Granularity, MarketData
from Artesian.MarketData import AggregationRule
from datetime import datetime
from dateutil import tz

cfg = ArtesianConfg()

mkservice = MarketData.MarketDataService(cfg)

mkdid = MarketData.MarketDataIdentifier('PROVIDER', 'MARKETDATANAME')
deleteData = MarketData.DeleteData(
    ID=mkdid,
    timezone='CET',
    rangeStart=datetime(2020, 1, 1, 6),
    rangeEnd=datetime(2020, 1, 1, 18),
)

mkdservice.deleteData(deleteData)

Jupyter Support

Artesian 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.

!pip install nest_asyncio

import nest_asyncio
nest_asyncio.apply()

Issue #3397 with workaround

Links

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

artesian_sdk-3.1.4.dev10.tar.gz (54.3 kB view hashes)

Uploaded Source

Built Distribution

artesian_sdk-3.1.4.dev10-py3-none-any.whl (59.1 kB view hashes)

Uploaded Python 3

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page