-
Notifications
You must be signed in to change notification settings - Fork 11
/
project.clj
273 lines (222 loc) · 10.4 KB
/
project.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
(defproject com.fxtlabs/stockings "1.1.0-SNAPSHOT"
:description "Easy access to financial data: stock quotes, exchange rates, industry sectors, companies, and more."
:url "https://github.com/fxtlabs/stockings"
:dependencies [[org.clojure/clojure "1.2.1"]
[joda-time "1.6"]
[clojure-csv "1.2.4"]
[clj-http "0.1.3"]]
:dev-dependencies
[[com.fxtlabs/autodoc "0.8.0-SNAPSHOT"
:exclusions [org.clojure/clojure org.clojure/clojure-contrib]]]
:license {:name "Eclipse Public License - v 1.0"
:url "http://www.eclipse.org/legal/epl-v10.html"
:distribution :repo
:comments "same as Clojure"}
:autodoc
{:name "Stockings"
:copyright "Copyright 2011 Filippo Tampieri"
:root "."
:source-path "src"
:web-src-dir "https://github.com/fxtlabs/stockings/blob/"
:web-home "http://stockings.fxtlabs.com/"
:output-path "autodoc"
:param-dir "autodoc-params"
:namespaces-to-document ["stockings"]
:load-except-list [#"/test/" #"project.clj"]
:description "Stockings is a Clojure library that gives you easy access to
financial data such as current and historical stock quotes, current currency
exchange rates, stock symbol suggestions, stock and company info by
exchanges and industry sectors, and more.
You can find Stockings' source code at <https://github.com/fxtlabs/stockings>.
## Usage
The stockings library is available from Clojars at
<http://clojars.org/com.fxtlabs/stockings>.
If you are using Leiningen, just add `[com.fxtlabs/stockings \"1.0.0\"]`
to the dependencies list in your `project.clj` file and run `lein deps`
to download the library from the Clojars archives.
## License
Copyright (C) 2011 Filippo Tampieri.
Distributed under the [Eclipse Public License v1.0](<http://www.eclipse.org/org/documents/epl-v10.php>),
the same as Clojure.
## Examples
Once you have the stockings JAR file on your classpath, you can run a
REPL, load the library and start exploring. The following examples show a few
commands (see user>) and their output (formatted here for readability).
They all assume you are using the `stockings.core` namespace:
user> (use 'stockings.core)
nil
### Current stock quotes
user> (get-quote \"YHOO\")
{:symbol \"YHOO\",
:last 16.02,
:last-date-time #<DateTime 2011-05-27T20:00:00.000Z>,
:name \"Yahoo! Inc.\",
:low 15.95,
:open 16.04,
:previous-close 15.98,
:high 16.19,
:volume 20096766}
gets the current stock quote for YAHOO! Note that the time for the
last trade is represented by a `org.joda.time.DateTime`
object in UTC. Stockings uses the Joda-Time library for all its
time-related values.
user> (get-quotes \"GOOG\" \"NASDAQ:AAPL\")
({:symbol \"GOOG\", ...}
{:symbol \"AAPL\", ...})
gets the current stock quotes for Google and Apple. Note that stock
symbols may optionally be prefixed with the name of an exchange (like
`NASDAQ:AAPL` above); however, the Yahoo! Finance service providing the
financial data does not recognize prefixed stock symbols, so the
prefix is simply dropped.
### Historical stock quotes
user> (import [org.joda.time LocalDate])
org.joda.time.LocalDate
user> (get-historical-quotes \"YHOO\" (LocalDate. 2011 4 1) (LocalDate. 2011 5 1))
(#:stockings.core.HistoricalQuote{:date #<LocalDate 2011-04-29>,
:open 17.46,
:high 17.77,
:low 17.36,
:close 17.7,
:volume 30800000}
#:stockings.core.HistoricalQuote{:date #<LocalDate 2011-04-28>,
:open 17.22,
:high 17.53,
:low 17.17,
:close 17.51,
:volume 14414700}
...
#:stockings.core.HistoricalQuote{:date #<LocalDate 2011-04-01>,
:open 16.83,
:high 16.98,
:low 16.72,
:close 16.84,
:volume 12487400})
gets the historical stock quotes for Yahoo! for the period starting on
April 1, 2011 and ending on May 1, 2011. There are a few things worth
noting:
* The quotes are returned in chronological order starting from the
most recent.
* There are no entries for dates that fall on a weekend or holiday.
* The dates are represented by `org.joda.time.LocalDate` objects.
Note that class ``LocalDate`` does not describe an exact instant
in time (e.g. an instant down to millisecond precision); instead,
it just refers to a given calendar day and no particular instant
of time within it.
### Info on companies and industry sectors
user> (get-stock \"YHOO\")
{:symbol \"YHOO\",
:name \"Yahoo! Inc.\",
:start-date #<LocalDate 1996-04-12>,
:end-date #<LocalDate 2011-05-30>,
:sector \"Technology\",
:industry \"Internet Information Providers\",
:full-time-employees 13600}
gets some info on a company.
user> (get-industry-sectors)
({:name \"Basic Materials\",
:industries [{:id \"112\", :name \"Agricultural Chemicals\"}
{:id \"132\", :name \"Aluminum\"}
{:id \"110\", :name \"Chemicals - Major Diversified\"}
...
{:id \"111\", :name \"Synthetics\"}]}
{:name \"Conglomerates\",
:industries [{:id \"210\", :name \"Conglomerates\"}]}
...)
gets a list of all industry sectors and a list of industries for each
sector.
user> (get-industry 112)
{:id \"112\",
:name \"Agricultural Chemicals\",
:companies [{:name \"Agrium Inc.\", :symbol \"AGU\"}
{:name \"American Vanguard Corporation\", :symbol \"AVD\"}
...
{:name \"Yongye International, Inc.\", :symbol \"YONG\"}]}
gets a list of all companies for a given industry (identified by its
ID).
### Current currency exchange rates
user> (get-exchange-rate :usd :eur)
{:base :usd,
:quote :eur,
:rate 0.7002,
:ask 0.7003,
:bid 0.7001,
:date-time #<DateTime 2011-05-30T20:43:00.000Z>}
gets the current exchange rate from a base currency (USD) to a quote (or
counter) currency (EUR). The currencies are denoted by their ISO 4217
3-letter designators used as strings or keywords. In other words:
user> (get-exchange-rate \"USD\" \"EUR\")
also works as above.
### Stock symbol lookup
user> (get-symbol-suggestion \"Terra Nitro\")
[{:symbol \"TNH\",
:name \"Terra Nitrogen Company, L.P.\",
:exch \"NYQ\",
:type \"S\",
:exchDisp \"NYSE\",
:typeDisp \"Equity\"}]
gets stock symbol suggestion for the company whose name starts with
the given prefix. Note that large companies may be traded on several
exchanges and thus correspond to more than one symbol.
### Current stock quotes - advanced use
So far so good. Now, let us look at a slightly more complex example.
Yahoo! Finance actually offers a lot more financial data when asking
for a stock quote. The `get-quote` example given at the beginning of
this section only returned a small subset of this data. Let us now see
how we can pick and choose what data we want to include in our stock
quotes.
user> raw-quote-keys
(:symbol :Name :PERatio :EarningsShare :EPSEstimateNextYear
:PercebtChangeFromYearHigh :ChangeFromTwoHundreddayMovingAverage
:TwoHundreddayMovingAverage :ChangeinPercent :Bid :DaysLow ...)
Var `raw-quote-keys` lists all the keys to the data contained in a raw
stock quote (what we can get from Yahoo! Finance). Let's say we want
to get custom stock quotes including the values of the keys `:symbol`,
`:Name`, and `:MarketCapitalization`.
user> (def parser (build-quote-parser {:symbol :symbol
:name :Name
:cap :MarketCapitalization}))
#'user/parser
user> (get-quote parser \"YHOO\")
{:symbol \"YHOO\", :name \"Yahoo! Inc.\", :cap 2.0873E10}
Function `get-quote` takes a quote parser as an optional first
parameter. The quote parser function is given the raw quote (with all
the keys listed in `raw-quote-keys`) and returns a parsed quote as a map
with the requested keys (`:symbol`, `:name`, and `:cap` in this case). All
we had to do was call `build-quote-parser` with a map specifying the
correspondences between the keys we want in the final quote and the
keys in the raw quote. So `get-quote` can get us back a result as a map
with exactly the info we want, no more, no less; note also that we are
completely free to use whatever names we want for the keys of the
resulting map.
Should we require even more flexibility, we can write our own quote
parser directly:
user> (defrecord MyQuote [stock-symbol company-name last last-date-time])
user.MyQuote
user> (defn my-parser [q]
(let [stock-symbol (parse-quote-item q :symbol)
company-name (parse-quote-item q :Name)
last (parse-quote-item q :LastTradePriceOnly)
last-date-time (parse-last-trade-date-time q)]
(MyQuote. stock-symbol company-name last last-date-time)))
#'user/my-parser
user> (get-quote my-parser \"YHOO\")
#:user.MyQuote{:stock-symbol \"YHOO\",
:company-name \"Yahoo! Inc.\",
:last 16.02,
:last-date-time #<DateTime 2011-05-27T20:00:00.000Z>}
The quote parser does not have to return a map; it can actually return
any type you like. Function `parse-quote-item` is used to parse one
field of the raw quote; it knows the data type (string, double, int,
etc.) of every field and will return the correct value and type.
Function `parse-last-trade-date-time` combines the values of
`:LastTradeDate` and `:LastTradeTime` and returns them as a
`org.joda.time.DateTime` object in UTC. You will want to use this
function if you need access to the last trade time and date because
the data returned by Yahoo! Finance for these fields is a bit
inconsistent; the date value is in UTC, but the time value is in the
time zone of the North American East Coast! Function
`parse-last-trade-date-time` corrects for this and returns a date time
in UTC.
## Digging Deeper
Stockings includes even more data and functions to help you dig into it.
Please, consult the detailed API documentation below to find out more."})