Difference between revisions of "Importing fund or stock prices from an OFX file"

From GnuCash
Jump to: navigation, search
Line 1: Line 1:
 
How to Import Fund or Stock Prices From an OFX File
 
How to Import Fund or Stock Prices From an OFX File
  
The attached python script show how to import prices from an OFX file.  I borrowed heavily from work done by [http://wiki.gnucash.org/wiki/Stocks/get_prices Peter Holtermann] and others (price_database_example.py in src/optional/python-bindings/example_scripts).  The read from OFX tool has only been tested on files from 1 source, so be wary.
+
The attached python script show how to import prices from an OFX file.  This was useful for me because my 401k funds are not publicly traded so the norm import prices tool doesn't work. The OFX file has prices in the <INVPOS> aggregate.  I borrowed heavily from work done by [http://wiki.gnucash.org/wiki/Stocks/get_prices Peter Holtermann] and others (price_database_example.py in src/optional/python-bindings/example_scripts).   
  
 +
Attached are 2 python scripts.  getPrices.py reads the OFX file and outputs a CSV file in this format:
 +
fundName, date, price.  The date looks like this:  20110118120000, year month day time.  I suggest you try this standalone 1st and see if it works for your OFX file.
 +
 +
The other file, importPrice.py calls getPrices.py and uses the python bindings to update the price database in GC.
 +
 +
Another very useful tool is ofx.py, found at [http://www.jongsma.org/gc/  http://www.jongsma.org/gc/].  I use this to download the OFX file.
 +
 +
---- getPrices.py ----
 
<pre>
 
<pre>
 
#!/usr/bin/python
 
#!/usr/bin/python
# usage: getPrices ofxfile outfile
+
# usage: getPrices.py ofxfile outfile
 
# Read an OFX w/ an INVPOS aggregate and write the prices
 
# Read an OFX w/ an INVPOS aggregate and write the prices
 
# to a CSV file
 
# to a CSV file
Line 53: Line 61:
 
             inlist=0
 
             inlist=0
 
          
 
          
 +
<\pre>
 +
 +
---- importPrice.py ---
 +
<pre>
 +
#!/usr/bin/python
 +
# Usage: importPrice.py ofxfile gcfile
 +
# Import prices from an OFX file into Gnucash
 +
 +
# Configuration Options
 +
cur_mnemonic="USD"
 +
namespace_name = "401k"
 +
 +
from gnucash import Session, Account, Split
 +
import gnucash
 +
import datetime
 +
import sys
 +
import os
 +
 +
ofxfile = sys.argv[1]
 +
gcfile = sys.argv[2]
 +
pricefile = 'pq.csv'
 +
 +
# Could call ofx.py here (see http://www.jongsma.org/gc/)
 +
# ofx.py site user account
 +
 +
# get the prices from the ofx file
 +
os.system('getPrices.py %s %s' % (ofxfile, pricefile) )
 +
 +
url = "xml://"+gcfile
 +
 +
# Read input data from file
 +
f = open(pricefile)
 +
data = []
 +
while 1:
 +
    tmp = f.readline()
 +
    if(len(tmp)<2):
 +
        break
 +
   
 +
    data.append(tmp)
 +
 +
f.close()
 +
 +
stock_date = []
 +
stock_price = []
 +
stock = []
 +
for i in range(len(data)):
 +
    date = data[i].rsplit(',')[1].lstrip()
 +
    year = int(date[0:4])
 +
    month = int(date[4:6])
 +
    day = int(date[6:8])
 +
    stock_date.append(datetime.datetime(year,month,day))
 +
    stock_price.append(float(data[i].rsplit(',')[2]))
 +
    stock.append(data[i].rsplit(',')[0])
 +
   
 +
 +
# Initialize Gnucash session
 +
session = Session(url, True, False, False)
 +
book = session.book
 +
pdb = book.get_price_db()
 +
comm_table = book.get_table()
 +
cur = comm_table.lookup("CURRENCY", cur_mnemonic)
 +
 +
commodities=comm_table.get_commodities(namespace_name)
 +
 +
for ii, stocki in enumerate(stock):
 +
  # find the commodity cusip that matches
 +
  for cmdt in commodities:
 +
    if cmdt.get_cusip() == stocki:
 +
     
 +
      # Get stock data
 +
      pl = pdb.get_prices(cmdt,cur)
 +
      if len(pl)<1:
 +
        print 'Need at least one database entry to clone ...'
 +
        print '... %s ...' % (cmdt.get_fullname())
 +
        exit()
 +
      pl0 = pl[0]
 +
      p_new = pl0.clone(book)
 +
      p_new = gnucash.GncPrice(instance=p_new)
 +
      print 'Adding %30s  %s  %s  %f' % (cmdt.get_fullname(),stocki,stock_date[ii],stock_price[ii])
 +
      p_new.set_time(stock_date[ii])
 +
      v = p_new.get_value()
 +
      v.denom = 1000000
 +
      v.num = int(stock_price[ii]*v.denom)
 +
      p_new.set_value(v)
 +
      pdb.add_price(p_new)
 +
 +
 +
# Clean up
 +
session.save()
 +
session.end()
 +
session.destroy()
 
<\pre>
 
<\pre>

Revision as of 15:42, 26 January 2011

How to Import Fund or Stock Prices From an OFX File

The attached python script show how to import prices from an OFX file. This was useful for me because my 401k funds are not publicly traded so the norm import prices tool doesn't work. The OFX file has prices in the <INVPOS> aggregate. I borrowed heavily from work done by Peter Holtermann and others (price_database_example.py in src/optional/python-bindings/example_scripts).

Attached are 2 python scripts. getPrices.py reads the OFX file and outputs a CSV file in this format: fundName, date, price. The date looks like this: 20110118120000, year month day time. I suggest you try this standalone 1st and see if it works for your OFX file.

The other file, importPrice.py calls getPrices.py and uses the python bindings to update the price database in GC.

Another very useful tool is ofx.py, found at http://www.jongsma.org/gc/. I use this to download the OFX file.


getPrices.py ----
#!/usr/bin/python
# usage: getPrices.py ofxfile outfile
# Read an OFX w/ an INVPOS aggregate and write the prices
# to a CSV file

# Brad Haack 2011-01-25

import sys

fp = open(sys.argv[1])
fout = open(sys.argv[2],'w')

flines = fp.readlines()

inlist=0
inpos=0
id = 0
unqid=[]
price=[]
date=[]

for line in flines:
    line = line.rstrip('\n')
    wd = line.split('>')
    for id in range(len(wd)):
        wi = wd[id]
        if wi == '<INVPOSLIST': # now we're in the list
            inlist = 1
        if inlist :
            if wi == '<INVPOS': # now we're in the pos info aggregate
                inpos = 1
                unqid.append(0)
                price.append(0)
                date.append(0)
            if inpos :
                if wi == '<UNIQUEID' :
                    unqid[id] = wd[id+1]
                if wi == '<UNITPRICE' :
                    price[id] = wd[id+1]
                if wi == '<DTPRICEASOF' :
                    date[id] = wd[id+1]
            if wi == '</INVPOS': # now we're out of the pos info aggregate
                inpos = 0
                str = '%s, %s, %s\n' % (unqid[id], date[id], price[id])
                fout.write( str)
            
        if wi == '\INVPOSLIST>': # now we're not in the list
            inlist=0
        
<\pre>


importPrice.py ---

<pre>

  1. !/usr/bin/python
  2. Usage: importPrice.py ofxfile gcfile
  3. Import prices from an OFX file into Gnucash
  1. Configuration Options

cur_mnemonic="USD" namespace_name = "401k"

from gnucash import Session, Account, Split import gnucash import datetime import sys import os

ofxfile = sys.argv[1] gcfile = sys.argv[2] pricefile = 'pq.csv'

  1. Could call ofx.py here (see http://www.jongsma.org/gc/)
  2. ofx.py site user account
  1. get the prices from the ofx file

os.system('getPrices.py %s %s' % (ofxfile, pricefile) )

url = "xml://"+gcfile

  1. Read input data from file

f = open(pricefile) data = [] while 1:

   tmp = f.readline()
   if(len(tmp)<2):
       break
   
   data.append(tmp)

f.close()

stock_date = [] stock_price = [] stock = [] for i in range(len(data)):

   date = data[i].rsplit(',')[1].lstrip()
   year = int(date[0:4])
   month = int(date[4:6])
   day = int(date[6:8])
   stock_date.append(datetime.datetime(year,month,day))
   stock_price.append(float(data[i].rsplit(',')[2]))
   stock.append(data[i].rsplit(',')[0])
   
  1. Initialize Gnucash session

session = Session(url, True, False, False) book = session.book pdb = book.get_price_db() comm_table = book.get_table() cur = comm_table.lookup("CURRENCY", cur_mnemonic)

commodities=comm_table.get_commodities(namespace_name)

for ii, stocki in enumerate(stock):

 # find the commodity cusip that matches
 for cmdt in commodities:
   if cmdt.get_cusip() == stocki:
     
     # Get stock data
     pl = pdb.get_prices(cmdt,cur)
     if len(pl)<1:
       print 'Need at least one database entry to clone ...'
       print '... %s ...' % (cmdt.get_fullname())
       exit()
     pl0 = pl[0]
     p_new = pl0.clone(book)
     p_new = gnucash.GncPrice(instance=p_new)
     print 'Adding %30s  %s  %s  %f' % (cmdt.get_fullname(),stocki,stock_date[ii],stock_price[ii])
     p_new.set_time(stock_date[ii])
     v = p_new.get_value()
     v.denom = 1000000
     v.num = int(stock_price[ii]*v.denom)
     p_new.set_value(v)
     pdb.add_price(p_new)


  1. Clean up

session.save() session.end() session.destroy()

<\pre>