/gdata/finance/__init__.py
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