/gdata/finance/__init__.py

http://radioappz.googlecode.com/ · Python · 486 lines · 374 code · 67 blank · 45 comment · 5 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. """Contains extensions to Atom objects used with Google Finance."""
  17. __author__ = 'thesweeheng@gmail.com'
  18. import atom
  19. import gdata
  20. GD_NAMESPACE = 'http://schemas.google.com/g/2005'
  21. GF_NAMESPACE = 'http://schemas.google.com/finance/2007'
  22. class Money(atom.AtomBase):
  23. """The <gd:money> element."""
  24. _tag = 'money'
  25. _namespace = GD_NAMESPACE
  26. _attributes = atom.AtomBase._attributes.copy()
  27. _attributes['amount'] = 'amount'
  28. _attributes['currencyCode'] = 'currency_code'
  29. def __init__(self, amount=None, currency_code=None, **kwargs):
  30. self.amount = amount
  31. self.currency_code = currency_code
  32. atom.AtomBase.__init__(self, **kwargs)
  33. def __str__(self):
  34. return "%s %s" % (self.amount, self.currency_code)
  35. def MoneyFromString(xml_string):
  36. return atom.CreateClassFromXMLString(Money, xml_string)
  37. class _Monies(atom.AtomBase):
  38. """An element containing multiple <gd:money> in multiple currencies."""
  39. _namespace = GF_NAMESPACE
  40. _children = atom.AtomBase._children.copy()
  41. _children['{%s}money' % GD_NAMESPACE] = ('money', [Money])
  42. def __init__(self, money=None, **kwargs):
  43. self.money = money or []
  44. atom.AtomBase.__init__(self, **kwargs)
  45. def __str__(self):
  46. return " / ".join(["%s" % i for i in self.money])
  47. class CostBasis(_Monies):
  48. """The <gf:costBasis> element."""
  49. _tag = 'costBasis'
  50. def CostBasisFromString(xml_string):
  51. return atom.CreateClassFromXMLString(CostBasis, xml_string)
  52. class DaysGain(_Monies):
  53. """The <gf:daysGain> element."""
  54. _tag = 'daysGain'
  55. def DaysGainFromString(xml_string):
  56. return atom.CreateClassFromXMLString(DaysGain, xml_string)
  57. class Gain(_Monies):
  58. """The <gf:gain> element."""
  59. _tag = 'gain'
  60. def GainFromString(xml_string):
  61. return atom.CreateClassFromXMLString(Gain, xml_string)
  62. class MarketValue(_Monies):
  63. """The <gf:marketValue> element."""
  64. _tag = 'gain'
  65. _tag = 'marketValue'
  66. def MarketValueFromString(xml_string):
  67. return atom.CreateClassFromXMLString(MarketValue, xml_string)
  68. class Commission(_Monies):
  69. """The <gf:commission> element."""
  70. _tag = 'commission'
  71. def CommissionFromString(xml_string):
  72. return atom.CreateClassFromXMLString(Commission, xml_string)
  73. class Price(_Monies):
  74. """The <gf:price> element."""
  75. _tag = 'price'
  76. def PriceFromString(xml_string):
  77. return atom.CreateClassFromXMLString(Price, xml_string)
  78. class Symbol(atom.AtomBase):
  79. """The <gf:symbol> element."""
  80. _tag = 'symbol'
  81. _namespace = GF_NAMESPACE
  82. _attributes = atom.AtomBase._attributes.copy()
  83. _attributes['fullName'] = 'full_name'
  84. _attributes['exchange'] = 'exchange'
  85. _attributes['symbol'] = 'symbol'
  86. def __init__(self, full_name=None, exchange=None, symbol=None, **kwargs):
  87. self.full_name = full_name
  88. self.exchange = exchange
  89. self.symbol = symbol
  90. atom.AtomBase.__init__(self, **kwargs)
  91. def __str__(self):
  92. return "%s:%s (%s)" % (self.exchange, self.symbol, self.full_name)
  93. def SymbolFromString(xml_string):
  94. return atom.CreateClassFromXMLString(Symbol, xml_string)
  95. class TransactionData(atom.AtomBase):
  96. """The <gf:transactionData> element."""
  97. _tag = 'transactionData'
  98. _namespace = GF_NAMESPACE
  99. _attributes = atom.AtomBase._attributes.copy()
  100. _attributes['type'] = 'type'
  101. _attributes['date'] = 'date'
  102. _attributes['shares'] = 'shares'
  103. _attributes['notes'] = 'notes'
  104. _children = atom.AtomBase._children.copy()
  105. _children['{%s}commission' % GF_NAMESPACE] = ('commission', Commission)
  106. _children['{%s}price' % GF_NAMESPACE] = ('price', Price)
  107. def __init__(self, type=None, date=None, shares=None,
  108. notes=None, commission=None, price=None, **kwargs):
  109. self.type = type
  110. self.date = date
  111. self.shares = shares
  112. self.notes = notes
  113. self.commission = commission
  114. self.price = price
  115. atom.AtomBase.__init__(self, **kwargs)
  116. def TransactionDataFromString(xml_string):
  117. return atom.CreateClassFromXMLString(TransactionData, xml_string)
  118. class TransactionEntry(gdata.GDataEntry):
  119. """An entry of the transaction feed.
  120. A TransactionEntry contains TransactionData such as the transaction
  121. type (Buy, Sell, Sell Short, or Buy to Cover), the number of units,
  122. the date, the price, any commission, and any notes.
  123. """
  124. _tag = 'entry'
  125. _namespace = atom.ATOM_NAMESPACE
  126. _children = gdata.GDataEntry._children.copy()
  127. _children['{%s}transactionData' % GF_NAMESPACE] = (
  128. 'transaction_data', TransactionData)
  129. def __init__(self, transaction_data=None, **kwargs):
  130. self.transaction_data = transaction_data
  131. gdata.GDataEntry.__init__(self, **kwargs)
  132. def transaction_id(self):
  133. return self.id.text.split("/")[-1]
  134. transaction_id = property(transaction_id, doc='The transaction ID.')
  135. def TransactionEntryFromString(xml_string):
  136. return atom.CreateClassFromXMLString(TransactionEntry, xml_string)
  137. class TransactionFeed(gdata.GDataFeed):
  138. """A feed that lists all of the transactions that have been recorded for
  139. a particular position.
  140. A transaction is a collection of information about an instance of
  141. buying or selling a particular security. The TransactionFeed lists all
  142. of the transactions that have been recorded for a particular position
  143. as a list of TransactionEntries.
  144. """
  145. _tag = 'feed'
  146. _namespace = atom.ATOM_NAMESPACE
  147. _children = gdata.GDataFeed._children.copy()
  148. _children['{%s}entry' % atom.ATOM_NAMESPACE] = ('entry', [TransactionEntry])
  149. def TransactionFeedFromString(xml_string):
  150. return atom.CreateClassFromXMLString(TransactionFeed, xml_string)
  151. class TransactionFeedLink(atom.AtomBase):
  152. """Link to TransactionFeed embedded in PositionEntry.
  153. If a PositionFeed is queried with transactions='true', TransactionFeeds
  154. are inlined in the returned PositionEntries. These TransactionFeeds are
  155. accessible via TransactionFeedLink's feed attribute.
  156. """
  157. _tag = 'feedLink'
  158. _namespace = GD_NAMESPACE
  159. _attributes = atom.AtomBase._attributes.copy()
  160. _attributes['href'] = 'href'
  161. _children = atom.AtomBase._children.copy()
  162. _children['{%s}feed' % atom.ATOM_NAMESPACE] = (
  163. 'feed', TransactionFeed)
  164. def __init__(self, href=None, feed=None, **kwargs):
  165. self.href = href
  166. self.feed = feed
  167. atom.AtomBase.__init__(self, **kwargs)
  168. class PositionData(atom.AtomBase):
  169. """The <gf:positionData> element."""
  170. _tag = 'positionData'
  171. _namespace = GF_NAMESPACE
  172. _attributes = atom.AtomBase._attributes.copy()
  173. _attributes['gainPercentage'] = 'gain_percentage'
  174. _attributes['return1w'] = 'return1w'
  175. _attributes['return4w'] = 'return4w'
  176. _attributes['return3m'] = 'return3m'
  177. _attributes['returnYTD'] = 'returnYTD'
  178. _attributes['return1y'] = 'return1y'
  179. _attributes['return3y'] = 'return3y'
  180. _attributes['return5y'] = 'return5y'
  181. _attributes['returnOverall'] = 'return_overall'
  182. _attributes['shares'] = 'shares'
  183. _children = atom.AtomBase._children.copy()
  184. _children['{%s}costBasis' % GF_NAMESPACE] = ('cost_basis', CostBasis)
  185. _children['{%s}daysGain' % GF_NAMESPACE] = ('days_gain', DaysGain)
  186. _children['{%s}gain' % GF_NAMESPACE] = ('gain', Gain)
  187. _children['{%s}marketValue' % GF_NAMESPACE] = ('market_value', MarketValue)
  188. def __init__(self, gain_percentage=None,
  189. return1w=None, return4w=None, return3m=None, returnYTD=None,
  190. return1y=None, return3y=None, return5y=None, return_overall=None,
  191. shares=None, cost_basis=None, days_gain=None,
  192. gain=None, market_value=None, **kwargs):
  193. self.gain_percentage = gain_percentage
  194. self.return1w = return1w
  195. self.return4w = return4w
  196. self.return3m = return3m
  197. self.returnYTD = returnYTD
  198. self.return1y = return1y
  199. self.return3y = return3y
  200. self.return5y = return5y
  201. self.return_overall = return_overall
  202. self.shares = shares
  203. self.cost_basis = cost_basis
  204. self.days_gain = days_gain
  205. self.gain = gain
  206. self.market_value = market_value
  207. atom.AtomBase.__init__(self, **kwargs)
  208. def PositionDataFromString(xml_string):
  209. return atom.CreateClassFromXMLString(PositionData, xml_string)
  210. class PositionEntry(gdata.GDataEntry):
  211. """An entry of the position feed.
  212. A PositionEntry contains the ticker exchange and Symbol for a stock,
  213. mutual fund, or other security, along with PositionData such as the
  214. number of units of that security that the user holds, and performance
  215. statistics.
  216. """
  217. _tag = 'entry'
  218. _namespace = atom.ATOM_NAMESPACE
  219. _children = gdata.GDataEntry._children.copy()
  220. _children['{%s}positionData' % GF_NAMESPACE] = (
  221. 'position_data', PositionData)
  222. _children['{%s}symbol' % GF_NAMESPACE] = ('symbol', Symbol)
  223. _children['{%s}feedLink' % GD_NAMESPACE] = (
  224. 'feed_link', TransactionFeedLink)
  225. def __init__(self, position_data=None, symbol=None, feed_link=None,
  226. **kwargs):
  227. self.position_data = position_data
  228. self.symbol = symbol
  229. self.feed_link = feed_link
  230. gdata.GDataEntry.__init__(self, **kwargs)
  231. def position_title(self):
  232. return self.title.text
  233. position_title = property(position_title,
  234. doc='The position title as a string (i.e. position.title.text).')
  235. def ticker_id(self):
  236. return self.id.text.split("/")[-1]
  237. ticker_id = property(ticker_id, doc='The position TICKER ID.')
  238. def transactions(self):
  239. if self.feed_link.feed:
  240. return self.feed_link.feed.entry
  241. else:
  242. return None
  243. transactions = property(transactions, doc="""
  244. Inlined TransactionEntries are returned if PositionFeed is queried
  245. with transactions='true'.""")
  246. def PositionEntryFromString(xml_string):
  247. return atom.CreateClassFromXMLString(PositionEntry, xml_string)
  248. class PositionFeed(gdata.GDataFeed):
  249. """A feed that lists all of the positions in a particular portfolio.
  250. A position is a collection of information about a security that the
  251. user holds. The PositionFeed lists all of the positions in a particular
  252. portfolio as a list of PositionEntries.
  253. """
  254. _tag = 'feed'
  255. _namespace = atom.ATOM_NAMESPACE
  256. _children = gdata.GDataFeed._children.copy()
  257. _children['{%s}entry' % atom.ATOM_NAMESPACE] = ('entry', [PositionEntry])
  258. def PositionFeedFromString(xml_string):
  259. return atom.CreateClassFromXMLString(PositionFeed, xml_string)
  260. class PositionFeedLink(atom.AtomBase):
  261. """Link to PositionFeed embedded in PortfolioEntry.
  262. If a PortfolioFeed is queried with positions='true', the PositionFeeds
  263. are inlined in the returned PortfolioEntries. These PositionFeeds are
  264. accessible via PositionFeedLink's feed attribute.
  265. """
  266. _tag = 'feedLink'
  267. _namespace = GD_NAMESPACE
  268. _attributes = atom.AtomBase._attributes.copy()
  269. _attributes['href'] = 'href'
  270. _children = atom.AtomBase._children.copy()
  271. _children['{%s}feed' % atom.ATOM_NAMESPACE] = (
  272. 'feed', PositionFeed)
  273. def __init__(self, href=None, feed=None, **kwargs):
  274. self.href = href
  275. self.feed = feed
  276. atom.AtomBase.__init__(self, **kwargs)
  277. class PortfolioData(atom.AtomBase):
  278. """The <gf:portfolioData> element."""
  279. _tag = 'portfolioData'
  280. _namespace = GF_NAMESPACE
  281. _attributes = atom.AtomBase._attributes.copy()
  282. _attributes['currencyCode'] = 'currency_code'
  283. _attributes['gainPercentage'] = 'gain_percentage'
  284. _attributes['return1w'] = 'return1w'
  285. _attributes['return4w'] = 'return4w'
  286. _attributes['return3m'] = 'return3m'
  287. _attributes['returnYTD'] = 'returnYTD'
  288. _attributes['return1y'] = 'return1y'
  289. _attributes['return3y'] = 'return3y'
  290. _attributes['return5y'] = 'return5y'
  291. _attributes['returnOverall'] = 'return_overall'
  292. _children = atom.AtomBase._children.copy()
  293. _children['{%s}costBasis' % GF_NAMESPACE] = ('cost_basis', CostBasis)
  294. _children['{%s}daysGain' % GF_NAMESPACE] = ('days_gain', DaysGain)
  295. _children['{%s}gain' % GF_NAMESPACE] = ('gain', Gain)
  296. _children['{%s}marketValue' % GF_NAMESPACE] = ('market_value', MarketValue)
  297. def __init__(self, currency_code=None, gain_percentage=None,
  298. return1w=None, return4w=None, return3m=None, returnYTD=None,
  299. return1y=None, return3y=None, return5y=None, return_overall=None,
  300. cost_basis=None, days_gain=None, gain=None, market_value=None, **kwargs):
  301. self.currency_code = currency_code
  302. self.gain_percentage = gain_percentage
  303. self.return1w = return1w
  304. self.return4w = return4w
  305. self.return3m = return3m
  306. self.returnYTD = returnYTD
  307. self.return1y = return1y
  308. self.return3y = return3y
  309. self.return5y = return5y
  310. self.return_overall = return_overall
  311. self.cost_basis = cost_basis
  312. self.days_gain = days_gain
  313. self.gain = gain
  314. self.market_value = market_value
  315. atom.AtomBase.__init__(self, **kwargs)
  316. def PortfolioDataFromString(xml_string):
  317. return atom.CreateClassFromXMLString(PortfolioData, xml_string)
  318. class PortfolioEntry(gdata.GDataEntry):
  319. """An entry of the PortfolioFeed.
  320. A PortfolioEntry contains the portfolio's title along with PortfolioData
  321. such as currency, total market value, and overall performance statistics.
  322. """
  323. _tag = 'entry'
  324. _namespace = atom.ATOM_NAMESPACE
  325. _children = gdata.GDataEntry._children.copy()
  326. _children['{%s}portfolioData' % GF_NAMESPACE] = (
  327. 'portfolio_data', PortfolioData)
  328. _children['{%s}feedLink' % GD_NAMESPACE] = (
  329. 'feed_link', PositionFeedLink)
  330. def __init__(self, portfolio_data=None, feed_link=None, **kwargs):
  331. self.portfolio_data = portfolio_data
  332. self.feed_link = feed_link
  333. gdata.GDataEntry.__init__(self, **kwargs)
  334. def portfolio_title(self):
  335. return self.title.text
  336. def set_portfolio_title(self, portfolio_title):
  337. self.title = atom.Title(text=portfolio_title, title_type='text')
  338. portfolio_title = property(portfolio_title, set_portfolio_title,
  339. doc='The portfolio title as a string (i.e. portfolio.title.text).')
  340. def portfolio_id(self):
  341. return self.id.text.split("/")[-1]
  342. portfolio_id = property(portfolio_id,
  343. doc='The portfolio ID. Do not confuse with portfolio.id.')
  344. def positions(self):
  345. if self.feed_link.feed:
  346. return self.feed_link.feed.entry
  347. else:
  348. return None
  349. positions = property(positions, doc="""
  350. Inlined PositionEntries are returned if PortfolioFeed was queried
  351. with positions='true'.""")
  352. def PortfolioEntryFromString(xml_string):
  353. return atom.CreateClassFromXMLString(PortfolioEntry, xml_string)
  354. class PortfolioFeed(gdata.GDataFeed):
  355. """A feed that lists all of the user's portfolios.
  356. A portfolio is a collection of positions that the user holds in various
  357. securities, plus metadata. The PortfolioFeed lists all of the user's
  358. portfolios as a list of PortfolioEntries.
  359. """
  360. _tag = 'feed'
  361. _namespace = atom.ATOM_NAMESPACE
  362. _children = gdata.GDataFeed._children.copy()
  363. _children['{%s}entry' % atom.ATOM_NAMESPACE] = ('entry', [PortfolioEntry])
  364. def PortfolioFeedFromString(xml_string):
  365. return atom.CreateClassFromXMLString(PortfolioFeed, xml_string)