Package: lemon
lemon.markets Python SDKlemon.marketsPython SDK facilitates communication with thelemon.marketsAPI for Python programs. The library implements all calls to the endpoints
defined in the Market Data API and Trading API. We currently do not support asynchronous calls.DocumentationSee theAPI docs.InstallationYou can install library usingpip:pipinstalllemonRequirements:Python 3.7+requestspytztyping-extensionsUsageSDK clientTo create and configure our SDK client you will need to have separate API tokens forMarket Data APIandTrading API. You also need to choose which environment you want to use for trading:paperorlive, defaults topaper.
For how to obtain and use our api token, seehere.
The snippet below shows how to properly create a SDK client:fromlemonimportapiclient=api.create(market_data_api_token='your-market-data-api-token',trading_api_token='your-trading-api-token',env='paper'# or env='live')lemon.api.createmethod allows also to configure:timeout- default timeout for requestsretry_count- default number of retries for requestsretry_backoff_factor- default retry backoff factor for retriesThe SDK client consists of three parts:market_data- let's you access the Market Data API endpointsstreaming- let's you retrieve an authentication token that you can use to stream live datatrading- let's you access the Trading API endpoints. Choose the desired target environment (paper or live) in the client configuration.Market Data API usagefromlemonimportapifromdatetimeimportdatetime,timezoneclient=api.create(market_data_api_token='your-market-data-api-token',trading_api_token='your-trading-api-token',)# get venuesresponse=client.market_data.venues.get()print(response.results)# get instrumentsresponse=client.market_data.instruments.get(isin=["US88160R1014","US0231351067"])response=client.market_data.instruments.get(tradable=True,)# automatically iterate over all pages. auto_iter() is available on all list responsesforinstrumentinresponse.auto_iter():print(instrument)response=client.market_data.instruments.get(type=['stock','etf'],currency=['EUR'],limit=10,sorting='asc')# get latest ohlcresponse=client.market_data.ohlc.get(isin=['US88160R1014'],period='m1',from_='latest',epoch=True,decimals=True)# get ohlcresponse=client.market_data.ohlc.get(isin=['US88160R1014'],period='d1',from_=datetime(2021,1,2))# get latest quotesresponse=client.market_data.quotes.get_latest(isin=['US88160R1014','US0231351067'],epoch=True,sorting='asc')# get historical quotes# for period <timestamp, timestamp + 1 day)response=client.market_data.quotes.get(isin="US88160R1014",from_=datetime(2022,10,5,tzinfo=timezone.utc),)# for period <timestamp - 1 day, timestamp)response=client.market_data.quotes.get(isin="US88160R1014",to=datetime(2022,10,5,tzinfo=timezone.utc),)# for specific period <from, to) - timedelta has to be <= 1 dayresponse=client.market_data.quotes.get(isin="US88160R1014",from_=datetime(2022,10,5,tzinfo=timezone.utc),to=datetime(2022,10,5,15,tzinfo=timezone.utc),)# if you don't provide from/to - endpoint works the same as 'client.market_data.quotes.get_latest'response=client.market_data.quotes.get(isin="US88160R1014")# get tradesresponse=client.market_data.trades.get_latest(isin=['US88160R1014','US0231351067'],decimals=True)# get historical trades# for period <timestamp, timestamp + 1 day)response=client.market_data.trades.get(isin="US88160R1014",from_=datetime(2022,10,5,tzinfo=timezone.utc),)# for period <timestamp - 1 day, timestamp)response=client.market_data.trades.get(isin="US88160R1014",to=datetime(2022,10,5,tzinfo=timezone.utc),)# for specific period <from, to) - timedelta has to be <= 1 dayresponse=client.market_data.trades.get(isin="US88160R1014",from_=datetime(2022,10,5,tzinfo=timezone.utc),to=datetime(2022,10,5,15,tzinfo=timezone.utc),)# if you don't provide from/to - endpoint works the same as 'client.market_data.trades.get_latest'response=client.market_data.trades.get(isin="US88160R1014")Streaming API Usagefromlemonimportapiclient=api.create(...)# get live streaming authentication tokenresponse=client.streaming.authenticate()Streaming API exampleThis example relies on that you have both this SDK installed as well as paho-mqtt package.Below is an example usage of live streaming quotes through alby mqtt broker using paho mqtt client.
When connecting to the broker the on_connect callback will be triggered.
This in return will trigger the on_subscribe callback where we can let the broker know what ISINS we are interested in
There is a limitation to only have 4 channels connected at once.
You may be able to create more than 4 channels - however we then may close any one of them at any time.After that we will simply get all the quote updates through the on_message callback.fromlemonimportapifromlemon.market_data.modelimportQuoteimportpaho.mqtt.clientasmqttimportjsonclient=api.create(...)# get live streaming authentication tokenresponse=client.streaming.authenticate()defon_connect(mqtt_client,userdata,flags,rc):mqtt_client.subscribe(response.user_id)defon_subscribe(mqtt_client,userdata,level,buff):mqtt_client.publish(f"{response.user_id}.subscriptions","US88160R1014,US0231351067")defon_message(mqtt_client,userdata,msg):data=json.loads(msg.payload)quote=Quote._from_data(data,int,int)# initiate mqtt- client for streamingmqtt_client=mqtt.Client("Ably_Client")mqtt_client.username_pw_set(username=response.token)mqtt_client.on_connect=on_connect# callbck to handle connectmqtt_client.on_subscribe=on_subscribe# callbck to handle subscribemqtt_client.on_message=on_message# callbck to handle messagemqtt_client.connect("mqtt.ably.io")mqtt_client.loop_forever()# start the mqtt client and loop foreverTrading API usagefromlemonimportapiclient=api.create(...)# create buy orderresponse=client.trading.orders.create(isin='US88160R1014',side='buy',quantity=1,)order_id=response.results.id# activate buy orderresponse=client.trading.orders.activate(order_id=order_id)# get buy order statusresponse=client.trading.orders.get_order(order_id=order_id)# get ordersresponse=client.trading.orders.get()# iterate over all orders of all pagesfororderinresponse.auto_iter():print(order)# cancel order# create an order firstresponse=client.trading.orders.create(isin='US88160R1014',side='buy',quantity=1,)# cancel the order via order_idresponse=client.trading.orders.cancel(order_id=response.results.id)# update accountresponse=client.trading.account.update(address_street='Ritterstrasse',address_city="Berlin")# withdraw money from accountresponse=client.trading.account.withdraw(amount=100000,pin="1234")# get bank statementsresponse=client.trading.account.get_bank_statements(type='eod_balance',from_="beginning")# get documentsresponse=client.trading.account.get_documents()# get documentresponse=client.trading.account.get_document(document_id='doc_xyz')# get userresponse=client.trading.user.get()# get positionsresponse=client.trading.positions.get(isin='US88160R1014')# get statementsresponse=client.trading.positions.get_statements()# get performanceresponse=client.trading.positions.get_performance()Direct API callsIt is possible to call Market Data API/Trading API endpoints directly by providing path to the endpoint
and optionally - query parameters and payload to be sent.  SDK currently supportsGET|POST|PUT|DELETEmethods.fromlemonimportapiclient=api.create(...)response=client.trading.put(url="account",json={"address_street":'New street name'})response=client.market_data.get(url="instruments",params={"search":"t*sla"})Error handlingError structure available in the SDK is presented belowBaseLemonError- base class for all errors thrown within the SDKLemonError- base class of errors returned by API. It contains information directly from it, such asstatus,error_code,error_message, ...InvalidQueryError- HTTP request validation errorAuthenticationError- authentication errorInternalServerError- internal API errorBusinessLogicError- a business logic error caused by specific conditions of the system preventing from fulfilling the requestAPIError- error thrown in case when it's impossible to decode the API responsePlease note that errors raised fromrequestsmodule are passed as they are.fromlemonimportapi,errorsclient=api.create(...)try:response=client.trading.orders.create(isin='...',side='buy',quantity=1)excepterrors.InvalidQueryError:...excepterrors.AuthenticationError:...excepterrors.InternalServerError:...excepterrors.BusinessLogicErroraserr:iferr.error_code=='some_specific_error':print(err.error_message)...# do something...excepterrors.LemonError:# InvalidRequestError/AuthenticationError/InternalServerError/BusinessLogicError...excepterrors.APIError:...excepterrors.BaseLemonError:# catches all errors defined above...except:# other errors, including errors from `requests` module...Model serializationEvery response(or response nested structure) can be serialized to python dictionary or JSON:fromlemonimportapiclient=api.create(market_data_api_token='your-market-data-api-token',trading_api_token='your-trading-api-token',)response=client.market_data.instruments.get()print(response.dict())print(response.json())print(response.results[0].dict())print(response.results[0].json())