Copyright (C) 2010 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. Service details and instances for the Finance service.
Some use cases: Create portfolio: finance create --title "Some Portfolio" --currency USD
Delete portfolio: finance delete --title "Some Portfolio"
List portfolios: finance list
Create position: finance create-pos --title "Some Portfolio" --ticker NYSE:PCLN
Delete position: finance delete-pos --title "Some Portfolio" --ticker NYSE:PCLN
List positions: finance list-pos --title "Some Portfolio"
Create transaction: finance create-txn --title "Some Portfolio" --ticker NASDAQ:PCLN --currency USD --ttype Sell --price 346.60 --commission 7.7 --shares 60 --date 2010-09-24 --notes "Stop loss on 347.01"
Delete transaction: finance delete-txn --title "Some Portfolio" --ticker NASDAQ:PCLN --txnid 4
List transactions: finance list-txn --title "Some Portfolio" --ticker NASDAQ:PCLN
__author__ = 'bartosh@gmail.com (Ed Bartosh)'
import logging
import datetime
import googlecl
import googlecl.calendar.date
from googlecl.base import BaseCL
from googlecl.service import BaseServiceCL
from googlecl.finance import SECTION_HEADER
from gdata.service import RequestError
from gdata.finance.service import FinanceService, PortfolioQuery, PositionQuery
from gdata.finance import PortfolioData, PortfolioEntry, TransactionEntry, \
TransactionData, Money, Price, Commission, \
PortfolioFeedFromString
LOG = logging.getLogger(googlecl.finance.LOGGER_NAME)
Extends gdata.photos.service.FinanceService for the command line.
class FinanceServiceCL(FinanceService, BaseServiceCL):
This class adds some features focused on using Finance via an installed app with a command line interface.
Constructor.
def __init__(self, config):
FinanceService.__init__(self)
BaseServiceCL.__init__(self, SECTION_HEADER, config)
self.max_results = None
Creates a portfolio.
def create_portfolio(self, title, currency):
Args: title: Title to give the portfolio. currency: Currency associated with the portfolio (e.g. USD)
pfl = PortfolioEntry(
portfolio_data=PortfolioData(currency_code=currency))
pfl.portfolio_title = title
try:
return self.AddPortfolio(pfl)
except RequestError, err:
LOG.error('Failed to create portfolio: %s' % err[0]['body'])
CreatePortfolio = create_portfolio
Check that the token being used is valid.
def is_token_valid(self, test_uri='/data/feed/api/user/default'):
return BaseCL.IsTokenValid(self, test_uri)
IsTokenValid = is_token_valid
Get portfolio entries or one entry.
def get_portfolio_entries(self, title=None, returns=False, positions=False,
multiple=True):
Args: title: string, portfolio title, could be regexp. returns: [optional] boolean, include returns into the result. positions: [optional] boolean, include positions into the result. multiple: boolean, return multiple entries if True Returns: list of portfolio entries
query = PortfolioQuery()
query.returns = returns
query.positions = positions
uri = "/finance/feeds/default/portfolios/" + query.ToUri()
if multiple:
return self.GetEntries(uri, titles=title,
converter=PortfolioFeedFromString)
else:
entry = self.GetSingleEntry(uri, title=title,
converter=PortfolioFeedFromString)
if entry:
return [entry]
else:
return []
Get portfolio by title.
def get_portfolio(self, title, returns=False, positions=False):
Args: title: string, portfolio title. returns: [optional] boolean, include returns into the result. positions: [optional] boolean, include positions into the result.
Returns: portfolio feed object or None if not found.
entries = self.get_portfolio_entries(title=title, returns=returns,
positions=positions, multiple=False)
if entries:
return entries[0]
else:
LOG.info('Portfolio "%s" not found' % title)
return None
Get positions in a portfolio.
def get_positions(self, portfolio_title, ticker_id=None,
include_returns=False):
Args: portfolio_title: Title of the portfolio. ticker_id: Ticker, e.g. "NYSE:GLD" include_returns: Include returns in the portfolio data. Default False.
Returns: List of positions in the portfolio, or empty list if no positions found matching the criteria.
XXX:Would be nice to differentiate between positions. Right now, just get all of them.
pfl = self.get_portfolio(portfolio_title, returns=include_returns,
positions=True)
if not pfl:
LOG.debug('No portfolio to get positions from!')
return []
if not pfl.positions:
LOG.debug('No positions found in this portfolio.')
return []
if ticker_id is not None:
positions = [self.GetPosition(portfolio_id=pfl.portfolio_id,
ticker_id=ticker_id)]
else:
positions = self.GetPositionFeed(portfolio_entry=pfl).entry
return positions
def get_transactions(self, portfolio_title, ticker_id, transaction_id=None):
pfl = self.get_portfolio(portfolio_title)
if not pfl:
LOG.debug('No portfolio to get transactions from!')
return []
if transaction_id:
transactions = [self.GetTransaction(portfolio_id=pfl.portfolio_id,
ticker_id=ticker_id,
transaction_id=transaction_id)]
else:
transactions = self.GetTransactionFeed(portfolio_id=pfl.portfolio_id,
ticker_id=ticker_id).entry
return transactions
Create transaction.
def create_transaction(self, pfl, ttype, ticker, shares=None, price=None,
currency=None, commission=None, date='', notes=None):
Args: pfl: portfolio object. ttype: string, transaction type, on of the 'Buy', 'Sell', 'Short Sell', 'Buy to Cover'. shares: [optional] decimal, amount of shares. price: [optional] decimal, price of the share. currency: [optional] string, portfolio currency by default. commission: [optional] decimal, brocker commission. date: [optional] string, transaction date, datetime.now() by default. notes: [optional] string, notes.
Returns: None if transaction created successfully, otherwise error string.
if not currency:
currency = pfl.portfolio_data.currency_code
if date is None:
if date is not provided from the command line current date is set
date = datetime.datetime.now().isoformat()
elif date is '':
special case for create position task. date should be set to None to create empty transaction. See detailed explanations in the _run_create_position function below
date = None
else:
parser = googlecl.calendar.date.DateParser()
date = parser.parse(date).local.isoformat()
if price is not None:
price = Price(money=[Money(amount=price, currency_code=currency)])
if commission is not None:
commission = Commission(money=[Money(amount=commission,
currency_code=currency)])
txn = TransactionEntry(transaction_data=TransactionData(
type=ttype, price=price, shares=shares, commission=commission,
date=date, notes=notes))
try:
return self.AddTransaction(txn, portfolio_id=pfl.portfolio_id,
ticker_id=ticker)
except RequestError, err:
LOG.error('Failed to create transaction: %s' % err[0]['body'])
SERVICE_CLASS = FinanceServiceCL
Local Variables: mode: python py-indent-offset: 2 indent-tabs-mode: nil tab-width: 2 End: