faset over fra Z3950 til google books
This commit is contained in:
486
python/gdata/finance/__init__.py
Normal file
486
python/gdata/finance/__init__.py
Normal file
@@ -0,0 +1,486 @@
|
||||
#!/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 <gd:money> 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 <gd:money> 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 <gf:costBasis> element."""
|
||||
_tag = 'costBasis'
|
||||
|
||||
|
||||
def CostBasisFromString(xml_string):
|
||||
return atom.CreateClassFromXMLString(CostBasis, xml_string)
|
||||
|
||||
|
||||
class DaysGain(_Monies):
|
||||
"""The <gf:daysGain> element."""
|
||||
_tag = 'daysGain'
|
||||
|
||||
|
||||
def DaysGainFromString(xml_string):
|
||||
return atom.CreateClassFromXMLString(DaysGain, xml_string)
|
||||
|
||||
|
||||
class Gain(_Monies):
|
||||
"""The <gf:gain> element."""
|
||||
_tag = 'gain'
|
||||
|
||||
|
||||
def GainFromString(xml_string):
|
||||
return atom.CreateClassFromXMLString(Gain, xml_string)
|
||||
|
||||
|
||||
class MarketValue(_Monies):
|
||||
"""The <gf:marketValue> element."""
|
||||
_tag = 'gain'
|
||||
_tag = 'marketValue'
|
||||
|
||||
|
||||
def MarketValueFromString(xml_string):
|
||||
return atom.CreateClassFromXMLString(MarketValue, xml_string)
|
||||
|
||||
|
||||
class Commission(_Monies):
|
||||
"""The <gf:commission> element."""
|
||||
_tag = 'commission'
|
||||
|
||||
|
||||
def CommissionFromString(xml_string):
|
||||
return atom.CreateClassFromXMLString(Commission, xml_string)
|
||||
|
||||
|
||||
class Price(_Monies):
|
||||
"""The <gf:price> element."""
|
||||
_tag = 'price'
|
||||
|
||||
|
||||
def PriceFromString(xml_string):
|
||||
return atom.CreateClassFromXMLString(Price, xml_string)
|
||||
|
||||
|
||||
class Symbol(atom.AtomBase):
|
||||
"""The <gf:symbol> 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 <gf:transactionData> 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 <gf:positionData> 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 <gf:portfolioData> 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)
|
||||
|
||||
|
156
python/gdata/finance/data.py
Normal file
156
python/gdata/finance/data.py
Normal file
@@ -0,0 +1,156 @@
|
||||
#!/usr/bin/python
|
||||
#
|
||||
# Copyright (C) 2009 Google Inc.
|
||||
#
|
||||
# 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 the data classes of the Google Finance Portfolio Data API"""
|
||||
|
||||
|
||||
__author__ = 'j.s@google.com (Jeff Scudder)'
|
||||
|
||||
|
||||
import atom.core
|
||||
import atom.data
|
||||
import gdata.data
|
||||
import gdata.opensearch.data
|
||||
|
||||
|
||||
GF_TEMPLATE = '{http://schemas.google.com/finance/2007/}%s'
|
||||
|
||||
|
||||
class Commission(atom.core.XmlElement):
|
||||
"""Commission for the transaction"""
|
||||
_qname = GF_TEMPLATE % 'commission'
|
||||
money = [gdata.data.Money]
|
||||
|
||||
|
||||
class CostBasis(atom.core.XmlElement):
|
||||
"""Cost basis for the portfolio or position"""
|
||||
_qname = GF_TEMPLATE % 'costBasis'
|
||||
money = [gdata.data.Money]
|
||||
|
||||
|
||||
class DaysGain(atom.core.XmlElement):
|
||||
"""Today's gain for the portfolio or position"""
|
||||
_qname = GF_TEMPLATE % 'daysGain'
|
||||
money = [gdata.data.Money]
|
||||
|
||||
|
||||
class Gain(atom.core.XmlElement):
|
||||
"""Total gain for the portfolio or position"""
|
||||
_qname = GF_TEMPLATE % 'gain'
|
||||
money = [gdata.data.Money]
|
||||
|
||||
|
||||
class MarketValue(atom.core.XmlElement):
|
||||
"""Market value for the portfolio or position"""
|
||||
_qname = GF_TEMPLATE % 'marketValue'
|
||||
money = [gdata.data.Money]
|
||||
|
||||
|
||||
class PortfolioData(atom.core.XmlElement):
|
||||
"""Data for the portfolio"""
|
||||
_qname = GF_TEMPLATE % 'portfolioData'
|
||||
return_overall = 'returnOverall'
|
||||
currency_code = 'currencyCode'
|
||||
return3y = 'return3y'
|
||||
return4w = 'return4w'
|
||||
market_value = MarketValue
|
||||
return_y_t_d = 'returnYTD'
|
||||
cost_basis = CostBasis
|
||||
gain_percentage = 'gainPercentage'
|
||||
days_gain = DaysGain
|
||||
return3m = 'return3m'
|
||||
return5y = 'return5y'
|
||||
return1w = 'return1w'
|
||||
gain = Gain
|
||||
return1y = 'return1y'
|
||||
|
||||
|
||||
class PortfolioEntry(gdata.data.GDEntry):
|
||||
"""Describes an entry in a feed of Finance portfolios"""
|
||||
portfolio_data = PortfolioData
|
||||
|
||||
|
||||
class PortfolioFeed(gdata.data.GDFeed):
|
||||
"""Describes a Finance portfolio feed"""
|
||||
entry = [PortfolioEntry]
|
||||
|
||||
|
||||
class PositionData(atom.core.XmlElement):
|
||||
"""Data for the position"""
|
||||
_qname = GF_TEMPLATE % 'positionData'
|
||||
return_y_t_d = 'returnYTD'
|
||||
return5y = 'return5y'
|
||||
return_overall = 'returnOverall'
|
||||
cost_basis = CostBasis
|
||||
return3y = 'return3y'
|
||||
return1y = 'return1y'
|
||||
return4w = 'return4w'
|
||||
shares = 'shares'
|
||||
days_gain = DaysGain
|
||||
gain_percentage = 'gainPercentage'
|
||||
market_value = MarketValue
|
||||
gain = Gain
|
||||
return3m = 'return3m'
|
||||
return1w = 'return1w'
|
||||
|
||||
|
||||
class Price(atom.core.XmlElement):
|
||||
"""Price of the transaction"""
|
||||
_qname = GF_TEMPLATE % 'price'
|
||||
money = [gdata.data.Money]
|
||||
|
||||
|
||||
class Symbol(atom.core.XmlElement):
|
||||
"""Stock symbol for the company"""
|
||||
_qname = GF_TEMPLATE % 'symbol'
|
||||
symbol = 'symbol'
|
||||
exchange = 'exchange'
|
||||
full_name = 'fullName'
|
||||
|
||||
|
||||
class PositionEntry(gdata.data.GDEntry):
|
||||
"""Describes an entry in a feed of Finance positions"""
|
||||
symbol = Symbol
|
||||
position_data = PositionData
|
||||
|
||||
|
||||
class PositionFeed(gdata.data.GDFeed):
|
||||
"""Describes a Finance position feed"""
|
||||
entry = [PositionEntry]
|
||||
|
||||
|
||||
class TransactionData(atom.core.XmlElement):
|
||||
"""Data for the transction"""
|
||||
_qname = GF_TEMPLATE % 'transactionData'
|
||||
shares = 'shares'
|
||||
notes = 'notes'
|
||||
date = 'date'
|
||||
type = 'type'
|
||||
commission = Commission
|
||||
price = Price
|
||||
|
||||
|
||||
class TransactionEntry(gdata.data.GDEntry):
|
||||
"""Describes an entry in a feed of Finance transactions"""
|
||||
transaction_data = TransactionData
|
||||
|
||||
|
||||
class TransactionFeed(gdata.data.GDFeed):
|
||||
"""Describes a Finance transaction feed"""
|
||||
entry = [TransactionEntry]
|
||||
|
||||
|
243
python/gdata/finance/service.py
Normal file
243
python/gdata/finance/service.py
Normal file
@@ -0,0 +1,243 @@
|
||||
#!/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)
|
Reference in New Issue
Block a user