Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Charles Allderman committed Aug 31, 2018
0 parents commit f4bb9c0
Show file tree
Hide file tree
Showing 5 changed files with 362 additions and 0 deletions.
58 changes: 58 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# PyIRess #

PyIress is a Python interface onto the Iress web services API. See the [Website] (https://www.iress.com/za/company/products/iress-pro-market-data-desktop/).

### Main Features ###

* The code allows for easy extraction of the following types of data
Time series information
Dividend information
Index information
* Version 0.1
* This is the first version and the intention is to add to the list of available functions.
* The following are currenly available:
- time_series : an items times series
- dividends : dividends for an item
- get_many : many of the above
- MarketCapitalizationHistorical : Index constituent information

### Installation ###

* Dependencies
zeep
For the [Zeep documentation] (https://python-zeep.readthedocs.io/en/master/).
pandas
For the dependencies of `pandas` please refer to the [pandas documentation](http://pandas.pydata.org/pandas-docs/stable/install.html).

* To install the latest version
pip install pyiress


### Some Notes on Use ###

Pandas is great for data analysis


from pyiress import Iress
import pandas as pd
companyname = "<>"
username = "<>"
password = "<>"
ApplicationID='app'

iress = Iress(companyname=companyname,username=username,password=password,show_request=False)
tickers=['AGL','BIL']
exchange = 'JSE'
start_date, end_date = pd.datetime(2012,9,30),pd.datetime(2018,8,30)
data=iress.get_many('time_series',tickers,exchange,start_date,end_date)
data=data[['ClosePrice']]
data.unstack(1).plot()
### Resources ###

* Use the help in Iress Pro. Go to Help/API Documentation and select the pertinant resource.


### Acknowledgements ###

* Thanks to Vladimir Filimonov @vfilimonov whe wrote PyDatastream on which this project is based
2 changes: 2 additions & 0 deletions pyiress/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
### Dummy __init__ file
from .pyiress import *
265 changes: 265 additions & 0 deletions pyiress/pyiress.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,265 @@
from __future__ import print_function
import zeep
import numpy as np
import pandas as pd
import warnings

_INFO = """PyIress documentation (GitHub):
https://github.com/ceaza/pyiress"""

WSDL_URL_GENERIC='http://127.0.0.1:51234/wsdl.aspx?un={username}&cp={companyname}&svc={service}&svr=&pw={password}'

class PyIressException(Exception):
pass

class Iress(object):
def __init__(self, companyname,username, password, service='IRESS',raise_on_error=True, show_request=False,
proxy=None, **kwargs):
"""Establish a connection to the IRESS Web Services with Version 4 desktop.
companyname / username / password - credentials for the Iress account.
service - only service for desktop version is IRESS.
raise_on_error - If True then error request will raise a "IressException",
otherwise either empty dataframe or partially
retrieved data will be returned
show_request - If True, then every time a request string will be printed
A custom WSDL url (if necessary for some reasons) could be provided
via "url" parameter.
"""
import logging.config
self.services=[service]
self.show_request = show_request
if self.show_request:
logging.config.dictConfig({
'version': 1,
'formatters': {
'verbose': {
'format': '%(name)s: %(message)s'
}
},
'handlers': {
'console': {
'level': 'DEBUG',
'class': 'logging.StreamHandler',
'formatter': 'verbose',
},
},
'loggers': {
'zeep.transports': {
'level': 'DEBUG',
'propagate': True,
'handlers': ['console'],
},
}
})
else:
logging.config.dictConfig({
'version': 1,
'disable_existing_loggers': True,
})
self.raise_on_error = raise_on_error
self.last_status = None # Will contain status of last request
WSDL_URL = WSDL_URL_GENERIC.format(companyname=companyname,username=username,password=password,service=service)
self._url = kwargs.pop('url', WSDL_URL)
# Trying to connect
try:
self.client = zeep.Client(wsdl=WSDL_URL, strict=False)
except:
raise PyIressException('Cannot Connect')

# Create session
login_details={'UserName':username,
'CompanyName':companyname,
'Password':password,
'ApplicationID':'app'}
IRESSSessionStartInputHeader = {"Parameters":login_details}
self.session=self.client.service.IRESSSessionStart(Input=IRESSSessionStartInputHeader)
self.IRESSSessionKey=self.session.Result.DataRows.DataRow[0].IRESSSessionKey
self.UserToken=self.session.Result.DataRows.DataRow[0].UserToken
self.last_response = None
self.header={'Header':{'SessionKey':self.IRESSSessionKey}}

# Check available data sources
if 'IRESS' not in self.services:
warnings.warn("'IRESS' source is not available for given subscription!")

@staticmethod
def info():
print(_INFO)

def sources(self):
"""Return available sources of data.
Curretly only IRESS"""
return self.services

def version(self):
"""Return version of Iress Client."""
res = self.client.namespaces
return res


def _time_series(self,ticker,exchange,start_date,end_date,freq='daily'):
'''
SecurityCode string Yes No The security code to filter by.
Exchange string Yes No The exchange to filter by.
DataSource string Yes No The data source to filter by.
Frequency string No No The frequency type, one of 'daily', 'weekly', 'monthly', 'quarterly' or 'yearly'.
TimeSeriesFromDate date No No The date to retrieve time series from.
TimeSeriesToDate date No No The date to retrieve time series to.
'''
parameters={'Parameters': {'SecurityCode': ticker,
'Exchange': exchange,
'Frequency':freq,
'TimeSeriesFromDate':start_date.strftime('%Y/%m/%d'),
'TimeSeriesToDate':end_date.strftime('%Y/%m/%d')
} }

inputs={**self.header, **parameters}
res=self.client.service.TimeSeriesGet2(Input=inputs)
try:
data=zeep.helpers.serialize_object(res.Result.DataRows.DataRow)
df=pd.DataFrame(data)
# print(df.tail())
df['TimeSeriesDate']=pd.to_datetime(df.TimeSeriesDate)
df=df.set_index('TimeSeriesDate')
# print(df.columns)
except:
df=pd.DataFrame()

return df


def time_series(self,ticker,exchange,start_date,end_date,freq='daily',fields=[]):
'''
SecurityCode string Yes No The security code to filter by.
Exchange string Yes No The exchange to filter by.
DataSource string Yes No The data source to filter by.
Frequency string No No The frequency type, one of 'daily', 'weekly', 'monthly', 'quarterly' or 'yearly'.
TimeSeriesFromDate date No No The date to retrieve time series from.
TimeSeriesToDate date No No The date to retrieve time series to.
Available fields - ['OpenPrice', 'HighPrice', 'LowPrice', 'ClosePrice', 'TotalVolume',
'TotalValue', 'TradeCount', 'AdjustmentFactor', 'MarketVWAP',
'ShortSold', 'ShortSoldPercent', 'ShortSellPosition',
'ShortSellPositionPercent', '_value_1', 'exchange']
'''
part_date=start_date
data=pd.DataFrame()
while part_date < pd.Timestamp(end_date):
new_data=self._time_series(ticker,exchange,part_date,end_date,freq)
data=pd.concat([data,new_data])
part_date = data.index.max() + pd.DateOffset(1,'D')
return data

def dividends(self,ticker,exchange,start_date,end_date,freq=None,index_on='ExDividendDate'):
'''
SecurityCode string Yes No The security code to filter by.
Exchange string Yes No The exchange to filter by.
DataSource string Yes No The data source to filter by.
Frequency string No No The frequency type, one of 'daily', 'weekly', 'monthly', 'quarterly' or 'yearly'.
TimeSeriesFromDate date No No The date to retrieve time series from.
TimeSeriesToDate date No No The date to retrieve time series to.
available fields = ['DividendAmount', 'AdjustedDividendAmount', 'FrankedPercent',
'PayableDate', 'BooksClosingDate', 'DividendType', 'ShareRate',
'DividendYield', 'DRPPrice', 'DividendDescription', 'DeclarationDate',
'STCCreditsPerShare', '_value_1', 'exchange']
'''
parameters={'Parameters': {'SecurityCode': ticker,
'Exchange': exchange,
'PayDateFrom':start_date.strftime('%Y/%m/%d'),
'PayDateTo':end_date.strftime('%Y/%m/%d')
} }

inputs={**self.header, **parameters}
res=self.client.service.SecurityDividendGetBySecurity(Input=inputs)
data=zeep.helpers.serialize_object(res.Result.DataRows.DataRow)
df=pd.DataFrame(data)
df[index_on]=pd.to_datetime(df[index_on])
df=df.set_index(index_on)

return df

def MarketCapitalizationHistorical(self,indexcode,ticker,exchange,start_date,end_date):
'''
Input Parameters
For the items that are nullable input None
Pos Name Type Nullable? DefaultValue Array? ArraySize Description Alias
1 IndexCode string Yes No The index to filter by.
2 SecurityCode string Yes No Security code.
3 Exchange string Yes No Exchange where the security is listed.
4 MarketCapitalizationDateFrom date No No The date to retrieve market capitalization history from.
5 MarketCapitalizationDateTo date No No The date to retrieve market capitalization history to.
Output Columns
Pos Name Type Nullable? Default Value Description Alias
1 SecurityCode string No Security code.
2 Exchange string No Exchange where the security is listed.
3 GICSCode int32 Yes Global Industry Classification Standard.
4 MarketCapitalizationDate date No Date at which market capitalization was calculated.
5 IndexCode string No Index code.
6 IndexFactor double Yes The index factor.
7 IndexPoints double Yes Index points.
8 SharesOnIssue double Yes Number of shares issued for the security at the time market capitalization was calculated.
9 MarketCapitalizationStartOfDay double Yes Market capitalization at the start of the day.
10 MarketCapitalizationEndOfDay double Yes Market capitalization at the end of the day.
11 MarketWeightStartOfDay double Yes Market weight at the start of the day.
12 MarketWeightEndOfDay double Yes Market weight at the end of the day.
13 IndexPriceStartOfDay double Yes Index price at the start of the day.
14 IndexPriceEndOfDay double Yes Index price at the end of the day.
'''

parameters={'Parameters': {'IndexCode':indexcode,
'SecurityCode': ticker,
'Exchange': exchange,
'MarketCapitalizationDateFrom':start_date.strftime('%Y/%m/%d'),
'MarketCapitalizationDateTo':end_date.strftime('%Y/%m/%d')
} }
remove_key=[]
for k,v in parameters['Parameters'].items():
if v==None:
remove_key.append(k)
for k in remove_key:
del parameters['Parameters'][k]

inputs={**self.header, **parameters}
res = self.client.service.MarketCapitalizationHistoricalGet(Input=inputs)
data=zeep.helpers.serialize_object(res.Result.DataRows.DataRow)
df=pd.DataFrame(data)
return df


def get_many(self,data_type,tickers,exchange,start_date,end_date,freq='daily'):
'''
'''
data_list=[]
date_field={'dividends':'ExDividendDate',
'time_series':'TimeSeriesDate'}
if data_type not in ['dividends','time_series']:
warnings.warn("Not available for this data type")
return
method_to_call = getattr(self, data_type)
for ticker in tickers:
data=method_to_call(ticker,exchange,start_date,end_date,freq)
data=data.reset_index()
data['ticker']=ticker
data['exchange']=exchange
data=data.set_index([date_field[data_type],'ticker'])
data_list.append(data)
df_data=pd.concat(data_list)
return df_data

if __name__ == "__main__":
pass






2 changes: 2 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[metadata]
description-file = README.md
35 changes: 35 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
from distutils.core import setup
import sys

if sys.version_info.major < 3:
break
else:
install_requires_list = ['zeep', 'pandas']

# Long description to be published in PyPi
LONG_DESCRIPTION = """
**PyIress** is a Python interface to the **Iress Pro Desktop Web Services
(IPD)** SOAP client (non free), with some convenience functions for retrieving
Iress data specifically. This package requires valid credentials for this
API.
For the documentation please refer to README.md inside the package or on the
GitHub (https://github.com/ceaza/pyiress/blob/master/README.md).
"""

_URL = 'https://github.com/ceaza/pyiress'
_VERSION = '0.0.1'

setup(name='PyIress',
version=_VERSION,
description='Python interface to the **Iress Pro Desktop Web Services API',
long_description=LONG_DESCRIPTION,
url=_URL,
download_url=_URL + '/archive/v' + _VERSION + '.zip',
author='Charles Allderman',
author_email='[email protected]',
license='MIT License',
packages=['pyiress'],
install_requires=install_requires_list,
classifiers=['Programming Language :: Python :: 3', ]
)

0 comments on commit f4bb9c0

Please sign in to comment.