#!/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)