Dear AppleScripters,
I’ve been beating my head against the wall over what seems to be a simple task. Using applescript to retrieve a stock quote from the internet. All the posts I can find are over 3 years old and the simple Apple supplied “Get Stock Quote” doesn’t function on any machine i’ve tested.
All I’m trying to do is have an apple script take a list of stock quotes i have, go retrieve the newest prices off of the internet and bring them back. I have worked a lot with AppleScript but have little XML/SOAP knowledge. Since Apple seems to include one it shouldn’t be that big a deal to get a simple script that works.
So can any body help me in finding some simple AppleScript code to do the Ticker to Current Stock Price? Or does anybody already have that code written?
i just prefer to have AppleScript do it on it’s own then having to get a third party app or worry about using my browser to go and get the information. Simply put, i have written a small XCode/AppleScript app that stays open and delivers all the information i need (kinda like a widget) but with more specialized content. (Motion sensors in my house, current weather, computers being used, etc)
Please let me know if anybody has any input. It would be much appreciated.
Cheers,
TalonGold
Why roll your own? There are several listed on Google (stock ticker price OS X). I own iStock ($12, shareware) and it does my portfolio nicely.
I can add that I diddled with SOAP at length before deciding I wasn’t going to get there. SOAP is a horror show.
I checked out iStock, very nice, and actually serves some of my needs. The specific reason was to built in a “ticker” of sorts into this application I’m making. Just on the side of this app would be current stock prices of a few stocks. I know people will be like ‘why not use a widget’ this is not a computer I’ll be running on, it’s basically a channel that is broadcasted in my home showing me all the information i need to know at a current moment. A custom full screened app.
Thats why specifically I was looking for a stock script, you wouldn’t think that such simply acquired information would be so hard to find or parse into applescript. ESPECIALLY a feature that APPLE themselves sends along with the computer.
Very strange, anybody else have any suggestions, and thanks for the heads up on iStock, pretty nice little piece of software.
Cheers,
TalonGold
The only SOAP call I’ve ever seen that worked for me was this trivia:
try
tell application "http://boyzoid.com/comp/randomQuote.cfc"
set aQuote to call soap {method name:"GetQuote", parameters:{HTMLFormat:false}}
end tell
set aList to |item| of aQuote
repeat with anItem in aList
if |key| of anItem is "AUTHOR" then
set auth to value of anItem
end if
if |key| of anItem is "QUOTE" then
set quot to value of anItem
end if
end repeat
set ourQuote to quot & return & " -- " & auth
on error anError
set ourQuote to false
end try
ourQuote
I just googled your request and came up with a method using URL Access Scripting on tidbits:
http://www.tidbits.com/resources/481/UASYahoo.html
It works fine, just need to change the parsing.
-N
Interesting that it works for you - produces trash for me.
Thanks to nedloh99, i was able to change the parsing and get it to work pretty well. It is nasty and a pretty thrown together script, but once you put in the stock ticker it’ll even translate to the company name, and give the current quote and the time the quote was posted.
So if anybody is interested, give it a try! Hopefully, even though it’s a low use script, Apple will take a note and not give us scripts that don’t work.
property fullQuote : ""
on run
try
set myQuote to text returned of (display dialog "What Quote?" default answer "")
--set myQuote to "MS"
set daSymbol to allCaps(myQuote)
-- make a temp file
set myFile to ((path to temporary items) as string) & "Stock Quote Script Temp"
-- fetch quote page
tell application "URL Access Scripting"
download "http://finance.yahoo.com/q" to file myFile replacing yes form data "s=" & daSymbol & "&d=v1"
quit
end tell
-- read HTML into a variable
open for access file myFile
set quoteHTML to (read file myFile to (get eof file myFile))
close access file myFile
set myCompanySearchText to " (" & daSymbol & ")</b></td><td align="
set myCompanyCount to count of myCompanySearchText
set companyAnswer to ((the offset of myCompanySearchText in quoteHTML))
set CompanyTimeShare to (characters companyAnswer through (companyAnswer - 30)) of quoteHTML as string
set companyAnswer2 to ((the offset of "<b>" in CompanyTimeShare))
set otherCount to count of CompanyTimeShare
set TheCompany to (characters (companyAnswer2 + 3) through (otherCount - 1)) of CompanyTimeShare as string
set mySearchText to "</small><big><b>"
set myCount to count of mySearchText
set myAnswer to ((the offset of mySearchText in quoteHTML) + myCount)
set currentQuote to (characters myAnswer through (myAnswer + 5)) of quoteHTML as string
my parseTheList(currentQuote)
set TimeShare to (characters ((myAnswer - myCount) - 3) through ((myAnswer - myCount) - 11)) of quoteHTML as string
if TimeShare is "4:00PM ET" or TimeShare is "4:01PM ET" then set TimeShare to "market close"
tell application "Finder" to delete file myFile
if fullQuote is not "" then
display dialog TheCompany & "'s current price is $" & fullQuote & " at " & TimeShare & "."
else
display dialog "Unable to find a price for " & daSymbol & "."
end if
on error
display dialog "Unable to find stock '" & myQuote & "'"
end try
end run
on allCaps(daText)
-- very messy capitalization routine
copy "" to newText
repeat with i from 1 to the count of character in daText
set curChar to character i of daText
set curNum to ASCII number curChar
if (curNum > 96) and (curNum < 123) then
set newText to (newText & (ASCII character (curNum - 32))) as string
else
set newText to (newText & curChar) as string
end if
end repeat
return newText
end allCaps
on parseTheList(parseMe)
--A rough nasty way of making sure you only pick out the numbers in case of a 2 digit or 3 digit price
set parseMe to every character of parseMe
set parsedList to {}
repeat with i from 1 to number of items in parseMe
set this_item to item i of parseMe
try
if this_item is "." then
copy this_item to the end of parsedList
else
set this_item to this_item as number
copy this_item to the end of parsedList
end if
end try
end repeat
set fullQuote to parsedList as string
end parseTheList
Not to worry, N, TG’s version works fine for me.
BTW, capitalization is easy (without disturbing numbers or punctuation) this way:
on allCaps(daText)
set UC to "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
set LC to "abcdefghijklmnopqrstuvwxyz"
considering case
set char to characters of daText
repeat with aC in char
if contents of aC is in LC then set contents of aC to item (offset of aC in LC) of UC
end repeat
end considering
return char as string
end allCaps
set newText to allCaps("Now iS the 1246 and, : so on")
--> "NOW IS THE 1246 AND, : SO ON"
To get numbers only and include a decimal point in the right place, same trick as capitalization works:
on NumsOnly(aString)
set numStr to ""
set keepers to "1234567890."
set strChr to characters of aString
repeat with C in strChr
if contents of C is in keepers then set numStr to numStr & contents of C
end repeat
return numStr
end NumsOnly
set nums to NumsOnly("some Text & $123.45 >") --> "123.45"
… and this way:
on allCaps(daText)
return do shell script "echo " & daText & " | tr a-z A-Z"
end allCaps
set newText to allCaps("Now iS the 1246 and, : so on")
--> "NOW IS THE 1246 AND, : SO ON"
Here’s a new version with StefanK’s much simpler capitalization script.
property fullQuote : ""
on run
try
with timeout of 7 seconds
set myQuote to text returned of (display dialog "What Quote?" default answer "")
--set myQuote to "MS"
set daSymbol to allCaps(myQuote)
-- make a temp file
set myFile to ((path to temporary items) as string) & "Stock Quote Script Temp"
-- fetch quote page
tell application "URL Access Scripting"
download "http://finance.yahoo.com/q" to file myFile replacing yes form data "s=" & daSymbol & "&d=v1"
quit
end tell
-- read HTML into a variable
open for access file myFile
set quoteHTML to (read file myFile to (get eof file myFile))
close access file myFile
--Get the full name of the company
set myCompanySearchText to " (" & daSymbol & ")</b></td><td align="
set myCompanyCount to count of myCompanySearchText
set companyAnswer to ((the offset of myCompanySearchText in quoteHTML))
set CompanyTimeShare to (characters companyAnswer through (companyAnswer - 30)) of quoteHTML as string
set companyAnswer2 to ((the offset of "<b>" in CompanyTimeShare))
set otherCount to count of CompanyTimeShare
set TheCompany to (characters (companyAnswer2 + 3) through (otherCount - 1)) of CompanyTimeShare as string
--Get the current quote
set mySearchText to "</small><big><b>"
set myCount to count of mySearchText
set myAnswer to ((the offset of mySearchText in quoteHTML) + myCount)
set currentQuote to (characters myAnswer through (myAnswer + 5)) of quoteHTML as string
--parse the quote to check for 2 or 3 digit prices
my parseTheList(currentQuote)
set TimeShare to (characters ((myAnswer - myCount) - 3) through ((myAnswer - myCount) - 11)) of quoteHTML as string
--check to see if the markets are open or closed
if TimeShare is "4:00PM ET" or TimeShare is "4:01PM ET" then set TimeShare to "market close"
tell application "Finder" to delete file myFile
if fullQuote is not "" then
display dialog TheCompany & "'s current price is $" & fullQuote & " at " & TimeShare & "."
else
display dialog "Unable to find a price for " & daSymbol & "."
end if
end timeout
on error
display dialog "Unable to find stock '" & myQuote & "'"
end try
end run
on allCaps(daText)
set newText to (do shell script "echo " & daText & " | tr a-z A-Z")
end allCaps
on parseTheList(parseMe)
--A rough nasty way of making sure you only pick out the numbers in case of a 2 digit or 3 digit price
set parseMe to every character of parseMe
set parsedList to {}
repeat with i from 1 to number of items in parseMe
set this_item to item i of parseMe
try
if this_item is "." then
copy this_item to the end of parsedList
else
set this_item to this_item as number
copy this_item to the end of parsedList
end if
end try
end repeat
set fullQuote to parsedList as string
end parseTheList
When I run it (as downloaded with the " changed to ") it returns this in the dialog (which I’ve declared a variable).
"Yahoo says AAPL last traded at meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">AAPL: Summary for APPLE INC - Yahoo! Finance at $e>
#screen,#masthead{text-align:center;margin:0;width:752px;}
#screen.xpand,#masthead.xpand{width:100%;}
#screen.xpand #yfncsubtit{width:100%;}
#masthead{padding-bottom:12px;}
#leftcol,#rightcol{margin:0;}
#leftcol{width:155px;float:left;}
#rightcol{width:585px;}
#content{width:752px;}
#footer {clear:both;}
///
body{text-align:center;}
#screen{text-align:left;min-width:700px;width:62.5em;width:expression(
document.all.footer ? (document.all.footer.offsetWidth>1000) ? ‘980’+‘px’ : document.all.footer.offsetWidth :‘62.5’+‘em’) ;margin:auto;border:1px solid #FFF;}
#screen.xpand{width:100%; text-align:center}
#portfolio{margin:10px auto;}
#hdrads{margin:10px auto 0 auto;}
#masthead,#leftcol,#rightcol{margin:0;}
#masthead{width:100%;}
#leftcol{float:left;width:18%;}
#rightcol{float:right;width:80%;}
#content{width:100%;}
#footer{clear:both;text-align:center;padding:10px
0;width:60em;margin:auto;border:0px solid #FFF;} #leftNavTable,#yfncmh,#yfncmkttme,#yfncduplgnwrn,#yfncpsnlbar,#yfnctitbar,#y
fncsubtit,#yfncbrobtn,#yfncsumtab,
.yfnc_systitlelinea1,.yfnc_systitlelineb1,.yfnc_modtitlew1{
width:100%;}
#yfncmh{width:100%;}
.yfncsumdatagrid{background:#DCDCDC;width:100%;}
.yfnc_modtitlew2{width:49%;}
/**/
.yfncnhl{color:#666;margin-bottom:10px;}
.yfncnhl .yfncnhlbl{color:#000;width:1.6em;text-align:center;}
#leftcol{display:none;}
#rightcol{display:block;}
-1)?1:0);
var yfimoz = ((yfiagt.indexOf(‘gecko’)>-1&&!yfisaf)?1:0);
var yfiopr = ((yfiagt.indexOf(‘opera’)>-1&&!yfisaf)?1:0);
//–>."
Okay, here’s an interesting one,
if you take this out of my script
on parseTheList(parseMe)
--A rough nasty way of making sure you only pick out the numbers in case of a 2 digit or 3 digit price
set parseMe to every character of parseMe
set parsedList to {}
repeat with i from 1 to number of items in parseMe
set this_item to item i of parseMe
try
if this_item is "." then
copy this_item to the end of parsedList
else
set this_item to this_item as number
copy this_item to the end of parsedList
end if
end try
end repeat
set fullQuote to parsedList as string
end parseTheList
and replace it with
on parseTheList(parseMe)
set fullQuote to ""
set keepers to "1234567890."
set strChr to characters of parseMe
repeat with C in strChr
if contents of C is in keepers then set fullQuote to fullQuote & contents of C
end repeat
return fullQuote
end parseTheList
It would seem that Yahoo will give the Stock quote to the third decimal place, so a search for SCHW (Charles Schwab) you can get a price of $21.325, while my original one will only go to the 2nd place and drop off the remainder. Not sure if thats a good or a bad thing, Yahoo DOES actually give it to you to that detail, but rarely do I think i’d have to know what kind of half cents a stock is trading at.
Is there an easier way to use the simplified parsing script but only have it go to the 2nd decimal place? For all standard purposes I’d only need actually dollars, instead of the “Gas Pumping” style that yahoo puts out.
Cheers,
TalonGold
Adam,
That was just the parsing thing I mentioned. I thought you were getting something COMPLETELY odd.
-N