PageRenderTime 55ms CodeModel.GetById 16ms app.highlight 26ms RepoModel.GetById 1ms app.codeStats 1ms

/gdata/finance/__init__.py

http://radioappz.googlecode.com/
Python | 486 lines | 374 code | 67 blank | 45 comment | 6 complexity | 3d08db094fecd0ab49acfa8f4fa426b9 MD5 | raw file
  1#!/usr/bin/python
  2#
  3# Copyright (C) 2009 Tan Swee Heng
  4#
  5# Licensed under the Apache License, Version 2.0 (the "License");
  6# you may not use this file except in compliance with the License.
  7# You may obtain a copy of the License at
  8#
  9#      http://www.apache.org/licenses/LICENSE-2.0
 10#
 11# Unless required by applicable law or agreed to in writing, software
 12# distributed under the License is distributed on an "AS IS" BASIS,
 13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 14# See the License for the specific language governing permissions and
 15# limitations under the License.
 16
 17
 18"""Contains extensions to Atom objects used with Google Finance."""
 19
 20
 21__author__ = 'thesweeheng@gmail.com'
 22
 23
 24import atom
 25import gdata
 26
 27
 28GD_NAMESPACE = 'http://schemas.google.com/g/2005'
 29GF_NAMESPACE = 'http://schemas.google.com/finance/2007'
 30
 31
 32class Money(atom.AtomBase):
 33  """The <gd:money> element."""
 34  _tag = 'money'
 35  _namespace = GD_NAMESPACE
 36  _attributes = atom.AtomBase._attributes.copy()
 37  _attributes['amount'] = 'amount'
 38  _attributes['currencyCode'] = 'currency_code'
 39  
 40  def __init__(self, amount=None, currency_code=None, **kwargs):
 41    self.amount = amount
 42    self.currency_code = currency_code
 43    atom.AtomBase.__init__(self, **kwargs)
 44
 45  def __str__(self):
 46    return "%s %s" % (self.amount, self.currency_code)
 47
 48
 49def MoneyFromString(xml_string):
 50  return atom.CreateClassFromXMLString(Money, xml_string)
 51
 52
 53class _Monies(atom.AtomBase):
 54  """An element containing multiple <gd:money> in multiple currencies."""
 55  _namespace = GF_NAMESPACE
 56  _children = atom.AtomBase._children.copy()
 57  _children['{%s}money' % GD_NAMESPACE] = ('money', [Money])
 58  
 59  def __init__(self, money=None, **kwargs):
 60    self.money = money or []
 61    atom.AtomBase.__init__(self, **kwargs)
 62
 63  def __str__(self):
 64    return " / ".join(["%s" % i for i in self.money])
 65
 66
 67class CostBasis(_Monies):
 68  """The <gf:costBasis> element."""
 69  _tag = 'costBasis'
 70
 71
 72def CostBasisFromString(xml_string):
 73  return atom.CreateClassFromXMLString(CostBasis, xml_string)
 74
 75
 76class DaysGain(_Monies):
 77  """The <gf:daysGain> element."""
 78  _tag = 'daysGain'
 79
 80
 81def DaysGainFromString(xml_string):
 82  return atom.CreateClassFromXMLString(DaysGain, xml_string)
 83
 84
 85class Gain(_Monies):
 86  """The <gf:gain> element."""
 87  _tag = 'gain'
 88
 89
 90def GainFromString(xml_string):
 91  return atom.CreateClassFromXMLString(Gain, xml_string)
 92
 93
 94class MarketValue(_Monies):
 95  """The <gf:marketValue> element."""
 96  _tag = 'gain'
 97  _tag = 'marketValue'
 98
 99
100def MarketValueFromString(xml_string):
101  return atom.CreateClassFromXMLString(MarketValue, xml_string)
102
103
104class Commission(_Monies):
105  """The <gf:commission> element."""
106  _tag = 'commission'
107
108
109def CommissionFromString(xml_string):
110  return atom.CreateClassFromXMLString(Commission, xml_string)
111
112
113class Price(_Monies):
114  """The <gf:price> element."""
115  _tag = 'price'
116
117
118def PriceFromString(xml_string):
119  return atom.CreateClassFromXMLString(Price, xml_string)
120
121
122class Symbol(atom.AtomBase):
123  """The <gf:symbol> element."""
124  _tag = 'symbol'
125  _namespace = GF_NAMESPACE
126  _attributes = atom.AtomBase._attributes.copy()
127  _attributes['fullName'] = 'full_name'
128  _attributes['exchange'] = 'exchange'
129  _attributes['symbol'] = 'symbol'
130  
131  def __init__(self, full_name=None, exchange=None, symbol=None, **kwargs):
132    self.full_name = full_name
133    self.exchange = exchange
134    self.symbol = symbol
135    atom.AtomBase.__init__(self, **kwargs)
136
137  def __str__(self):
138    return "%s:%s (%s)" % (self.exchange, self.symbol, self.full_name)
139
140
141def SymbolFromString(xml_string):
142  return atom.CreateClassFromXMLString(Symbol, xml_string)
143
144
145class TransactionData(atom.AtomBase):
146  """The <gf:transactionData> element."""
147  _tag = 'transactionData'
148  _namespace = GF_NAMESPACE
149  _attributes = atom.AtomBase._attributes.copy()
150  _attributes['type'] = 'type'
151  _attributes['date'] = 'date'
152  _attributes['shares'] = 'shares'
153  _attributes['notes'] = 'notes'
154  _children = atom.AtomBase._children.copy()
155  _children['{%s}commission' % GF_NAMESPACE] = ('commission', Commission)
156  _children['{%s}price' % GF_NAMESPACE] = ('price', Price)
157
158  def __init__(self, type=None, date=None, shares=None,
159      notes=None, commission=None, price=None, **kwargs):
160    self.type = type 
161    self.date = date
162    self.shares = shares
163    self.notes = notes
164    self.commission = commission
165    self.price = price
166    atom.AtomBase.__init__(self, **kwargs)
167
168
169def TransactionDataFromString(xml_string):
170  return atom.CreateClassFromXMLString(TransactionData, xml_string)
171
172
173class TransactionEntry(gdata.GDataEntry):
174  """An entry of the transaction feed.
175
176  A TransactionEntry contains TransactionData such as the transaction
177  type (Buy,  Sell,  Sell Short, or  Buy to Cover), the number of units,
178  the date, the price, any commission, and any notes.
179  """
180  _tag = 'entry'
181  _namespace = atom.ATOM_NAMESPACE
182  _children = gdata.GDataEntry._children.copy() 
183  _children['{%s}transactionData' % GF_NAMESPACE] = (
184      'transaction_data', TransactionData)
185
186  def __init__(self, transaction_data=None, **kwargs):
187    self.transaction_data = transaction_data
188    gdata.GDataEntry.__init__(self, **kwargs)
189
190  def transaction_id(self):
191    return self.id.text.split("/")[-1]
192
193  transaction_id = property(transaction_id, doc='The transaction ID.')
194
195
196def TransactionEntryFromString(xml_string):
197  return atom.CreateClassFromXMLString(TransactionEntry, xml_string)
198
199
200class TransactionFeed(gdata.GDataFeed):
201  """A feed that lists all of the transactions that have been recorded for
202  a particular position.
203  
204  A transaction is a collection of information about an instance of
205  buying or selling a particular security. The TransactionFeed lists all
206  of the transactions that have been recorded for a particular position
207  as a list of TransactionEntries.
208  """
209  _tag = 'feed'
210  _namespace = atom.ATOM_NAMESPACE
211  _children = gdata.GDataFeed._children.copy()
212  _children['{%s}entry' % atom.ATOM_NAMESPACE] = ('entry', [TransactionEntry])
213
214
215def TransactionFeedFromString(xml_string):
216  return atom.CreateClassFromXMLString(TransactionFeed, xml_string)
217
218
219class TransactionFeedLink(atom.AtomBase):
220  """Link to TransactionFeed embedded in PositionEntry.
221
222  If a PositionFeed is queried with transactions='true', TransactionFeeds
223  are inlined in the returned PositionEntries. These TransactionFeeds are
224  accessible via TransactionFeedLink's feed attribute.
225  """
226  _tag = 'feedLink'
227  _namespace = GD_NAMESPACE
228  _attributes = atom.AtomBase._attributes.copy()
229  _attributes['href'] = 'href'
230  _children = atom.AtomBase._children.copy() 
231  _children['{%s}feed' % atom.ATOM_NAMESPACE] = (
232      'feed', TransactionFeed)
233
234  def __init__(self, href=None, feed=None, **kwargs):
235    self.href = href
236    self.feed = feed
237    atom.AtomBase.__init__(self, **kwargs)
238
239
240class PositionData(atom.AtomBase):
241  """The <gf:positionData> element."""
242  _tag = 'positionData'
243  _namespace = GF_NAMESPACE
244  _attributes = atom.AtomBase._attributes.copy()
245  _attributes['gainPercentage'] = 'gain_percentage'
246  _attributes['return1w'] = 'return1w'
247  _attributes['return4w'] = 'return4w'
248  _attributes['return3m'] = 'return3m'
249  _attributes['returnYTD'] = 'returnYTD'
250  _attributes['return1y'] = 'return1y'
251  _attributes['return3y'] = 'return3y'
252  _attributes['return5y'] = 'return5y'
253  _attributes['returnOverall'] = 'return_overall'
254  _attributes['shares'] = 'shares'
255  _children = atom.AtomBase._children.copy()
256  _children['{%s}costBasis' % GF_NAMESPACE] = ('cost_basis', CostBasis)
257  _children['{%s}daysGain' % GF_NAMESPACE] = ('days_gain', DaysGain)
258  _children['{%s}gain' % GF_NAMESPACE] = ('gain', Gain)
259  _children['{%s}marketValue' % GF_NAMESPACE] = ('market_value', MarketValue)
260
261  def __init__(self, gain_percentage=None,
262      return1w=None, return4w=None, return3m=None, returnYTD=None,
263      return1y=None, return3y=None, return5y=None, return_overall=None,
264      shares=None, cost_basis=None, days_gain=None,
265      gain=None, market_value=None, **kwargs):
266    self.gain_percentage = gain_percentage
267    self.return1w = return1w
268    self.return4w = return4w
269    self.return3m = return3m
270    self.returnYTD = returnYTD
271    self.return1y = return1y
272    self.return3y = return3y
273    self.return5y = return5y
274    self.return_overall = return_overall
275    self.shares = shares
276    self.cost_basis = cost_basis
277    self.days_gain = days_gain
278    self.gain = gain
279    self.market_value = market_value
280    atom.AtomBase.__init__(self, **kwargs)
281
282
283def PositionDataFromString(xml_string):
284  return atom.CreateClassFromXMLString(PositionData, xml_string)
285
286
287class PositionEntry(gdata.GDataEntry):
288  """An entry of the position feed.
289
290  A PositionEntry contains the ticker exchange and Symbol for a stock,
291  mutual fund, or other security, along with PositionData such as the
292  number of units of that security that the user holds, and performance
293  statistics.
294  """
295  _tag = 'entry'
296  _namespace = atom.ATOM_NAMESPACE
297  _children = gdata.GDataEntry._children.copy() 
298  _children['{%s}positionData' % GF_NAMESPACE] = (
299      'position_data', PositionData)
300  _children['{%s}symbol' % GF_NAMESPACE] = ('symbol', Symbol)
301  _children['{%s}feedLink' % GD_NAMESPACE] = (
302    'feed_link', TransactionFeedLink)
303
304  def __init__(self, position_data=None, symbol=None, feed_link=None,
305      **kwargs):
306    self.position_data = position_data
307    self.symbol = symbol
308    self.feed_link = feed_link
309    gdata.GDataEntry.__init__(self, **kwargs)
310
311  def position_title(self):
312    return self.title.text
313
314  position_title = property(position_title,
315    doc='The position title as a string (i.e. position.title.text).')
316
317  def ticker_id(self):
318    return self.id.text.split("/")[-1]
319
320  ticker_id = property(ticker_id, doc='The position TICKER ID.')
321
322  def transactions(self):
323    if self.feed_link.feed:
324      return self.feed_link.feed.entry
325    else:
326      return None
327
328  transactions = property(transactions, doc="""
329      Inlined TransactionEntries are returned if PositionFeed is queried
330      with transactions='true'.""")
331
332
333def PositionEntryFromString(xml_string):
334  return atom.CreateClassFromXMLString(PositionEntry, xml_string)
335
336
337class PositionFeed(gdata.GDataFeed):
338  """A feed that lists all of the positions in a particular portfolio.
339
340  A position is a collection of information about a security that the
341  user holds. The PositionFeed lists all of the positions in a particular
342  portfolio as a list of PositionEntries.
343  """
344  _tag = 'feed'
345  _namespace = atom.ATOM_NAMESPACE
346  _children = gdata.GDataFeed._children.copy()
347  _children['{%s}entry' % atom.ATOM_NAMESPACE] = ('entry', [PositionEntry])
348
349
350def PositionFeedFromString(xml_string):
351  return atom.CreateClassFromXMLString(PositionFeed, xml_string)
352
353
354class PositionFeedLink(atom.AtomBase):
355  """Link to PositionFeed embedded in PortfolioEntry.
356
357  If a PortfolioFeed is queried with positions='true', the PositionFeeds
358  are inlined in the returned PortfolioEntries. These PositionFeeds are
359  accessible via PositionFeedLink's feed attribute.
360  """
361  _tag = 'feedLink'
362  _namespace = GD_NAMESPACE
363  _attributes = atom.AtomBase._attributes.copy()
364  _attributes['href'] = 'href'
365  _children = atom.AtomBase._children.copy() 
366  _children['{%s}feed' % atom.ATOM_NAMESPACE] = (
367      'feed', PositionFeed)
368
369  def __init__(self, href=None, feed=None, **kwargs):
370    self.href = href
371    self.feed = feed
372    atom.AtomBase.__init__(self, **kwargs)
373
374
375class PortfolioData(atom.AtomBase):
376  """The <gf:portfolioData> element."""
377  _tag = 'portfolioData'
378  _namespace = GF_NAMESPACE
379  _attributes = atom.AtomBase._attributes.copy()
380  _attributes['currencyCode'] = 'currency_code'
381  _attributes['gainPercentage'] = 'gain_percentage'
382  _attributes['return1w'] = 'return1w'
383  _attributes['return4w'] = 'return4w'
384  _attributes['return3m'] = 'return3m'
385  _attributes['returnYTD'] = 'returnYTD'
386  _attributes['return1y'] = 'return1y'
387  _attributes['return3y'] = 'return3y'
388  _attributes['return5y'] = 'return5y'
389  _attributes['returnOverall'] = 'return_overall'
390  _children = atom.AtomBase._children.copy()
391  _children['{%s}costBasis' % GF_NAMESPACE] = ('cost_basis', CostBasis)
392  _children['{%s}daysGain' % GF_NAMESPACE] = ('days_gain', DaysGain)
393  _children['{%s}gain' % GF_NAMESPACE] = ('gain', Gain)
394  _children['{%s}marketValue' % GF_NAMESPACE] = ('market_value', MarketValue)
395
396  def __init__(self, currency_code=None, gain_percentage=None,
397      return1w=None, return4w=None, return3m=None, returnYTD=None,
398      return1y=None, return3y=None, return5y=None, return_overall=None,
399      cost_basis=None, days_gain=None, gain=None, market_value=None, **kwargs):
400    self.currency_code = currency_code
401    self.gain_percentage = gain_percentage
402    self.return1w = return1w
403    self.return4w = return4w
404    self.return3m = return3m
405    self.returnYTD = returnYTD
406    self.return1y = return1y
407    self.return3y = return3y
408    self.return5y = return5y
409    self.return_overall = return_overall
410    self.cost_basis = cost_basis
411    self.days_gain = days_gain
412    self.gain = gain
413    self.market_value = market_value
414    atom.AtomBase.__init__(self, **kwargs)
415
416
417def PortfolioDataFromString(xml_string):
418  return atom.CreateClassFromXMLString(PortfolioData, xml_string)
419
420
421class PortfolioEntry(gdata.GDataEntry):
422  """An entry of the PortfolioFeed.
423
424  A PortfolioEntry contains the portfolio's title along with PortfolioData
425  such as currency, total market value, and overall performance statistics.
426  """
427  _tag = 'entry'
428  _namespace = atom.ATOM_NAMESPACE
429  _children = gdata.GDataEntry._children.copy() 
430  _children['{%s}portfolioData' % GF_NAMESPACE] = (
431      'portfolio_data', PortfolioData)
432  _children['{%s}feedLink' % GD_NAMESPACE] = (
433    'feed_link', PositionFeedLink)
434
435  def __init__(self, portfolio_data=None, feed_link=None, **kwargs):
436    self.portfolio_data = portfolio_data
437    self.feed_link = feed_link
438    gdata.GDataEntry.__init__(self, **kwargs)
439
440  def portfolio_title(self):
441    return self.title.text
442
443  def set_portfolio_title(self, portfolio_title):
444    self.title = atom.Title(text=portfolio_title, title_type='text')
445
446  portfolio_title = property(portfolio_title,  set_portfolio_title,
447      doc='The portfolio title as a string (i.e. portfolio.title.text).')
448
449  def portfolio_id(self):
450    return self.id.text.split("/")[-1]
451
452  portfolio_id = property(portfolio_id,
453      doc='The portfolio ID. Do not confuse with portfolio.id.')
454
455  def positions(self):
456    if self.feed_link.feed:
457      return self.feed_link.feed.entry
458    else:
459      return None
460
461  positions = property(positions, doc="""
462      Inlined PositionEntries are returned if PortfolioFeed was queried
463      with positions='true'.""")
464
465
466def PortfolioEntryFromString(xml_string):
467  return atom.CreateClassFromXMLString(PortfolioEntry, xml_string)
468
469    
470class PortfolioFeed(gdata.GDataFeed):
471  """A feed that lists all of the user's portfolios.
472
473  A portfolio is a collection of positions that the user holds in various
474  securities, plus metadata. The PortfolioFeed lists all of the user's
475  portfolios as a list of PortfolioEntries.
476  """
477  _tag = 'feed'
478  _namespace = atom.ATOM_NAMESPACE
479  _children = gdata.GDataFeed._children.copy()
480  _children['{%s}entry' % atom.ATOM_NAMESPACE] = ('entry', [PortfolioEntry])
481
482
483def PortfolioFeedFromString(xml_string):
484  return atom.CreateClassFromXMLString(PortfolioFeed, xml_string)
485
486