244 lines
8.8 KiB
Python
244 lines
8.8 KiB
Python
|
#!/usr/bin/python
|
||
|
#
|
||
|
# Copyright (C) 2009 Tan Swee Heng
|
||
|
#
|
||
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
# you may not use this file except in compliance with the License.
|
||
|
# You may obtain a copy of the License at
|
||
|
#
|
||
|
# http://www.apache.org/licenses/LICENSE-2.0
|
||
|
#
|
||
|
# Unless required by applicable law or agreed to in writing, software
|
||
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
# See the License for the specific language governing permissions and
|
||
|
# limitations under the License.
|
||
|
|
||
|
|
||
|
"""Classes to interact with the Google Finance server."""
|
||
|
|
||
|
|
||
|
__author__ = 'thesweeheng@gmail.com'
|
||
|
|
||
|
|
||
|
import gdata.service
|
||
|
import gdata.finance
|
||
|
import atom
|
||
|
|
||
|
|
||
|
class PortfolioQuery(gdata.service.Query):
|
||
|
"""A query object for the list of a user's portfolios."""
|
||
|
|
||
|
def returns(self):
|
||
|
return self.get('returns', False)
|
||
|
|
||
|
def set_returns(self, value):
|
||
|
if value is 'true' or value is True:
|
||
|
self['returns'] = 'true'
|
||
|
|
||
|
returns = property(returns, set_returns, doc="The returns query parameter")
|
||
|
|
||
|
def positions(self):
|
||
|
return self.get('positions', False)
|
||
|
|
||
|
def set_positions(self, value):
|
||
|
if value is 'true' or value is True:
|
||
|
self['positions'] = 'true'
|
||
|
|
||
|
positions = property(positions, set_positions,
|
||
|
doc="The positions query parameter")
|
||
|
|
||
|
|
||
|
class PositionQuery(gdata.service.Query):
|
||
|
"""A query object for the list of a user's positions in a portfolio."""
|
||
|
|
||
|
def returns(self):
|
||
|
return self.get('returns', False)
|
||
|
|
||
|
def set_returns(self, value):
|
||
|
if value is 'true' or value is True:
|
||
|
self['returns'] = 'true'
|
||
|
|
||
|
returns = property(returns, set_returns,
|
||
|
doc="The returns query parameter")
|
||
|
|
||
|
def transactions(self):
|
||
|
return self.get('transactions', False)
|
||
|
|
||
|
def set_transactions(self, value):
|
||
|
if value is 'true' or value is True:
|
||
|
self['transactions'] = 'true'
|
||
|
|
||
|
transactions = property(transactions, set_transactions,
|
||
|
doc="The transactions query parameter")
|
||
|
|
||
|
|
||
|
class FinanceService(gdata.service.GDataService):
|
||
|
|
||
|
def __init__(self, email=None, password=None, source=None,
|
||
|
server='finance.google.com', **kwargs):
|
||
|
"""Creates a client for the Finance service.
|
||
|
|
||
|
Args:
|
||
|
email: string (optional) The user's email address, used for
|
||
|
authentication.
|
||
|
password: string (optional) The user's password.
|
||
|
source: string (optional) The name of the user's application.
|
||
|
server: string (optional) The name of the server to which a connection
|
||
|
will be opened. Default value: 'finance.google.com'.
|
||
|
**kwargs: The other parameters to pass to gdata.service.GDataService
|
||
|
constructor.
|
||
|
"""
|
||
|
gdata.service.GDataService.__init__(self,
|
||
|
email=email, password=password, service='finance', server=server,
|
||
|
**kwargs)
|
||
|
|
||
|
def GetPortfolioFeed(self, query=None):
|
||
|
uri = '/finance/feeds/default/portfolios'
|
||
|
if query:
|
||
|
uri = PortfolioQuery(feed=uri, params=query).ToUri()
|
||
|
return self.Get(uri, converter=gdata.finance.PortfolioFeedFromString)
|
||
|
|
||
|
def GetPositionFeed(self, portfolio_entry=None, portfolio_id=None,
|
||
|
query=None):
|
||
|
"""
|
||
|
Args:
|
||
|
portfolio_entry: PortfolioEntry (optional; see Notes)
|
||
|
portfolio_id: string (optional; see Notes) This may be obtained
|
||
|
from a PortfolioEntry's portfolio_id attribute.
|
||
|
query: PortfolioQuery (optional)
|
||
|
|
||
|
Notes:
|
||
|
Either a PortfolioEntry OR a portfolio ID must be provided.
|
||
|
"""
|
||
|
if portfolio_entry:
|
||
|
uri = portfolio_entry.GetSelfLink().href + '/positions'
|
||
|
elif portfolio_id:
|
||
|
uri = '/finance/feeds/default/portfolios/%s/positions' % portfolio_id
|
||
|
if query:
|
||
|
uri = PositionQuery(feed=uri, params=query).ToUri()
|
||
|
return self.Get(uri, converter=gdata.finance.PositionFeedFromString)
|
||
|
|
||
|
def GetTransactionFeed(self, position_entry=None,
|
||
|
portfolio_id=None, ticker_id=None):
|
||
|
"""
|
||
|
Args:
|
||
|
position_entry: PositionEntry (optional; see Notes)
|
||
|
portfolio_id: string (optional; see Notes) This may be obtained
|
||
|
from a PortfolioEntry's portfolio_id attribute.
|
||
|
ticker_id: string (optional; see Notes) This may be obtained from
|
||
|
a PositionEntry's ticker_id attribute. Alternatively it can
|
||
|
be constructed using the security's exchange and symbol,
|
||
|
e.g. 'NASDAQ:GOOG'
|
||
|
|
||
|
Notes:
|
||
|
Either a PositionEntry OR (a portfolio ID AND ticker ID) must
|
||
|
be provided.
|
||
|
"""
|
||
|
if position_entry:
|
||
|
uri = position_entry.GetSelfLink().href + '/transactions'
|
||
|
elif portfolio_id and ticker_id:
|
||
|
uri = '/finance/feeds/default/portfolios/%s/positions/%s/transactions' \
|
||
|
% (portfolio_id, ticker_id)
|
||
|
return self.Get(uri, converter=gdata.finance.TransactionFeedFromString)
|
||
|
|
||
|
def GetPortfolio(self, portfolio_id=None, query=None):
|
||
|
uri = '/finance/feeds/default/portfolios/%s' % portfolio_id
|
||
|
if query:
|
||
|
uri = PortfolioQuery(feed=uri, params=query).ToUri()
|
||
|
return self.Get(uri, converter=gdata.finance.PortfolioEntryFromString)
|
||
|
|
||
|
def AddPortfolio(self, portfolio_entry=None):
|
||
|
uri = '/finance/feeds/default/portfolios'
|
||
|
return self.Post(portfolio_entry, uri,
|
||
|
converter=gdata.finance.PortfolioEntryFromString)
|
||
|
|
||
|
def UpdatePortfolio(self, portfolio_entry=None):
|
||
|
uri = portfolio_entry.GetEditLink().href
|
||
|
return self.Put(portfolio_entry, uri,
|
||
|
converter=gdata.finance.PortfolioEntryFromString)
|
||
|
|
||
|
def DeletePortfolio(self, portfolio_entry=None):
|
||
|
uri = portfolio_entry.GetEditLink().href
|
||
|
return self.Delete(uri)
|
||
|
|
||
|
def GetPosition(self, portfolio_id=None, ticker_id=None, query=None):
|
||
|
uri = '/finance/feeds/default/portfolios/%s/positions/%s' \
|
||
|
% (portfolio_id, ticker_id)
|
||
|
if query:
|
||
|
uri = PositionQuery(feed=uri, params=query).ToUri()
|
||
|
return self.Get(uri, converter=gdata.finance.PositionEntryFromString)
|
||
|
|
||
|
def DeletePosition(self, position_entry=None,
|
||
|
portfolio_id=None, ticker_id=None, transaction_feed=None):
|
||
|
"""A position is deleted by deleting all its transactions.
|
||
|
|
||
|
Args:
|
||
|
position_entry: PositionEntry (optional; see Notes)
|
||
|
portfolio_id: string (optional; see Notes) This may be obtained
|
||
|
from a PortfolioEntry's portfolio_id attribute.
|
||
|
ticker_id: string (optional; see Notes) This may be obtained from
|
||
|
a PositionEntry's ticker_id attribute. Alternatively it can
|
||
|
be constructed using the security's exchange and symbol,
|
||
|
e.g. 'NASDAQ:GOOG'
|
||
|
transaction_feed: TransactionFeed (optional; see Notes)
|
||
|
|
||
|
Notes:
|
||
|
Either a PositionEntry OR (a portfolio ID AND ticker ID) OR
|
||
|
a TransactionFeed must be provided.
|
||
|
"""
|
||
|
if transaction_feed:
|
||
|
feed = transaction_feed
|
||
|
else:
|
||
|
if position_entry:
|
||
|
feed = self.GetTransactionFeed(position_entry=position_entry)
|
||
|
elif portfolio_id and ticker_id:
|
||
|
feed = self.GetTransactionFeed(
|
||
|
portfolio_id=portfolio_id, ticker_id=ticker_id)
|
||
|
for txn in feed.entry:
|
||
|
self.DeleteTransaction(txn)
|
||
|
return True
|
||
|
|
||
|
def GetTransaction(self, portfolio_id=None, ticker_id=None,
|
||
|
transaction_id=None):
|
||
|
uri = '/finance/feeds/default/portfolios/%s/positions/%s/transactions/%s' \
|
||
|
% (portfolio_id, ticker_id, transaction_id)
|
||
|
return self.Get(uri, converter=gdata.finance.TransactionEntryFromString)
|
||
|
|
||
|
def AddTransaction(self, transaction_entry=None, transaction_feed = None,
|
||
|
position_entry=None, portfolio_id=None, ticker_id=None):
|
||
|
"""
|
||
|
Args:
|
||
|
transaction_entry: TransactionEntry (required)
|
||
|
transaction_feed: TransactionFeed (optional; see Notes)
|
||
|
position_entry: PositionEntry (optional; see Notes)
|
||
|
portfolio_id: string (optional; see Notes) This may be obtained
|
||
|
from a PortfolioEntry's portfolio_id attribute.
|
||
|
ticker_id: string (optional; see Notes) This may be obtained from
|
||
|
a PositionEntry's ticker_id attribute. Alternatively it can
|
||
|
be constructed using the security's exchange and symbol,
|
||
|
e.g. 'NASDAQ:GOOG'
|
||
|
|
||
|
Notes:
|
||
|
Either a TransactionFeed OR a PositionEntry OR (a portfolio ID AND
|
||
|
ticker ID) must be provided.
|
||
|
"""
|
||
|
if transaction_feed:
|
||
|
uri = transaction_feed.GetPostLink().href
|
||
|
elif position_entry:
|
||
|
uri = position_entry.GetSelfLink().href + '/transactions'
|
||
|
elif portfolio_id and ticker_id:
|
||
|
uri = '/finance/feeds/default/portfolios/%s/positions/%s/transactions' \
|
||
|
% (portfolio_id, ticker_id)
|
||
|
return self.Post(transaction_entry, uri,
|
||
|
converter=gdata.finance.TransactionEntryFromString)
|
||
|
|
||
|
def UpdateTransaction(self, transaction_entry=None):
|
||
|
uri = transaction_entry.GetEditLink().href
|
||
|
return self.Put(transaction_entry, uri,
|
||
|
converter=gdata.finance.TransactionEntryFromString)
|
||
|
|
||
|
def DeleteTransaction(self, transaction_entry=None):
|
||
|
uri = transaction_entry.GetEditLink().href
|
||
|
return self.Delete(uri)
|