@@ -6,42 +6,108 @@ struct APIResponse
6
6
http_resp:: HTTP.Messages.Response
7
7
end
8
8
9
+ abstract type AbstractQueryOpt <: AbstractDict{Symbol,Any} end
10
+
11
+ Base. length (:: T ) where {T<: AbstractQueryOpt } = fieldcount (T)
12
+ Base. length (:: Type{T} ) where {T<: AbstractQueryOpt } = fieldcount (T)
13
+
14
+ function Base. iterate (aqo:: T , state = 1 ) where {T<: AbstractQueryOpt }
15
+ (state > length (T)) && return nothing
16
+ (fieldname (T, state) => getfield (aqo, state), state + 1 )
17
+ end
9
18
10
19
"""
11
- Description
20
+ struct YahooOpt <: AbstractQueryOpt
21
+ period1 # the start time
22
+ period2 # the end time
23
+ interval # "1d", "1wk" or "1mo"
24
+ events # currently only `:history` supported
25
+ end
12
26
13
- The yahoo() method is a wrapper for downloading historical stock prices from Yahoo .
27
+ The Yahoo Finance HTTP API query object .
14
28
15
- Usage
29
+ # Examples
16
30
17
- AAPL = yahoo("AAPL)
18
- SPX = yahoo()
31
+ ```jl-repl
32
+ julia> t = Dates.now()
33
+ 2020-08-09T01:38:04.735
19
34
20
- Method Signature(s)
35
+ julia> YahooOpt(period1 = t - Year(2), period2 = t)
36
+ YahooOpt{DateTime} with 4 entries:
37
+ :period1 => 1533778685
38
+ :period2 => 1596937085
39
+ :interval => "1d"
40
+ :events => :history
41
+ ```
42
+ """
43
+ struct YahooOpt <: AbstractQueryOpt
44
+ period1:: DateTime
45
+ period2:: DateTime
46
+ interval:: String
47
+ events:: Symbol
48
+
49
+ YahooOpt (; period1:: DateTime = DateTime (1971 , 2 , 8 ),
50
+ period2:: DateTime = Dates. now (),
51
+ interval:: String = " 1d" ,
52
+ events:: Symbol = :history ) =
53
+ new (period1, period2, interval, events)
54
+ end
21
55
22
- yahoo(data::ASCIIString="^GSPC")
56
+ function Base. iterate (opt:: YahooOpt , state = 1 )
57
+ (state > length (YahooOpt)) && return nothing
58
+ k = fieldname (YahooOpt, state)
59
+ v = getfield (opt, state)
60
+ v′ = (k ∈ (:period1 , :period2 )) ? round (Int, datetime2unix (v)) : v
61
+ (k => v′, state + 1 )
62
+ end
23
63
24
- Details
64
+ """
65
+ yahoo(symbol::AbstractString, opt::YahooOpt = YahooOpt())::TimeArray
66
+ yahoo(symbol::Symbol, opt::YahooOpt = YahooOpt())::TimeArray
25
67
26
- The yahoo method takes a stock name in the form of a string and returns a TimeSeries.TimeArray data structure
27
- corresponding to the Yahoo Finance ticker. With no argument, the default historical time series is the S&P 500.
68
+ This is a wrapper for downloading historical stock prices from Yahoo Finance.
28
69
29
- References
70
+ The yahoo method takes a stock name in the form of a string and returns a
71
+ `TimeSeries.TimeArray` corresponding to the Yahoo Finance ticker.
72
+ With no argument, the default historical time series is the S&P 500.
30
73
31
- http://www.finance.yahoo.com
74
+ # Examples
32
75
33
- See Also
76
+ ```julia
77
+ AAPL = yahoo(:AAPL)
78
+ SPX = yahoo("^GSPC")
79
+ NQ = yahoo("^IXIC")
80
+ ```
81
+
82
+ ```jl-repl
83
+ julia> start = DateTime(2018, 1, 1)
84
+ 2018-01-01T00:00:00
85
+
86
+ julia> yahoo(:AAPL, YahooOpt(period1 = start))
87
+ 655×6 TimeArray{Float64,2,Date,Array{Float64,2}} 2018-01-02 to 2020-08-07
88
+ ...
89
+ ```
90
+
91
+ # References
92
+
93
+ https://finance.yahoo.com
34
94
35
- fred() which accesses the St. Louis Federal Reserve financial and economic data sets.
95
+ # See Also
96
+
97
+ fred() which accesses the St. Louis Federal Reserve financial and economic data sets.
36
98
"""
37
- function yahoo (data:: String = " ^GSPC" )
38
- Base. depwarn (" Yahoo Finance API changed, this function may not work anymore" , :yahoo )
39
- url = " http://ichart.yahoo.com/table.csv?s=$data "
40
- http_resp = HTTP. request (" GET" , url)
41
- resp = APIResponse (data, http_resp)
42
- TimeArray (resp)
99
+ function yahoo (sym:: AbstractString = " ^GSPC" , opt:: YahooOpt = YahooOpt ())
100
+ host = rand ([" query1" , " query2" ])
101
+ url = " https://$host .finance.yahoo.com/v7/finance/download/$sym "
102
+ res = HTTP. get (url, query = opt)
103
+ @assert res. status == 200
104
+ csv = CSV. File (res. body, missingstrings = [" null" ])
105
+ sch = TimeSeries. Tables. schema (csv)
106
+ TimeArray (csv, timestamp = first (sch. names))
43
107
end
44
108
109
+ yahoo (s:: Symbol , opt:: YahooOpt = YahooOpt ()) = yahoo (string (s), opt)
110
+
45
111
"""
46
112
Description
47
113
@@ -72,45 +138,10 @@ See Also
72
138
"""
73
139
function fred (data:: String = " CPIAUCNS" )
74
140
url = " http://research.stlouisfed.org/fred2/series/$data /downloaddata/$data .csv"
75
- http_resp = HTTP. request (" GET" , url)
76
- resp = APIResponse (data, http_resp)
77
- TimeArray (resp)
78
- end
79
-
80
-
81
- function TimeArray (resp:: APIResponse )
82
- # This function transform the Response object into a TimeArray
83
- # Split the data on every "\n"
84
- raw_data = String (resp. http_resp. body)
85
- data = split (raw_data, " \n " )
86
- # Extract the head and body of the data
87
- head = strip (data[1 ])
88
- body = data[2 : end ]
89
- # Parse body
90
- body[end ] == " " ? pop! (body) : nothing # remove trailing empty string if it's there
91
- body = [split (line, " ," ) for line in body] # split on comma
92
- # ######## Timestamp
93
- # take the first row (assuming it's date)
94
- # TODO : regex query needed to catch edge cases
95
- dates = [line[1 ] for line in body]
96
- timestamp = Date[Date (d) for d in dates] # parse dates
97
- # ######## Values
98
- svals = [line[2 : end ] for line in body] # get rows 2 to the end
99
- fvals = zeros (length (svals),length (svals[1 ]))
100
- for r in 1 : size (fvals,1 )
101
- for c in 1 : size (fvals,2 )
102
- # is not empty and is not equal to FRED's iconic "." sentinel for missingness
103
- if ~ isempty (svals[r][c]) && ~ isequal (svals[r][c]," .\r " )
104
- fvals[r,c] = parse (Float64, svals[r][c])
105
- else
106
- # captures FRED's "." sentinel
107
- fvals[r,c] = NaN
108
- end
109
- end
110
- end
111
- # ######## Column names
112
- names = split (head, " ," )[2 : end ] # Won't need the Date name (fist column) for TimeArray
113
- names = String[name for name in names]
114
- return TimeArray (timestamp, fvals, names, resp. data)
141
+ res = HTTP. get (url)
142
+ @assert res. status == 200
143
+ csv = CSV. File (res. body)
144
+ sch = TimeSeries. Tables. schema (csv)
145
+ TimeArray (csv, timestamp = first (sch. names))
115
146
end
116
147
0 commit comments