#!/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. """Contains extensions to Atom objects used with Google Finance.""" __author__ = 'thesweeheng@gmail.com' import atom import gdata GD_NAMESPACE = 'http://schemas.google.com/g/2005' GF_NAMESPACE = 'http://schemas.google.com/finance/2007' class Money(atom.AtomBase): """The element.""" _tag = 'money' _namespace = GD_NAMESPACE _attributes = atom.AtomBase._attributes.copy() _attributes['amount'] = 'amount' _attributes['currencyCode'] = 'currency_code' def __init__(self, amount=None, currency_code=None, **kwargs): self.amount = amount self.currency_code = currency_code atom.AtomBase.__init__(self, **kwargs) def __str__(self): return "%s %s" % (self.amount, self.currency_code) def MoneyFromString(xml_string): return atom.CreateClassFromXMLString(Money, xml_string) class _Monies(atom.AtomBase): """An element containing multiple in multiple currencies.""" _namespace = GF_NAMESPACE _children = atom.AtomBase._children.copy() _children['{%s}money' % GD_NAMESPACE] = ('money', [Money]) def __init__(self, money=None, **kwargs): self.money = money or [] atom.AtomBase.__init__(self, **kwargs) def __str__(self): return " / ".join(["%s" % i for i in self.money]) class CostBasis(_Monies): """The element.""" _tag = 'costBasis' def CostBasisFromString(xml_string): return atom.CreateClassFromXMLString(CostBasis, xml_string) class DaysGain(_Monies): """The element.""" _tag = 'daysGain' def DaysGainFromString(xml_string): return atom.CreateClassFromXMLString(DaysGain, xml_string) class Gain(_Monies): """The element.""" _tag = 'gain' def GainFromString(xml_string): return atom.CreateClassFromXMLString(Gain, xml_string) class MarketValue(_Monies): """The element.""" _tag = 'gain' _tag = 'marketValue' def MarketValueFromString(xml_string): return atom.CreateClassFromXMLString(MarketValue, xml_string) class Commission(_Monies): """The element.""" _tag = 'commission' def CommissionFromString(xml_string): return atom.CreateClassFromXMLString(Commission, xml_string) class Price(_Monies): """The element.""" _tag = 'price' def PriceFromString(xml_string): return atom.CreateClassFromXMLString(Price, xml_string) class Symbol(atom.AtomBase): """The element.""" _tag = 'symbol' _namespace = GF_NAMESPACE _attributes = atom.AtomBase._attributes.copy() _attributes['fullName'] = 'full_name' _attributes['exchange'] = 'exchange' _attributes['symbol'] = 'symbol' def __init__(self, full_name=None, exchange=None, symbol=None, **kwargs): self.full_name = full_name self.exchange = exchange self.symbol = symbol atom.AtomBase.__init__(self, **kwargs) def __str__(self): return "%s:%s (%s)" % (self.exchange, self.symbol, self.full_name) def SymbolFromString(xml_string): return atom.CreateClassFromXMLString(Symbol, xml_string) class TransactionData(atom.AtomBase): """The element.""" _tag = 'transactionData' _namespace = GF_NAMESPACE _attributes = atom.AtomBase._attributes.copy() _attributes['type'] = 'type' _attributes['date'] = 'date' _attributes['shares'] = 'shares' _attributes['notes'] = 'notes' _children = atom.AtomBase._children.copy() _children['{%s}commission' % GF_NAMESPACE] = ('commission', Commission) _children['{%s}price' % GF_NAMESPACE] = ('price', Price) def __init__(self, type=None, date=None, shares=None, notes=None, commission=None, price=None, **kwargs): self.type = type self.date = date self.shares = shares self.notes = notes self.commission = commission self.price = price atom.AtomBase.__init__(self, **kwargs) def TransactionDataFromString(xml_string): return atom.CreateClassFromXMLString(TransactionData, xml_string) class TransactionEntry(gdata.GDataEntry): """An entry of the transaction feed. A TransactionEntry contains TransactionData such as the transaction type (Buy, Sell, Sell Short, or Buy to Cover), the number of units, the date, the price, any commission, and any notes. """ _tag = 'entry' _namespace = atom.ATOM_NAMESPACE _children = gdata.GDataEntry._children.copy() _children['{%s}transactionData' % GF_NAMESPACE] = ( 'transaction_data', TransactionData) def __init__(self, transaction_data=None, **kwargs): self.transaction_data = transaction_data gdata.GDataEntry.__init__(self, **kwargs) def transaction_id(self): return self.id.text.split("/")[-1] transaction_id = property(transaction_id, doc='The transaction ID.') def TransactionEntryFromString(xml_string): return atom.CreateClassFromXMLString(TransactionEntry, xml_string) class TransactionFeed(gdata.GDataFeed): """A feed that lists all of the transactions that have been recorded for a particular position. A transaction is a collection of information about an instance of buying or selling a particular security. The TransactionFeed lists all of the transactions that have been recorded for a particular position as a list of TransactionEntries. """ _tag = 'feed' _namespace = atom.ATOM_NAMESPACE _children = gdata.GDataFeed._children.copy() _children['{%s}entry' % atom.ATOM_NAMESPACE] = ('entry', [TransactionEntry]) def TransactionFeedFromString(xml_string): return atom.CreateClassFromXMLString(TransactionFeed, xml_string) class TransactionFeedLink(atom.AtomBase): """Link to TransactionFeed embedded in PositionEntry. If a PositionFeed is queried with transactions='true', TransactionFeeds are inlined in the returned PositionEntries. These TransactionFeeds are accessible via TransactionFeedLink's feed attribute. """ _tag = 'feedLink' _namespace = GD_NAMESPACE _attributes = atom.AtomBase._attributes.copy() _attributes['href'] = 'href' _children = atom.AtomBase._children.copy() _children['{%s}feed' % atom.ATOM_NAMESPACE] = ( 'feed', TransactionFeed) def __init__(self, href=None, feed=None, **kwargs): self.href = href self.feed = feed atom.AtomBase.__init__(self, **kwargs) class PositionData(atom.AtomBase): """The element.""" _tag = 'positionData' _namespace = GF_NAMESPACE _attributes = atom.AtomBase._attributes.copy() _attributes['gainPercentage'] = 'gain_percentage' _attributes['return1w'] = 'return1w' _attributes['return4w'] = 'return4w' _attributes['return3m'] = 'return3m' _attributes['returnYTD'] = 'returnYTD' _attributes['return1y'] = 'return1y' _attributes['return3y'] = 'return3y' _attributes['return5y'] = 'return5y' _attributes['returnOverall'] = 'return_overall' _attributes['shares'] = 'shares' _children = atom.AtomBase._children.copy() _children['{%s}costBasis' % GF_NAMESPACE] = ('cost_basis', CostBasis) _children['{%s}daysGain' % GF_NAMESPACE] = ('days_gain', DaysGain) _children['{%s}gain' % GF_NAMESPACE] = ('gain', Gain) _children['{%s}marketValue' % GF_NAMESPACE] = ('market_value', MarketValue) def __init__(self, gain_percentage=None, return1w=None, return4w=None, return3m=None, returnYTD=None, return1y=None, return3y=None, return5y=None, return_overall=None, shares=None, cost_basis=None, days_gain=None, gain=None, market_value=None, **kwargs): self.gain_percentage = gain_percentage self.return1w = return1w self.return4w = return4w self.return3m = return3m self.returnYTD = returnYTD self.return1y = return1y self.return3y = return3y self.return5y = return5y self.return_overall = return_overall self.shares = shares self.cost_basis = cost_basis self.days_gain = days_gain self.gain = gain self.market_value = market_value atom.AtomBase.__init__(self, **kwargs) def PositionDataFromString(xml_string): return atom.CreateClassFromXMLString(PositionData, xml_string) class PositionEntry(gdata.GDataEntry): """An entry of the position feed. A PositionEntry contains the ticker exchange and Symbol for a stock, mutual fund, or other security, along with PositionData such as the number of units of that security that the user holds, and performance statistics. """ _tag = 'entry' _namespace = atom.ATOM_NAMESPACE _children = gdata.GDataEntry._children.copy() _children['{%s}positionData' % GF_NAMESPACE] = ( 'position_data', PositionData) _children['{%s}symbol' % GF_NAMESPACE] = ('symbol', Symbol) _children['{%s}feedLink' % GD_NAMESPACE] = ( 'feed_link', TransactionFeedLink) def __init__(self, position_data=None, symbol=None, feed_link=None, **kwargs): self.position_data = position_data self.symbol = symbol self.feed_link = feed_link gdata.GDataEntry.__init__(self, **kwargs) def position_title(self): return self.title.text position_title = property(position_title, doc='The position title as a string (i.e. position.title.text).') def ticker_id(self): return self.id.text.split("/")[-1] ticker_id = property(ticker_id, doc='The position TICKER ID.') def transactions(self): if self.feed_link.feed: return self.feed_link.feed.entry else: return None transactions = property(transactions, doc=""" Inlined TransactionEntries are returned if PositionFeed is queried with transactions='true'.""") def PositionEntryFromString(xml_string): return atom.CreateClassFromXMLString(PositionEntry, xml_string) class PositionFeed(gdata.GDataFeed): """A feed that lists all of the positions in a particular portfolio. A position is a collection of information about a security that the user holds. The PositionFeed lists all of the positions in a particular portfolio as a list of PositionEntries. """ _tag = 'feed' _namespace = atom.ATOM_NAMESPACE _children = gdata.GDataFeed._children.copy() _children['{%s}entry' % atom.ATOM_NAMESPACE] = ('entry', [PositionEntry]) def PositionFeedFromString(xml_string): return atom.CreateClassFromXMLString(PositionFeed, xml_string) class PositionFeedLink(atom.AtomBase): """Link to PositionFeed embedded in PortfolioEntry. If a PortfolioFeed is queried with positions='true', the PositionFeeds are inlined in the returned PortfolioEntries. These PositionFeeds are accessible via PositionFeedLink's feed attribute. """ _tag = 'feedLink' _namespace = GD_NAMESPACE _attributes = atom.AtomBase._attributes.copy() _attributes['href'] = 'href' _children = atom.AtomBase._children.copy() _children['{%s}feed' % atom.ATOM_NAMESPACE] = ( 'feed', PositionFeed) def __init__(self, href=None, feed=None, **kwargs): self.href = href self.feed = feed atom.AtomBase.__init__(self, **kwargs) class PortfolioData(atom.AtomBase): """The element.""" _tag = 'portfolioData' _namespace = GF_NAMESPACE _attributes = atom.AtomBase._attributes.copy() _attributes['currencyCode'] = 'currency_code' _attributes['gainPercentage'] = 'gain_percentage' _attributes['return1w'] = 'return1w' _attributes['return4w'] = 'return4w' _attributes['return3m'] = 'return3m' _attributes['returnYTD'] = 'returnYTD' _attributes['return1y'] = 'return1y' _attributes['return3y'] = 'return3y' _attributes['return5y'] = 'return5y' _attributes['returnOverall'] = 'return_overall' _children = atom.AtomBase._children.copy() _children['{%s}costBasis' % GF_NAMESPACE] = ('cost_basis', CostBasis) _children['{%s}daysGain' % GF_NAMESPACE] = ('days_gain', DaysGain) _children['{%s}gain' % GF_NAMESPACE] = ('gain', Gain) _children['{%s}marketValue' % GF_NAMESPACE] = ('market_value', MarketValue) def __init__(self, currency_code=None, gain_percentage=None, return1w=None, return4w=None, return3m=None, returnYTD=None, return1y=None, return3y=None, return5y=None, return_overall=None, cost_basis=None, days_gain=None, gain=None, market_value=None, **kwargs): self.currency_code = currency_code self.gain_percentage = gain_percentage self.return1w = return1w self.return4w = return4w self.return3m = return3m self.returnYTD = returnYTD self.return1y = return1y self.return3y = return3y self.return5y = return5y self.return_overall = return_overall self.cost_basis = cost_basis self.days_gain = days_gain self.gain = gain self.market_value = market_value atom.AtomBase.__init__(self, **kwargs) def PortfolioDataFromString(xml_string): return atom.CreateClassFromXMLString(PortfolioData, xml_string) class PortfolioEntry(gdata.GDataEntry): """An entry of the PortfolioFeed. A PortfolioEntry contains the portfolio's title along with PortfolioData such as currency, total market value, and overall performance statistics. """ _tag = 'entry' _namespace = atom.ATOM_NAMESPACE _children = gdata.GDataEntry._children.copy() _children['{%s}portfolioData' % GF_NAMESPACE] = ( 'portfolio_data', PortfolioData) _children['{%s}feedLink' % GD_NAMESPACE] = ( 'feed_link', PositionFeedLink) def __init__(self, portfolio_data=None, feed_link=None, **kwargs): self.portfolio_data = portfolio_data self.feed_link = feed_link gdata.GDataEntry.__init__(self, **kwargs) def portfolio_title(self): return self.title.text def set_portfolio_title(self, portfolio_title): self.title = atom.Title(text=portfolio_title, title_type='text') portfolio_title = property(portfolio_title, set_portfolio_title, doc='The portfolio title as a string (i.e. portfolio.title.text).') def portfolio_id(self): return self.id.text.split("/")[-1] portfolio_id = property(portfolio_id, doc='The portfolio ID. Do not confuse with portfolio.id.') def positions(self): if self.feed_link.feed: return self.feed_link.feed.entry else: return None positions = property(positions, doc=""" Inlined PositionEntries are returned if PortfolioFeed was queried with positions='true'.""") def PortfolioEntryFromString(xml_string): return atom.CreateClassFromXMLString(PortfolioEntry, xml_string) class PortfolioFeed(gdata.GDataFeed): """A feed that lists all of the user's portfolios. A portfolio is a collection of positions that the user holds in various securities, plus metadata. The PortfolioFeed lists all of the user's portfolios as a list of PortfolioEntries. """ _tag = 'feed' _namespace = atom.ATOM_NAMESPACE _children = gdata.GDataFeed._children.copy() _children['{%s}entry' % atom.ATOM_NAMESPACE] = ('entry', [PortfolioEntry]) def PortfolioFeedFromString(xml_string): return atom.CreateClassFromXMLString(PortfolioFeed, xml_string)