Stocks/get prices
From GnuCash
This document presents one way to import historic stock quotes into GnuCash. This example uses GnuCash's Python Bindings which may need to be installed separately.
- Prerequisite
- Some knowledge of Perl and Python is required.
- Ensure that both Perl and Python are available.
- You will also need to install the special Perl module Finance::QuoteHist: [metacpan.org or github] and its dependencies.
To run the scripts below you need a GnuCash xml file named test.gnucash. For illustration, we show how to get prices for an account named Intel that contains shares of the INTC stock. The method for adding the INTC stock to your GnuCash file is explained in Add stock to portfolio. In addition, you have to add one price of INTC into the database by hand.
Get the data
We will get the data with Finance::QuoteHist and store it in a text file. The Perl script to get the quotes is as follows:#!/usr/bin/perl -w
use Finance::QuoteHist;
print "Will get stock quotes of $ARGV[0] and save it into the file $ARGV[0]\n";
$fname = $ARGV[0];
open (MYFILE, ">$fname");
$q = Finance::QuoteHist->new
(
symbols => [($ARGV[0])],
start_date => '01/01/2000',
end_date => 'today',
);
print "name,date, open, high, low, close, volume\n";
foreach $row ($q->quotes()) {
($name,$date, $open, $high, $low, $close, $volume) = @$row;
print MYFILE "$name,$date, $open, $high, $low, $close, $volume\n";
}
close(MYFILE);
chmod a+x get_quotes
- Example
- Execute it with the argument INTC to get the Intel prices saved into the file INTC:
% chmod a+x get_quotes % ./get_quotes INTC
- The INTC file should look similar to this:
INTC,2000/01/03, 83.2700, 87.3700, 83.2500, 87.0000, 57710200 INTC,2000/01/04, 85.4400, 87.8700, 82.2500, 82.9400, 51019600 INTC,2000/01/05, 83.0000, 85.8700, 80.5000, 83.6200, 52389000
Import the data into GnuCash
The following python script will read the text file INTC and add the prices to the GnuCash file test.gnucash.#!/usr/bin/env python3
# NOTE: Some aspects below require GnuCash release 5.17 or newer.
from gnucash import Session, GncNumeric, GncPrice, PriceSource, GNC_HOW_DENOM_FIXED, GNC_HOW_RND_ROUND_HALF_UP
from gnucash.gnucash_core_c import COMMODITY_DENOM_MULT
import datetime
from gnc_convenience import find_account
FILE = "./test.gnucash"
url = "xml://"+FILE
# Read data from file
f = open('INTC')
data = []
while 1:
tmp = f.readline()
if(len(tmp)<2):
break
data.append(tmp)
f.close()
stock_date = []
stock_price = []
for i in range(1,len(data)):
year = int(data[i].rsplit(',')[1].rsplit('/')[0])
month = int(data[i].rsplit(',')[1].rsplit('/')[1])
day = int(data[i].rsplit(',')[1].rsplit('/')[2])
stock_date.append(datetime.datetime(year,month,day))
stock_price.append(float(data[i].rsplit(',')[5]))
# Initialize Gnucash session
session = Session(url)
root = session.book.get_root_account()
book = session.book
account = book.get_root_account()
pdb = book.get_price_db()
comm_table = book.get_table()
# This example assumes the Intel holding is priced in USD.
ac = find_account(account, 'Intel')[0]
stock = ac.GetCommodity()
cur = comm_table.lookup("CURRENCY", "USD")
# Construct the price at the precision GnuCash uses for a commodity quoted in a
# currency: the currency's smallest unit (its SCU -- get_fraction() is 100 for
# USD, i.e. cents) times COMMODITY_DENOM_MULT (10000), the extra precision a
# price carries beyond an ordinary amount. See "Price policy" in gnc-pricedb.h.
price_denom = cur.get_fraction() * COMMODITY_DENOM_MULT
for i in range(0, len(stock_date)):
print('Adding', i, stock_date[i], stock_price[i])
# --- Create a fresh price object with all properties set ------------------
p_new = GncPrice(book)
p_new.set_commodity(stock)
p_new.set_currency(cur)
p_new.set_time64(stock_date[i])
p_new.set_value(GncNumeric(stock_price[i], price_denom,
GNC_HOW_DENOM_FIXED | GNC_HOW_RND_ROUND_HALF_UP))
p_new.set_source(PriceSource.FINANCE_QUOTE)
p_new.set_typestr("last") # bid / ask / last / nav / unknown
# --------------------------------------------------------------------------
pdb.add_price(p_new)
# Clean up
session.save()
session.end()
session.destroy()
You now have the stock quotes from Intel in test.gnucash.