Remove all references to the now-defunct Yahoo! quote retrieval

And make Alphavantage the default.
This commit is contained in:
John Ralls 2018-01-02 10:43:49 -08:00
parent 320c5211b0
commit c0fd3b3165
9 changed files with 34 additions and 724 deletions

View File

@ -440,7 +440,7 @@ gnc_tree_view_commodity_new (QofBook *book,
sort_by_quote_flag, sort_by_quote_flag,
NULL); NULL);
col = gnc_tree_view_add_text_column ( col = gnc_tree_view_add_text_column (
view, _("Source"), "quote_source", NULL, "yahoo", view, _("Source"), "quote_source", NULL, "alphavantage",
GNC_TREE_MODEL_COMMODITY_COL_QUOTE_SOURCE, GNC_TREE_MODEL_COMMODITY_COL_QUOTE_SOURCE,
GNC_TREE_MODEL_COMMODITY_COL_VISIBILITY, GNC_TREE_MODEL_COMMODITY_COL_VISIBILITY,
sort_by_commodity_string); sort_by_commodity_string);

View File

@ -51,7 +51,7 @@
<cmdty:xcode>12345</cmdty:xcode> <cmdty:xcode>12345</cmdty:xcode>
<cmdty:fraction>10000</cmdty:fraction> <cmdty:fraction>10000</cmdty:fraction>
<cmdty:get_quotes/> <cmdty:get_quotes/>
<cmdty:quote_source>yahoo</cmdty:quote_source> <cmdty:quote_source>alphavantage</cmdty:quote_source>
</gnc:commodity> </gnc:commodity>
<gnc:account version="2.0.0"> <gnc:account version="2.0.0">
<act:name>Root Account</act:name> <act:name>Root Account</act:name>

View File

@ -116,9 +116,9 @@ Jon Trowbridge (@url{http://www.gnome.org/guppi}).
The @dfn{Price Quotes} module (@file{src/quotes}) is a Perl system to The @dfn{Price Quotes} module (@file{src/quotes}) is a Perl system to
fetch stock price data off the Internet and insert it into the GnuCash fetch stock price data off the Internet and insert it into the GnuCash
Engine. This module requires the functionality of the Finance::Quote Engine. This module requires the functionality of the Finance::Quote
module available at SourceForge. The Finance::Quote module can fetch module available from CPAN. The Finance::Quote module can fetch
price quotes from many different sources including Yahoo, Yahoo Europe, price quotes from many different sources including Alphavantage
and some international exchanges. and several international exchanges.
The Finance::Quote module also supports fetching currency exchange The Finance::Quote module also supports fetching currency exchange
rates. GnuCash will be extended to allow the fetching and use of rates. GnuCash will be extended to allow the fetching and use of

View File

@ -160,6 +160,7 @@ static gnc_quote_source currency_quote_source =
static gnc_quote_source single_quote_sources[] = static gnc_quote_source single_quote_sources[] =
{ {
{ FALSE, 0, 0, "Alphavantage USA", "ALPHAVANTAGE", "alphavantage" },
{ FALSE, 0, 0, "Amsterdam Euronext eXchange, NL", "AEX", "aex" }, { FALSE, 0, 0, "Amsterdam Euronext eXchange, NL", "AEX", "aex" },
{ FALSE, 0, 0, "American International Assurance, HK", "AIAHK", "aiahk" }, { FALSE, 0, 0, "American International Assurance, HK", "AIAHK", "aiahk" },
{ FALSE, 0, 0, "Association of Mutual Funds in India", "AMFIINDIA", "amfiindia" }, { FALSE, 0, 0, "Association of Mutual Funds in India", "AMFIINDIA", "amfiindia" },
@ -169,20 +170,26 @@ static gnc_quote_source single_quote_sources[] =
{ FALSE, 0, 0, "BMO NesbittBurns, CA", "BMONESBITTBURNS", "bmonesbittburns" }, { FALSE, 0, 0, "BMO NesbittBurns, CA", "BMONESBITTBURNS", "bmonesbittburns" },
{ FALSE, 0, 0, "Bucharest Stock Exchange, RO", "BSERO", "bsero" }, { FALSE, 0, 0, "Bucharest Stock Exchange, RO", "BSERO", "bsero" },
{ FALSE, 0, 0, "Budapest Stock Exchange (BET), ex-BUX, HU", "BSE", "bse" }, { FALSE, 0, 0, "Budapest Stock Exchange (BET), ex-BUX, HU", "BSE", "bse" },
{ FALSE, 0, 0, "Canada Mutual", "CANADAMUTUAL", "canadamutual" },
{ FALSE, 0, 0, "Citywire Funds, GB", "citywire", "citywire" }, { FALSE, 0, 0, "Citywire Funds, GB", "citywire", "citywire" },
{ FALSE, 0, 0, "Colombo Stock Exchange, LK", "CSE", "cse" }, { FALSE, 0, 0, "Colombo Stock Exchange, LK", "CSE", "cse" },
{ FALSE, 0, 0, "Cominvest, ex-Adig, DE", "COMINVEST", "cominvest" }, { FALSE, 0, 0, "Cominvest, ex-Adig, DE", "COMINVEST", "cominvest" },
{ FALSE, 0, 0, "Deka Investments, DE", "DEKA", "deka" }, { FALSE, 0, 0, "Deka Investments, DE", "DEKA", "deka" },
{ FALSE, 0, 0, "Dutch", "DUTCH", "dutch" },
{ FALSE, 0, 0, "DWS, DE", "DWS", "dwsfunds" }, { FALSE, 0, 0, "DWS, DE", "DWS", "dwsfunds" },
{ FALSE, 0, 0, "Equinox Unit Trusts, ZA", "ZA_unittrusts", "za_unittrusts" }, { FALSE, 0, 0, "Equinox Unit Trusts, ZA", "ZA_unittrusts", "za_unittrusts" },
{ FALSE, 0, 0, "Fidelity", "FIDELITY", "fidelity" },
{ FALSE, 0, 0, "Fidelity Direct", "FIDELITY_DIRECT", "fidelity_direct" }, { FALSE, 0, 0, "Fidelity Direct", "FIDELITY_DIRECT", "fidelity_direct" },
{ FALSE, 0, 0, "Finance Canada", "FINANCECANADA", "financecanada" }, { FALSE, 0, 0, "Finance Canada", "FINANCECANADA", "financecanada" },
{ FALSE, 0, 0, "Financial Times Funds service, GB", "FTFUNDS", "ftfunds" }, { FALSE, 0, 0, "Financial Times Funds service, GB", "FTFUNDS", "ftfunds" },
{ FALSE, 0, 0, "Finanzpartner, DE", "FINANZPARTNER", "finanzpartner" }, { FALSE, 0, 0, "Finanzpartner, DE", "FINANZPARTNER", "finanzpartner" },
{ FALSE, 0, 0, "First Trust Portfolios, US", "FTPORTFOLIOS_DIRECT", "ftportfolios_direct" }, { FALSE, 0, 0, "First Trust Portfolios, US", "FTPORTFOLIOS", "ftportfolios" },
{ FALSE, 0, 0, "Fund Library, CA", "FUNDLIBRARY", "fundlibrary" }, { FALSE, 0, 0, "Fund Library, CA", "FUNDLIBRARY", "fundlibrary" },
{ FALSE, 0, 0, "GoldMoney spot rates, JE", "GOLDMONEY", "goldmoney" }, { FALSE, 0, 0, "GoldMoney spot rates, JE", "GOLDMONEY", "goldmoney" },
{ FALSE, 0, 0, "HElsinki stock eXchange, FI", "HEX", "hex" }, { FALSE, 0, 0, "Greece", "GREECE", "greece" },
{ FALSE, 0, 0, "Helsinki stock eXchange, FI", "HEX", "hex" },
{ FALSE, 0, 0, "Hungary", "HU", "hu" },
{ FALSE, 0, 0, "India Mutual", "INDIAMUTUAL", "indiamutual" },
{ FALSE, 0, 0, "Man Investments, AU", "maninv", "maninv" }, { FALSE, 0, 0, "Man Investments, AU", "maninv", "maninv" },
{ FALSE, 0, 0, "Morningstar, GB", "MSTARUK", "mstaruk" }, { FALSE, 0, 0, "Morningstar, GB", "MSTARUK", "mstaruk" },
{ FALSE, 0, 0, "Morningstar, JP", "MORNINGSTARJP", "morningstarjp" }, { FALSE, 0, 0, "Morningstar, JP", "MORNINGSTARJP", "morningstarjp" },
@ -192,6 +199,7 @@ static gnc_quote_source single_quote_sources[] =
{ FALSE, 0, 0, "Paris Stock Exchange/Boursorama, FR", "BOURSO", "bourso" }, { FALSE, 0, 0, "Paris Stock Exchange/Boursorama, FR", "BOURSO", "bourso" },
{ FALSE, 0, 0, "Paris Stock Exchange/LeRevenu, FR", "LEREVENU", "lerevenu" }, { FALSE, 0, 0, "Paris Stock Exchange/LeRevenu, FR", "LEREVENU", "lerevenu" },
{ FALSE, 0, 0, "Platinum Asset Management, AU", "PLATINUM", "platinum" }, { FALSE, 0, 0, "Platinum Asset Management, AU", "PLATINUM", "platinum" },
{ FALSE, 0, 0, "Romania", "romania", "romania" },
{ FALSE, 0, 0, "SIX Swiss Exchange funds, CH", "SIXFUNDS", "sixfunds" }, { FALSE, 0, 0, "SIX Swiss Exchange funds, CH", "SIXFUNDS", "sixfunds" },
{ FALSE, 0, 0, "SIX Swiss Exchange shares, CH", "SIXSHARES", "sixshares" }, { FALSE, 0, 0, "SIX Swiss Exchange shares, CH", "SIXSHARES", "sixshares" },
{ FALSE, 0, 0, "Skandinaviska Enskilda Banken, SE", "SEB_FUNDS", "seb_funds" }, { FALSE, 0, 0, "Skandinaviska Enskilda Banken, SE", "SEB_FUNDS", "seb_funds" },
@ -201,47 +209,23 @@ static gnc_quote_source single_quote_sources[] =
{ FALSE, 0, 0, "TD Efunds, CA", "TDEFUNDS", "tdefunds" }, { FALSE, 0, 0, "TD Efunds, CA", "TDEFUNDS", "tdefunds" },
{ FALSE, 0, 0, "TIAA-CREF, US", "TIAACREF", "tiaacref" }, { FALSE, 0, 0, "TIAA-CREF, US", "TIAACREF", "tiaacref" },
{ FALSE, 0, 0, "Toronto Stock eXchange, CA", "TSX", "tsx" }, { FALSE, 0, 0, "Toronto Stock eXchange, CA", "TSX", "tsx" },
{ FALSE, 0, 0, "T. Rowe Price", "TRPRICE", "troweprice" },
{ FALSE, 0, 0, "T. Rowe Price, US", "TRPRICE_DIRECT", "troweprice_direct" }, { FALSE, 0, 0, "T. Rowe Price, US", "TRPRICE_DIRECT", "troweprice_direct" },
{ FALSE, 0, 0, "Trustnet via tnetuk.pm, GB", "TNETUK", "tnetuk" }, { FALSE, 0, 0, "Trustnet via tnetuk.pm, GB", "TNETUK", "tnetuk" },
{ FALSE, 0, 0, "Trustnet via trustnet.pm, GB", "TRUSTNET", "trustnet" }, { FALSE, 0, 0, "Trustnet via trustnet.pm, GB", "TRUSTNET", "trustnet" },
{ FALSE, 0, 0, "U.K. Unit Trusts", "UKUNITTRUSTS", "uk_unit_trusts" },
{ FALSE, 0, 0, "Union Investment, DE", "UNIONFUNDS", "unionfunds" }, { FALSE, 0, 0, "Union Investment, DE", "UNIONFUNDS", "unionfunds" },
{ FALSE, 0, 0, "US Treasury Bonds", "usfedbonds", "usfedbonds" }, { FALSE, 0, 0, "US Treasury Bonds", "usfedbonds", "usfedbonds" },
{ FALSE, 0, 0, "US Govt. Thrift Savings Plan", "TSP", "tsp" }, { FALSE, 0, 0, "US Govt. Thrift Savings Plan", "TSP", "tsp" },
{ FALSE, 0, 0, "Vanguard", "VANGUARD", "vanguard" }, /* No module seen in F::Q 1.17. */ { FALSE, 0, 0, "Vanguard", "VANGUARD", "vanguard" }, /* No module seen in F::Q 1.17. */
{ FALSE, 0, 0, "VWD, DE (unmaintained)", "VWD", "vwd" }, { FALSE, 0, 0, "VWD, DE (unmaintained)", "VWD", "vwd" },
{ FALSE, 0, 0, "Yahoo USA", "YAHOO", "yahoo" },
{ FALSE, 0, 0, "Yahoo Asia", "YAHOO_ASIA", "yahoo_asia" },
{ FALSE, 0, 0, "Yahoo Australia", "YAHOO_AUSTRALIA", "yahoo_australia" },
{ FALSE, 0, 0, "Yahoo Brasil", "YAHOO_BRASIL", "yahoo_brasil" },
{ FALSE, 0, 0, "Yahoo Europe", "YAHOO_EUROPE", "yahoo_europe" },
{ FALSE, 0, 0, "Yahoo New Zealand", "YAHOO_NZ", "yahoo_nz" },
{ FALSE, 0, 0, "Yahoo as JSON", "YAHOO_JSON", "yahoo_json" }, { FALSE, 0, 0, "Yahoo as JSON", "YAHOO_JSON", "yahoo_json" },
}; };
static gnc_quote_source multiple_quote_sources[] = static gnc_quote_source multiple_quote_sources[] =
{ {
{ FALSE, 0, 0, "Asia (Yahoo, ...)", "ASIA", "asia" }, { FALSE, 0, 0, "Europe (Athens, Boursorama, Bucharest)", "EUROPE", "europe" },
{ FALSE, 0, 0, "Australia (ASX, Yahoo, ...)", "AUSTRALIA", "australia" }, { FALSE, 0, 0, "France (Boursorama, LeRevenue)", "FRANCE", "france" },
{ FALSE, 0, 0, "Brasil (Yahoo, ...)", "BRASIL", "brasil" },
{ FALSE, 0, 0, "Canada (Yahoo, ...)", "CANADA", "canada" },
{ FALSE, 0, 0, "Canada Mutual (Fund Library, ...)", "CANADAMUTUAL", "canadamutual" },
{ FALSE, 0, 0, "Dutch (AEX, ...)", "DUTCH", "dutch" },
{ FALSE, 0, 0, "Europe (Yahoo, ...)", "EUROPE", "europe" },
{ FALSE, 0, 0, "Greece (ASE, ...)", "GREECE", "greece" },
{ FALSE, 0, 0, "Hungary (Bamosz, BET)", "HU", "hu" },
{ FALSE, 0, 0, "India Mutual (AMFI, ...)", "INDIAMUTUAL", "indiamutual" },
{ FALSE, 0, 0, "Fidelity (Fidelity, ...)", "FIDELITY", "fidelity" },
{ FALSE, 0, 0, "Finland (HEX, ...)", "FINLAND", "finland" },
{ FALSE, 0, 0, "First Trust (First Trust, ...)", "FTPORTFOLIOS", "ftportfolios" },
{ FALSE, 0, 0, "France (Boursorama, ...)", "FRANCE", "france" },
{ FALSE, 0, 0, "Nasdaq (Yahoo, ...)", "NASDAQ", "nasdaq" },
{ FALSE, 0, 0, "New Zealand (Yahoo, ...)", "NZ", "nz" },
{ FALSE, 0, 0, "NYSE (Yahoo, ...)", "NYSE", "nyse" },
/* { FALSE, 0, 0, "South Africa (Sharenet, ...)", "ZA", "za" }, */
{ FALSE, 0, 0, "Romania (BSE-RO, ...)", "romania", "romania" },
{ FALSE, 0, 0, "T. Rowe Price", "TRPRICE", "troweprice" },
{ FALSE, 0, 0, "U.K. Funds (citywire, FTfunds, MStar, tnetuk, ...)", "ukfunds", "ukfunds" }, { FALSE, 0, 0, "U.K. Funds (citywire, FTfunds, MStar, tnetuk, ...)", "ukfunds", "ukfunds" },
{ FALSE, 0, 0, "U.K. Unit Trusts (trustnet, ...)", "UKUNITTRUSTS", "uk_unit_trusts" },
{ FALSE, 0, 0, "USA (Yahoo, Fool, ...)", "USA", "usa" },
}; };
static const int num_single_quote_sources = static const int num_single_quote_sources =
@ -1123,7 +1107,7 @@ gnc_commodity_get_default_quote_source(const gnc_commodity *cm)
if (cm && gnc_commodity_is_iso(cm)) if (cm && gnc_commodity_is_iso(cm))
return &currency_quote_source; return &currency_quote_source;
/* Should make this a user option at some point. */ /* Should make this a user option at some point. */
return gnc_quote_source_lookup_by_internal("yahoo"); return gnc_quote_source_lookup_by_internal("alphavantage");
} }
/******************************************************************** /********************************************************************

View File

@ -22,12 +22,12 @@ my $quoter = Finance::Quote->new();
# ----------------------------------- # -----------------------------------
# get quotes for two stocks ... # get quotes for two stocks ...
%quotes = $quoter->fetch("yahoo","IBM", "SGI"); %quotes = $quoter->fetch("alphavantage","IBM", "SGI");
# print some selected values # print some selected values
print "NYSE by Yahoo: ", $quotes {"IBM", "name"}, print "NYSE by Alphavantage: ", $quotes {"IBM", "name"},
" last price: ", $quotes {"IBM", "last"}, "\n"; " last price: ", $quotes {"IBM", "last"}, "\n";
print "NYSE by Yahoo: ", $quotes {"SGI", "name"}, print "NYSE by Alphavantage: ", $quotes {"SGI", "name"},
" last price: ", $quotes {"SGI", "last"}, "\n"; " last price: ", $quotes {"SGI", "last"}, "\n";
# loop over and print all values. # loop over and print all values.

View File

@ -200,8 +200,8 @@ gnc-fq-dump - Print out data from the F::Q module
=head1 SYNOPSIS =head1 SYNOPSIS
gnc-fq-dump yahoo CSCO JNPR gnc-fq-dump alphavantage CSCO JNPR
gnc-fq-dump yahoo BAESY.PK gnc-fq-dump alphavantage BAESY.PK
gnc-fq-dump europe 48406.PA 13000.PA gnc-fq-dump europe 48406.PA 13000.PA
gnc-fq-dump vwd 632034 gnc-fq-dump vwd 632034
gnc-fq-dump ftportfolios FKYGTX gnc-fq-dump ftportfolios FKYGTX

View File

@ -48,16 +48,14 @@ side :>).
(<method-name> symbol symbol symbol ...) (<method-name> symbol symbol symbol ...)
where <method-name> indicates the desired Finance::Quote method. where <method-name> indicates the desired Finance::Quote method.
The currently recognized subset is yahoo, yahoo_europe, One can list the many methods by running gnc-fq-check.
fidelity_direct, troweprice_direct, vanguard, asx, tiaacref,
and currency.
For currency quotes, the symbols alternate between the 'from' For currency quotes, the symbols alternate between the 'from'
and 'to' currencies. and 'to' currencies.
For example: For example:
(yahoo "IBM" "LNUX") (alphavantage "IBM" "LNUX")
(fidelity_direct "FBIOX" "FSELX") (fidelity_direct "FBIOX" "FSELX")
(currency "USD" "AUD") (currency "USD" "AUD")
@ -78,7 +76,7 @@ need to convert it to that.
For example: For example:
$ echo '(yahoo "CSCO" "JDSU" "^IXIC")' | ./gnc-fq-helper $ echo '(alphavantage "CSCO" "JDSU" "^IXIC")' | ./gnc-fq-helper
(("CSCO" (symbol . "CSCO") (("CSCO" (symbol . "CSCO")
(gnc:time-no-zone . "2001-03-13 19:27:00") (gnc:time-no-zone . "2001-03-13 19:27:00")
(last . 20.375) (last . 20.375)
@ -95,7 +93,7 @@ For example:
On error, the overall result may be #f, or on individual errors, the On error, the overall result may be #f, or on individual errors, the
list sub-item for a given symbol may be #f, like this: list sub-item for a given symbol may be #f, like this:
$ echo '(yahoo "CSCO" "JDSU")' | ./gnc-fq-helper $ echo '(alphavantage "CSCO" "JDSU")' | ./gnc-fq-helper
(#f (#f
("JDSU" (symbol . "JDSU") ("JDSU" (symbol . "JDSU")
(gnc:time-no-zone . "2001-03-13 19:27:00") (gnc:time-no-zone . "2001-03-13 19:27:00")

View File

@ -1,672 +0,0 @@
#!/usr/bin/perl -w
#######################################################################
# $Id$
# Looks up investment prices on the web, and builds a report
# to summarize the results
#######################################################################
$HISTORYFILE="histprices";
$newprices = "NO"; # Haven't found *any* new prices so far...
#######################################################################
# Start by initializing the security list
#######################################################################
# My TSE stocks...
#######################################################################
&add_stock("T", 100, 1670.5, "TSE");
#&add_stock("NVA", 100, 1345.5, "TSE");
&add_stock("NVA", 100, -10.16, "TSE");
&add_stock("TRP", 52, 1345.50, "TSE");
&add_stock("PCA", 100, 1733, "TSE");
&add_stock("TOC", 50, 21.035*50, "TSE");
&add_stock("RY", 50, 32.785*50, "TSE");
#######################################################################
# My Canada Trust Everest funds...
#######################################################################
# Original numbers of units...
#&add_stock("CTMM", 83.951, 839.51, "CTE"); # Not strictly correct..
#&add_stock("CTBOND", 121.747, 1315.17, "CTE");
#&add_stock("CTSTK", 57.177, 832.73, "CTE");
#&add_stock("CTSPEC", 28.263, 504.07, "CTE");
#&add_stock("CTAMER", 177.723, 1983.05, "CTE");
#&add_stock("CTUSEQ", 19.644, 294.91, "CTE");
#&add_stock("CTASIA", 28.224, 251.99, "CTE");
#&add_stock("CTEURO", 60.136, 530.50, "CTE");
#&add_stock("CTEMER", 27.463, 266.67, "CTE");
#&add_stock("CTIBND", 84.879, 907.37, "CTE");
# Units as at Oct 31/98
&add_stock("CTMM", 89.572, 839.51, "CTE");
&add_stock("CTBOND", 137.398, 1315.17, "CTE");
&add_stock("CTSTK", 62.896, 832.73, "CTE");
&add_stock("CTSPEC", 28.263, 504.07, "CTE");
&add_stock("CTAMER", 251.604, 1983.05, "CTE");
&add_stock("CTUSEQ", 20.467, 294.91, "CTE");
&add_stock("CTASIA", 28.238, 251.99, "CTE");
&add_stock("CTEURO", 91.298, 530.50, "CTE");
&add_stock("CTEMER", 27.463, 266.67, "CTE");
&add_stock("CTIBND", 94.264, 907.37, "CTE");
# Stuff on NYSE
&add_stock("MOT", 15, (62+5/8)*15, "NYSE");
#&add_stock("IFMXE", 0.1, 0.1, "NYSE");
&add_stock("TSG", 13.0289, 43.02*5+43.75+44.48, "NYSE");
&add_stock("TSG", 27.619-13.0289, 44.48*8, "NYSE");
# SuperSaver 401(k)... Approximate...
&add_stock("AADBX", 0.3*2115.93/14, 0.3*1604.85, "NYSE");
&add_stock("AADEX", 0.5*2115.93/19, 0.5*1604.85, "NYSE");
&add_stock("AAIEX", 0.2*2115.93/15, 0.2*1604.85, "NYSE");
# SGRP Balances: Approximate...
&add_stock("AADBX", 712.33/14.9, 700, "NYSE"); # Balanced
&add_stock("AADEX", 4556.64/22.5 + (533.94+200.24+183.55)/22.5, 3500+(533.94+200.24+183.55), "NYSE"); # Equity
&add_stock("AAIEX", 1829.63/18.8 + (213.57+80.1+73.41)/18.8, 1700+(213.57+80.1+73.41), "NYSE"); # Int'l Equity
&add_stock("AASPX", 2104.81/15 + (320.37+120.12+110.13)/15, 1900 + (320.37+120.12+110.13), "NYSE"); # Stock Index
#######################################################################
# Working Ventures fund...
#######################################################################
&add_stock("WORKVE", 219.701, 3000, "OTHER");
$PRICE{"WORKVE"} = 3000/219.701; # Hack in a price for Working Ventures
$OLD{"WORKVE"} = "yes"; # Indicate that this is *not* a "new" price...
#######################################################################
# Map CT Everest fund names to the "short" IDs
#######################################################################
# I don't want to get long names; this builds an array that
# shortens the names used in the CT Everest Funds web page to
# the ones used above
#######################################################################
&ct_fund_ids; # Get mapping of CT "long" fund names to "short" names
&load_prices; # Load old prices, so that failure to get a price
# means we fall back to the previously-found
# price
$CURRNAME{"CDN"} = "Canadian";
$CURRNAME{"USD"} = "United States";
$CURRATE{"CDN"} = 1;
$CURRATE{"USD"} = 1.37;
&get_currency("USD");
#######################################################################
# Now, get the current prices by sundry queries of web sites
#######################################################################
&search_web_for_prices(); # Find new closing prices
&calc_variances(); # Calculate variances
#######################################################################
# Run report that details portfolio value based on the prices, costs
# and quantities of shares...
#######################################################################
if ($newprices eq "YES") {
&show_report(); # Display a report summarizing the results...
# &show_variances();
# &hilo_portfolios();
&save_prices(); # Save prices...
}
exit 0; # Done
#######################################################################
#######################################################################
#######################################################################
#######################################################################
#######################################################################
######################## End of the main body #########################
#######################################################################
#######################################################################
#######################################################################
#######################################################################
#######################################################################
#######################################################################
#######################################################################
############################# Subroutines #############################
#######################################################################
#######################################################################
#######################################################################
############### &add_stock("NVA", 100, 1345.5, "TSE"); ################
#######################################################################
# Add a security to the "active list," including the "ticker symbol,"
# quantity of shares, original total cost, and the exchange to look it
# up on.
#######################################################################
sub add_stock {
local($ticker, $num, $cost, $exchange) = @_;
$NUM{$ticker} += $num;
$COST{$ticker} += $cost;
$EXCHANGE{$ticker} = $exchange;
local ($currency) = "CDN";
if ($exchange eq "TSE") {
$currency = "CDN";
}
if ($exchange eq "NYSE") {
$currency = "USD";
}
if ($exchange eq "NY") {
$currency = "USD";
}
$CURRENCY{$ticker} = $currency;
}
#######################################################################
######## &get_url_command("http://www.conline.com/~cbbrowne");#########
#######################################################################
# Build the appropriate command that accesses (in raw form) the
# requested URL. Probably ought to change this to use the w3c
# "line mode" utility, as it's minscule
#######################################################################
sub get_url_command {
local ($url) = @_;
return "lynx -source '$url'";
}
#######################################################################
###################### &search_web_for_prices(); ######################
#######################################################################
# This program searches the %EXCHANGE array, determining how
# the security price should be searched out, and invokes the
# appropriate method.
#######################################################################
sub search_web_for_prices {
local ($ticker);
# Do some per-ticker searching
foreach $ticker (keys EXCHANGE) {
local($exchange) = $EXCHANGE{$ticker};
if ($exchange eq "TSE") {
&get_TSE($ticker);
&get_yahoo($ticker, "TSE");
}
if ($exchange eq "CTE") {
# Do nothing; data is coming
# in en masse via &get_all_everest_rates;
}
if ($exchange eq "NYSE") {
&get_yahoo($ticker, $EXCHANGE{$ticker});
}
}
# search for CT Everest fund data
&get_CT_Everest; # Get Everest mutual fund data
# Search for Working Ventures fund data
&get_WV;
# get all of the TSE stock prices
# foreach $ticker (ord("a")..ord("z")) {
# &get_TSE( chr($ticker) );
# }
}
#######################################################################
########################## &get_TSE ("RY"); ###########################
#######################################################################
# Look up a stock's price on the TSE using the Telenium service
#######################################################################
sub get_TSE {
local ($stock) = @_;
local ($page) = "http://www.telenium.ca/TSE/" .
lc(
substr($stock, 0, 1)
)
. ".html";
if ($OLD{$stock} eq "NO!") { # We've already priced this stock
return;
}
local ($command) = &get_url_command($page) . " | grep ' $stock'";
local ($line);
open(GETPAGE, "$command |");
# open(GETPAGE, "<a:/t~1.htm");
while ($line = <GETPAGE>) {
chop $line;
# print $line, "\n";
if ($line =~ /(\d*\.\d*)\D+\d+\S*\s+\d+\s+\S+\s+\d+\/\d+\s+(\S*)\s*$/) {
local($lp, $ls) = (sprintf("%.4f", $1), $2);
# print "Found $ls @ $lp\n";
#... 21.3 21.35 21.2 21.2 -0.15 142300 193 02/14 T
#... 19.4 19.5 19.2 19.35-0.1 687239 181 02/04 T
#... 51.5 52 50.6 51.4 0 1527378 583 02/05 RY
#... 1.18 1.2 1.1 1.2 0.02 44700 29 02/03 NBX
# ^^^
# Want this "close" value...
if ($lp < 0.001) {
# Do nothing
} elsif ($ls eq $stock) {
if ((($lp * 1.0) != $PRICE{$stock}) && ($price > 0)) {
$newprices = "YES";
$PRICE{$stock} = sprintf("%.4f", $price);
print "NEW PRICE: $stock, $lp\n";
} else {
$price = $PRICE{$stock};
}
$PRICE{$stock} = sprintf("%.4f", $lp);
$OLD{$stock} = "NO!"; # Indicate that this is an update...
}
}
}
close GETPAGE;
}
#######################################################################
############################ &get_yahoo(); ############################
#######################################################################
# Look up a stock via "yahoo"
#######################################################################
sub get_yahoo {
local ($stock, $exchange) = @_;
local ($price);
if (($exchange eq "NY") || ($exchange eq "NYSE")) {
$exchange = "";
}
if ($exchange eq "TSE") {
$exchange = ".TO";
}
local ($page) = "http://quote.yahoo.com/download/quotes.csv?symbols=" .
$stock . $exchange .
"&format=sl1d1t1c1ohgv&ext=.csv";
if ($OLD{$stock} eq "NO!") { # We've already priced this stock
return;
}
local ($command) = &get_url_command($page);
local ($line);
# print $command, "\n";
open(GETPAGE, "$command |");
while ($line = <GETPAGE>) {
# print "$line";
local ($trash, $price)=split(/,/, $line);
# print "$trash, $price\n";
# print "Old price: ", $PRICE{$stock}, "\n";
if ((($price * 1.0) != $PRICE{$stock}) && ($price > 0) ) {
$newprices = "YES";
print "NEW PRICE: $stock, $price\n";
} else {
$price = $PRICE{$stock};
# print "Keep old price: $price\n";
}
$PRICE{$stock} = sprintf("%.4f", $price);
$OLD{$stock} = "NO!"; # Indicate that this is an update...
# print "Done - ", $stock, $PRICE{$stock}, $OLD{$stock}, "\n";
}
}
#######################################################################
########################## &get_CT_Everest(); #########################
#######################################################################
# Look up all of the CT Everest mutual fund prices
#######################################################################
sub get_CT_Everest {
local ($line, $fund, $value);
local ($url) = "http://www.canadatrust.com/test/ctrates/EV.html";
local ($command) = &get_url_command($url);
open(FUNDS, "$command |");
while ($line = <FUNDS>) {
if ($line =~ /.*\s+\d+.\d+\s+\d+.\d+\s+.\d+.\d+/) {
# print "CT: $line";
$fund = substr($line, 0, 15);
# print "fund: [", $fund, "] ID:[", $ID{$fund}, "]\n";
if ($ID{$fund} ne "") {
$value = substr($line, 30, 11);
if (($value*1.0) != $PRICE{$ID{$fund}}) {
$newprices = "YES";
print "NEW PRICE: $fund, $value\n";
}
$PRICE{$ID{$fund}} = $value;
$OLD{$ID{$fund}} = "NO!"; # Indicate that this is an update...
# print "CT Price: $value ", $ID{$fund}, "\n";
}
}
}
close FUNDS;
}
#######################################################################
############################## &get_WV(); #############################
#######################################################################
# Look up Working Ventures fund price
#######################################################################
sub get_WV {
local ($url) = "http://www.workingventures.ca/main_cell.html";
local ($command) = &get_url_command($url) . " | grep 'share price' ";
open(FUNDS, "$command |");
while (<FUNDS>) {
if (/\D+\$(\d+\.\d+)\D+/) {
# matches .... $13.66 ...
if (($1 * 1.0) != $PRICE{"WORKVE"}) {
$newprices = "YES";
print "NEW PRICE: WV, $1\n";
}
$PRICE{"WORKVE"} = sprintf("%.4f", $1);
$OLD{"WORKVE"} = "NO!"; # Indicate that this is an update...
}
}
close FUNDS;
}
#######################################################################
########################### &ct_fund_ids (); ##########################
#######################################################################
# Build an associative array that lets one take the names used in the
# CT mutual fund web page, and associate them with the short forms
# used as "ticker" codes
#######################################################################
sub ct_fund_ids {
%ID = ("MONEY MARKET ", "CTMM",
"PREMIUM MMF ", "CTPMM",
"SHORT TERM BND ", "CTSTB",
"MORTGAGE ", "CTMTG",
"BALANCED ", "CTBAL",
"BOND ", "CTBOND",
"DIV INCOME ", "CTDIV",
"STOCK ", "CTSTK",
"SPECIAL EQUITY ", "CTSPEC",
"INT'L BOND ", "CTIBND",
"NORTH AMERICAN ", "CTNA",
"AMERIGROWTH ", "CTAMER",
"U.S. EQUITY ", "CTUSEQ",
"ASIAGROWTH ", "CTASIA",
"EUROGROWTH ", "CTEURO",
"GLOBALGROWTH ", "CTGLOB",
"INT'L EQUITY ", "CTINTL",
"EMERGING MKTS. ", "CTEMER"
);
}
#######################################################################
############################ &save_prices()############################
#######################################################################
# Dump data out to a file
#######################################################################
sub save_prices {
local ($date) = `date '+%Y/%m/%d-%H:%M:%S'`;
chop $date;
local ($ticker, $price);
open(HISTPRICES, ">>$HISTORYFILE");
while ($ticker = each %PRICE) {
if ($OLD{$ticker} eq "yes") {
# Don't dump it; we didn't get a new price...
} else {
$key = $date . "" . $ticker;
$price = $PRICE{$ticker};
print HISTPRICES $date, "|", $ticker, "|", $price, "\n";;
}
}
close HISTPRICES;
}
#######################################################################
########################### &load_prices();############################
#######################################################################
# Preload prices, thus always keeping around the latest successfully
# located price.
# This means that if the web search process fails, we still do have
# pricing, even if it's somewhat out of date...
#######################################################################
sub load_prices {
local ($date) = `date '+%Y/%m/%d-%H:%M:%S'`;
chop $date;
local ($ticker, $price, $line);
open(HISTPRICES, "<$HISTORYFILE");
while ($line = <HISTPRICES>) {
($date, $ticker, $price) = split(/\|/, $line);
$PRICE{$ticker} = $price;
$OLD{$ticker} = "yes"; # Indicate that this is an old price
# and thus not to be redumped
}
close HISTPRICES;
}
#######################################################################
############################ &show_report();###########################
#######################################################################
# Look up all of the securities, and build a report listing the cost,
# value, and net profit/loss on each security, along with totals.
########################################################################
sub show_report {
local($date) = `date`;
chop $date;
local($ticker, $shares, $price, $value, $cost, $profitloss);
local ($tp, $tv, $tc);
format STDOUT_TOP =
Portfolio Valuation
as at @<<<<<<<<<<<<<<<<<<<<<<<<<<<
$date
Ticker Shares Recent Price Value Cost Profit/Loss
------------------------------------------------------------------------
.
format STDOUT =
@<<<<<<< @>>>>>>> @>>>>>>>> @>>>>>>>>>>> @>>>>>>>>>>> @>>>>>>>>>>>>
$ticker, $shares, $price, $value, $cost, $profitloss
.
foreach $stock (sort keys EXCHANGE) {
if ($stock ne "zPortfolio") {
$ticker = $stock;
$shares = sprintf("%.4f", $NUM{$stock});
$price = sprintf("%.4f", $PRICE{$stock});
$value = sprintf("%.2f", $shares * $price * $CURRATE{$CURRENCY{$stock}});
$cost = sprintf("%.2f", $COST{$stock} * $CURRATE{$CURRENCY{$stock} });
$profitloss = sprintf("%.2f", $value - $cost);
$tv += $value;
$tc += $cost;
$tp += $profitloss;
write;
}
}
($ticker, $shares, $price, $value, $cost, $profitloss) =
("", "", "", "---------------", "---------------", "---------------");
write;
($ticker, $shares, $price, $value, $cost, $profitloss) =
("Total", "", "", sprintf("%.2f", $tv), sprintf("%.2f" ,$tc),
sprintf("%.2f" ,$tp));
write;
($ticker, $shares, $price, $value, $cost, $profitloss) =
("", "", "", "===============", "===============", "===============");
write;
}
#########################################################################=
#####
############################## Find Variances #########################=
#####
#########################################################################=
#####
sub calc_variances {
local ($x);
open(PRICEF, "<$HISTORYFILE");
while (<PRICEF>) {
($date, $id, $price) = split(/\|/, $_);
$XCOUNT{$id} ++;
$quantity = $NUM{$id};
$x = $quantity * $price * $CURRATE{$CURRENCY{$id}};
$XSUM{$id} += $x;
$XSQUARESUM{$id} += ($x * $x);
$DATES{$date} ++;
$PRICES{"$date|$id"} = $price;
# printf "XC: %9.2f XSUM: %9.2f XSQ: %9.2f\n", $XCOUNT{$id}, $XSUM{$id}, $XSQUARESUM{$id};
}
&complete_price_list(); # Get prices for *every* day
&value_portfolios(); # Value the portfolio for every day
}
# Need to make sure that we have prices for each stock for each date
# This is done by (for each stock) going thru all the dates, and
# inserting prices for dates where prices are missing. We use the
# last price present for the stock.
sub complete_price_list {
foreach $stock (keys XCOUNT) {
$current_price = $XSUM{$stock} / $XCOUNT{$stock};
# Move forwards until a price gets found. That price
# is then used for all "empty" price slots up to the first
# actual measurement
FIRSTPRICE:
foreach $date (sort keys DATES) {
if ($PRICES{"$date|$stock"}) {
$current_price = $PRICES{"$date|$stock"};
last FIRSTPRICE;
}
}
# Now, proceed onwards...
foreach $date (sort keys DATES) {
if ($PRICES{"$date|$stock"}) {
# There's a price
$current_price = $PRICES{"$date|$stock"};
} else {
$PRICES{"$date|$stock"} = $current_price;
}
}
}
}
sub value_portfolios {
# &setup_portfolio_quantities();
$NUM{"zPortfolio"}=1;
foreach $date (sort keys DATES) {
$price = 0;
foreach $stock (keys XCOUNT) {
$price += $NUM{$stock} * $PRICES{"$date|$stock"}* $CURRATE{$CURRENCY{$stock}};
}
$XCOUNT{"zPortfolio"} ++;
$XSUM{"zPortfolio"} += $price;
$XSQUARESUM{"zPortfolio"} += ($price * $price);
# printf "Portfolio on %15s valued at %14.2f\n", $date, $price;
}
}
sub hilo_portfolios {
local($date, $hi, $lo, $hival, $loval);
local ($stock, $price, $latest_date);
foreach $stock (keys XCOUNT) {
$LO{$stock} = 99999999;
$HI{$stock} = -99999999;
}
$HI{"zPortfolio"} = -99999999;
$LO{"zPortfolio"} = 99999999;
foreach $date (keys DATES) {
local ($pprice);
local($dt) = split(/-/, $date);
foreach $stock (keys XCOUNT) {
$price = $PRICES{"$date|$stock"};
if ($date >= $latest_date) {
$latest_date = $date;
$CURRENT{$stock} = $price;
}
if ($price > $HI{$stock}) {
($HI{$stock}, $HIDATE{$stock}) = ($price, $dt);
}
if ($price < $LO{$stock}) {
($LO{$stock}, $LODATE{$stock}) = ($price, $dt);
}
$pprice += $NUM{$stock} * $price;
}
if ($date >= $latest_date) {
$latest_date = $date;
$CURRENT{"zPortfolio"} = $pprice;
}
if ($pprice > $HI{"zPortfolio"}) {
($HI{"zPortfolio"}, $HIDATE{"zPortfolio"}) = ($pprice, $dt);
}
if ($pprice > $LO{"zPortfolio"}) {
($LO{"zPortfolio"}, $LODATE{"zPortfolio"}) = ($pprice, $dt);
}
}
# Report results...
print
"-----------------------------------------------------------------------
Highs/Lows
-----------------------------------------------------------------------
";
printf "%10s %10s %10s %10s %10s %10s\n", "Stock", "High Date", "High",
"Low Date", "Low Price", "Current";
print "-----------------------------------------------------------------------";
foreach $stock (sort keys XCOUNT) {
printf "%10s %10s %10.2f %10s %10.2f %10.2f\n", $stock, $HIDATE{$stock},
$HI{$stock}, $LODATE{$stock}, $LO{$stock}, $CURRENT{$stock};
}
print "-----------------------------------------------------------------------";
}
sub show_variances {
print
"-----------------------------------------------------------------------
Variance/Standard Deviations for Portfolio *VALUE*
------------------------------------------------------------------------
Security Mean Variance Std. Dev. % Std.Dev
------------------------------------------------------------------------
";
foreach $i (sort keys XCOUNT) {
if ($XCOUNT{$i} > 2) {
$variance = (($XCOUNT{$i} * $XSQUARESUM{$i})
- ($XSUM{$i} * $XSUM{$i})) /
($XCOUNT{$i} * ($XCOUNT{$i}-1));
}
$variance = -$variance if ($variance < 0);
$deviation = sqrt($variance);
# printf "XC: %5d XSUM: %9.2f XSQ: %9.2f\n", $XCOUNT{$i}, $XSUM{$i}, $XSQUARESUM{$i};
# Divide by mean price to determine volatility of price
if ($XCOUNT{$i} != 0 && $XSUM{$i} != 0) {
$volatility = $deviation / ($XSUM{$i} / $XCOUNT{$i});
printf "%10s %10.2f %14.3f %9.3f %9.3f\n", $i, $XSUM{$i}/$XCOUNT{$i},
$variance, $deviation,
$volatility *100;
($VARIANCE{$i}, $STD{$i}, $VOLATILITY{$i}) = ($variance, $deviation,
$volatility);
}
}
print "------------------------------------------------------------------------";
}
sub get_currency {
local ($to) = @_;
local($url) =
"http://www.dna.lth.se/cgi-bin/kurt/rates/rates?CAD+$to";
local($line, $rate);
local ($command) = &get_url_command($url);
local($fromname, $toname) = ($CURRNAME{"CDN"}, $CURRNAME{$to});
open(CURRS, "$command |");
while ($line = <CURRS>) {
if ($line =~ /Rate: $fromname.*$toname.*:\s*(\d*.\d+)/) {
$rate = $1;
$CURRATE{$toname} = sprintf("%f", $rate);
return;
}
}
}

View File

@ -118,7 +118,7 @@
;; ;;
;; (<fq-method> sym sym ...) ;; (<fq-method> sym sym ...)
;; ;;
;; i.e. (yahoo "RHAT" "LNUX" "IBM") ;; i.e. (alphavantage "RHAT" "LNUX" "IBM")
;; ;;
;; for currencies, we have ;; for currencies, we have
;; ;;
@ -210,7 +210,7 @@
;; gnc-fq-helper. Each item will of the list will be of the ;; gnc-fq-helper. Each item will of the list will be of the
;; form: ;; form:
;; ;;
;; (("yahoo" (commodity-1 currency-1 tz-1) ;; (("alphavantage" (commodity-1 currency-1 tz-1)
;; (commodity-2 currency-2 tz-2) ...) ;; (commodity-2 currency-2 tz-2) ...)
;; ("fidelity_direct" (commodity-3 currency-3 tz-3) ;; ("fidelity_direct" (commodity-3 currency-3 tz-3)
;; (commodity-4 currency-4 tz-4) ...) ;; (commodity-4 currency-4 tz-4) ...)
@ -259,10 +259,10 @@
;; their fq-suitable symbol strings. i.e. turn the former into ;; their fq-suitable symbol strings. i.e. turn the former into
;; the latter: ;; the latter:
;; ;;
;; ("yahoo" (commodity-1 currency-1 tz-1) ;; ("alphavantage" (commodity-1 currency-1 tz-1)
;; (commodity-2 currency-2 tz-2) ...) ;; (commodity-2 currency-2 tz-2) ...)
;; ;;
;; ("yahoo" "IBM" "AMD" ...) ;; ("alphavantage" "IBM" "AMD" ...)
;; ;;
(if (equal? (car fq-call-data) "currency") (if (equal? (car fq-call-data) "currency")