├── .gitignore ├── LICENSE ├── README.md └── quandl ├── doc.html ├── quandl.go └── quandl_test.go /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | quandl/quandl_test.go 3 | 4 | quandl/quandl_test.go 5 | 6 | quandl/quandl_test.go 7 | 8 | quandl/quandl_test.go 9 | 10 | quandl/quandl_test.go 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Hedge Chart 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | golang-quandl 2 | ============= 3 | 4 | Quandl package for Go (golang) 5 | 6 | Usage (anonymous): 7 | ``` 8 | q, _ := quandl.GetData("DMDRN/MSFT_MKT_CAP", "2000-01-01", "2013-01-05") 9 | 10 | dates, marketCap := q.GetTimeSeriesData() 11 | ``` 12 | 13 | Usage (with auth token): 14 | ``` 15 | quandl.SetAuthToken("your auth token here") 16 | 17 | q, _ := GetAllHistory("DMDRN/MSFT_MKT_CAP") 18 | 19 | dates, marketCap := q.GetTimeSeriesData() 20 | 21 | ``` 22 | 23 | Running a search: 24 | ``` 25 | body, err := Search("Apple Inc Short Interest") 26 | 27 | if err == nil { 28 | fmt.Printf("%s", body) 29 | } 30 | ``` 31 | 32 | Get all stocks in Quandl: 33 | ``` 34 | identifier, description := quandl.GetStockList() 35 | ``` 36 | 37 | Get all ETFs in Quandl: 38 | ``` 39 | identifier, description := quandl.GetETFList() 40 | ``` 41 | 42 | To use these identifiers you can simply use: 43 | ``` 44 | q, _ := quandl.GetData(identifier[0], "2013-01-01", "2013-01-05") 45 | 46 | dates, values := q.GetTimeSeriesData() 47 | ``` 48 | 49 | The QuandResponse struct that is returned contains some metadata that may be useful for identifying attributes about the data that is returned. 50 | ``` 51 | type QuandlResponse struct { 52 | SourceCode string `json:"source_code"` 53 | SourceName string `json:"source_name"` 54 | Code string `json:"code"` 55 | Frequency string `json:"frequency"` 56 | FromDate string `json:"from_date"` 57 | ToDate string `json:"to_date"` 58 | Columns []string `json:"column_names"` 59 | Data interface{} `json:"data"` 60 | } 61 | ``` 62 | 63 | PACKAGE DOCUMENTATION 64 | ===================== 65 | ``` 66 | 67 | package quandl 68 | import "github.com/HedgeChart/golang-quandl/quandl" 69 | 70 | 71 | 72 | FUNCTIONS 73 | 74 | func GetAllSecurityList() ([]string, []string) 75 | GetAllSecurityList gets all the security identifiers and descriptions 76 | 77 | func GetBitcoinList() ([]string, []string) 78 | GetBitcoinList just returns 79 | http://www.quandl.com/api/v1/datasets/BITCOIN/BITSTAMPUSD 80 | 81 | func GetCommoditiesList() ([]string, []string) 82 | GetCommoditiesList gets all the Quandl codes and commodity descriptions 83 | 84 | func GetDowConstituents() ([]string, []string) 85 | GetDowConstituents 86 | 87 | func GetETFList() ([]string, []string) 88 | GetETFList gets all the Quandl codes and ETF descriptions 89 | 90 | func GetETFTickerList() ([]string, []string) 91 | GetETFTickerList gets all the Quandl codes and ETF tickers 92 | 93 | func GetEconomicDataList() ([]string, []string) 94 | Economic data (doesn't pertain to a particular security) 95 | GetEconomicDataList 96 | 97 | func GetFTSE100Constituents() ([]string, []string) 98 | GetFTSE100Constituents 99 | 100 | func GetFinancialRatiosList() ([]string, []string) 101 | GetFinancialRatiosList returns the list of Damordoran financial ratios. 102 | Currently this list is hard-coded into the file because Quandl does not 103 | provide a file from where to read. A caveat about using these is that 104 | you need to append the ticker in a particular way to use these ratios 105 | 106 | func GetNasdaq100Constituents() ([]string, []string) 107 | GetNasdaq100Constituents 108 | 109 | func GetNasdaqCompositeConstituents() ([]string, []string) 110 | GetNasdaqCompositeConstituents 111 | 112 | func GetSP500Constituents() ([]string, []string) 113 | Index membership GetSP500Constituents 114 | 115 | func GetSP500SectorMappings() ([]string, []string) 116 | Sector mappings GetSP500SectorMappings 117 | 118 | func GetStockIndexList() ([]string, []string) 119 | GetStockIndexList gets all the Quandl codes and stock index descriptions 120 | 121 | func GetStockList() ([]string, []string) 122 | GetStockList gets all the Quandl stock codes and descriptions 123 | 124 | func GetStockTickerList() ([]string, []string) 125 | GetStockTickerList gets all the Quandl codes and tickers 126 | 127 | func Search(query string) ([]byte, error) 128 | Search executes a query against the Quandl API and returns the JSON 129 | object as a byte stream. In future releases of this Go (golang) Quandl 130 | package this will return a native object instead of the json 131 | 132 | func SetAuthToken(token string) 133 | SetAuthToken sets the auth token globally so that all subsequent calls 134 | that retrieve data from the Quandl API will use the auth token. 135 | 136 | 137 | TYPES 138 | 139 | type QuandlResponse struct { 140 | SourceCode string `json:"source_code"` 141 | SourceName string `json:"source_name"` 142 | Code string `json:"code"` 143 | Frequency string `json:"frequency"` 144 | FromDate string `json:"from_date"` 145 | ToDate string `json:"to_date"` 146 | Columns []string `json:"column_names"` 147 | Data interface{} `json:"data"` 148 | } 149 | 150 | 151 | func GetAllHistory(identifier string) (*QuandlResponse, error) 152 | GetAllHistory is similar to GetData except that it does not restrict a 153 | date range 154 | 155 | 156 | func GetData(identifier string, startDate string, endDate string) (*QuandlResponse, error) 157 | GetData gets Quandl data for a particular identifier and a date range. 158 | You can optionally set the auth token before running this function so 159 | that you can make unlimited API calls instead of being limited to 160 | 500/day. 161 | 162 | 163 | func (q *QuandlResponse) GetTimeSeries(column string) ([]string, []float64) 164 | GetTimeSeries returns a date vector and the value vector for a 165 | particular column in the QuandlResponse 166 | 167 | func (q *QuandlResponse) GetTimeSeriesColumn(column string) []float64 168 | GetTimeSeriesColumn returns the data from the Quandl response for a 169 | particular column. For some series, particularly stock data, multiple 170 | columns are returned. Using this method you can specify the specific 171 | column to extract. 172 | 173 | func (q *QuandlResponse) GetTimeSeriesData() ([]float64, string) 174 | GetTimeSeriesData returns the most relevant data column from the Quandl 175 | response. In many cases you will not necessarily know beforehand what 176 | type of data is being requested and therefore cannot determine if it's 177 | stock data vs. economic data. In such cases, you can use this function 178 | to grab the column that is most likely relevant. The method also returns 179 | the most relevant 180 | 181 | func (q *QuandlResponse) GetTimeSeriesDate() []string 182 | GetTimeSeriesDate returns the series of dates in the time series 183 | 184 | 185 | ``` 186 | -------------------------------------------------------------------------------- /quandl/doc.html: -------------------------------------------------------------------------------- 1 | 6 | 12 | 13 | 14 | 15 |
16 |
17 |
import "github.com/HedgeChart/golang-quandl/quandl"
18 |
19 |
20 |
Overview
21 |
Index
22 | 23 |
Examples
24 | 25 | 26 |
27 |
28 | 29 |
30 | 33 |
34 |

Overview ▾

35 | 36 |
37 |
38 |
39 | 42 |
43 |

Example

44 | 45 | 46 | 47 |

Code:

48 |
GetData("BOE/XUDLBK73", "2013-01-01", "2013-01-05")
 49 | 
 50 | 
51 | 52 |

Output:

53 |
&{BOE Bank of England XUDLBK73 daily 2005-04-01 2014-05-09 [Date Value] [[2013-01-04 %!s(float64=6.2303)] [2013-01-03 %!s(float64=6.2301)] [2013-01-02 %!s(float64=6.2301)]]}
 54 | 
55 | 56 | 57 |
58 |
59 | 60 | 61 |
62 | 65 |
66 |

Index ▾

67 | 68 | 69 |
70 |
71 | 72 | 73 | 74 | 75 |
func GetAllSecurityList() ([]string, []string)
76 | 77 | 78 |
func GetBitcoinList() ([]string, []string)
79 | 80 | 81 |
func GetCommoditiesList() ([]string, []string)
82 | 83 | 84 |
func GetDowConstituents() ([]string, []string)
85 | 86 | 87 |
func GetETFList() ([]string, []string)
88 | 89 | 90 |
func GetETFTickerList() ([]string, []string)
91 | 92 | 93 |
func GetEconomicDataList() ([]string, []string)
94 | 95 | 96 |
func GetFTSE100Constituents() ([]string, []string)
97 | 98 | 99 |
func GetFinancialRatiosList() ([]string, []string)
100 | 101 | 102 |
func GetNasdaq100Constituents() ([]string, []string)
103 | 104 | 105 |
func GetNasdaqCompositeConstituents() ([]string, []string)
106 | 107 | 108 |
func GetSP500Constituents() ([]string, []string)
109 | 110 | 111 |
func GetSP500SectorMappings() ([]string, []string)
112 | 113 | 114 |
func GetStockIndexList() ([]string, []string)
115 | 116 | 117 |
func GetStockList() ([]string, []string)
118 | 119 | 120 |
func GetStockTickerList() ([]string, []string)
121 | 122 | 123 |
func Search(query string) ([]byte, error)
124 | 125 | 126 |
func SetAuthToken(token string)
127 | 128 | 129 | 130 |
type QuandlResponse
131 | 132 | 133 |
    func GetAllHistory(identifier string) (*QuandlResponse, error)
134 | 135 | 136 |
    func GetData(identifier string, startDate string, endDate string) (*QuandlResponse, error)
137 | 138 | 139 | 140 |
    func (q *QuandlResponse) GetTimeSeries(column string) ([]string, []float64)
141 | 142 | 143 |
    func (q *QuandlResponse) GetTimeSeriesColumn(column string) []float64
144 | 145 | 146 |
    func (q *QuandlResponse) GetTimeSeriesData() ([]float64, string)
147 | 148 | 149 |
    func (q *QuandlResponse) GetTimeSeriesDate() []string
150 | 151 | 152 | 153 |
154 |
155 | 156 | 157 |
158 |

Examples

159 |
160 | 161 |
Package
162 | 163 |
GetAllHistory
164 | 165 |
GetAllSecurityList
166 | 167 |
GetEconomicDataList
168 | 169 |
GetFinancialRatiosList
170 | 171 |
GetStockList
172 | 173 |
SetAuthToken
174 | 175 |
176 |
177 | 178 | 179 | 180 |

Package files

181 |

182 | 183 | 184 | quandl.go 185 | 186 | 187 |

188 | 189 |
190 |
191 | 192 | 193 | 194 | 195 | 196 | 197 |

func GetAllSecurityList

198 |
func GetAllSecurityList() ([]string, []string)
199 |

200 | GetAllSecurityList gets all the security identifiers and descriptions 201 |

202 | 203 |
204 | 207 |
208 |

Example

209 | 210 | 211 | 212 |

Code:

213 |
identifier, description := GetAllSecurityList()
214 | 
215 | fmt.Printf("len(identifier)=%v\n%q : %q\n", len(identifier), identifier[20000], description[20000])
216 | 
217 | 
218 | 219 |

Output:

220 |
len(identifier)=21382
221 | "GOOG/NYSEARCA_TDTT" : "TDTT"
222 | 
223 | 224 | 225 |
226 |
227 | 228 | 229 | 230 | 231 |

func GetBitcoinList

232 |
func GetBitcoinList() ([]string, []string)
233 |

234 | GetBitcoinList just returns http://www.quandl.com/api/v1/datasets/BITCOIN/BITSTAMPUSD 235 |

236 | 237 | 238 | 239 | 240 | 241 |

func GetCommoditiesList

242 |
func GetCommoditiesList() ([]string, []string)
243 |

244 | GetCommoditiesList gets all the Quandl codes and commodity descriptions 245 |

246 | 247 | 248 | 249 | 250 | 251 |

func GetDowConstituents

252 |
func GetDowConstituents() ([]string, []string)
253 |

254 | GetDowConstituents 255 |

256 | 257 | 258 | 259 | 260 | 261 |

func GetETFList

262 |
func GetETFList() ([]string, []string)
263 |

264 | GetETFList gets all the Quandl codes and ETF descriptions 265 |

266 | 267 | 268 | 269 | 270 | 271 |

func GetETFTickerList

272 |
func GetETFTickerList() ([]string, []string)
273 |

274 | GetETFTickerList gets all the Quandl codes and ETF tickers 275 |

276 | 277 | 278 | 279 | 280 | 281 |

func GetEconomicDataList

282 |
func GetEconomicDataList() ([]string, []string)
283 |

284 | Economic data (doesn't pertain to a particular security) 285 | GetEconomicDataList 286 |

287 | 288 |
289 | 292 |
293 |

Example

294 | 295 | 296 | 297 |

Code:

298 |
identifier, description := GetEconomicDataList()
299 | 
300 | fmt.Printf("%q : %q\n", identifier[0], description[0])
301 | 
302 | 
303 | 304 |

Output:

305 |
"FRED/LAWFIN" : "Finance and Insurance Wages and Salaries in Louisiana"
306 | 
307 | 308 | 309 |
310 |
311 | 312 | 313 | 314 | 315 |

func GetFTSE100Constituents

316 |
func GetFTSE100Constituents() ([]string, []string)
317 |

318 | GetFTSE100Constituents 319 |

320 | 321 | 322 | 323 | 324 | 325 |

func GetFinancialRatiosList

326 |
func GetFinancialRatiosList() ([]string, []string)
327 |

328 | GetFinancialRatiosList returns the list of Damordoran financial ratios. Currently 329 | this list is hard-coded into the file because Quandl does not provide a file from 330 | where to read. A caveat about using these is that you need to append the ticker 331 | in a particular way to use these ratios 332 |

333 | 334 |
335 | 338 |
339 |

Example

340 | 341 | 342 | 343 |

Code:

344 |
identifier, description := GetFinancialRatiosList()
345 | 
346 | fmt.Printf("%q : %q\n", identifier[10], description[10])
347 | 
348 | 
349 | 350 |

Output:

351 |
"PE_FWD" : "Forward PE Ratio"
352 | 
353 | 354 | 355 |
356 |
357 | 358 | 359 | 360 | 361 |

func GetNasdaq100Constituents

362 |
func GetNasdaq100Constituents() ([]string, []string)
363 |

364 | GetNasdaq100Constituents 365 |

366 | 367 | 368 | 369 | 370 | 371 |

func GetNasdaqCompositeConstituents

372 |
func GetNasdaqCompositeConstituents() ([]string, []string)
373 |

374 | GetNasdaqCompositeConstituents 375 |

376 | 377 | 378 | 379 | 380 | 381 |

func GetSP500Constituents

382 |
func GetSP500Constituents() ([]string, []string)
383 |

384 | Index membership 385 | GetSP500Constituents 386 |

387 | 388 | 389 | 390 | 391 | 392 |

func GetSP500SectorMappings

393 |
func GetSP500SectorMappings() ([]string, []string)
394 |

395 | Sector mappings 396 | GetSP500SectorMappings 397 |

398 | 399 | 400 | 401 | 402 | 403 |

func GetStockIndexList

404 |
func GetStockIndexList() ([]string, []string)
405 |

406 | GetStockIndexList gets all the Quandl codes and stock index descriptions 407 |

408 | 409 | 410 | 411 | 412 | 413 |

func GetStockList

414 |
func GetStockList() ([]string, []string)
415 |

416 | GetStockList gets all the Quandl stock codes and descriptions 417 |

418 | 419 |
420 | 423 |
424 |

Example

425 | 426 | 427 | 428 |

Code:

429 |
identifier, description := GetStockList()
430 | 
431 | fmt.Printf("%q : %q\n", identifier[0], description[0])
432 | 
433 | 
434 | 435 |

Output:

436 |
"WIKI/ACT" : "Actavis, Inc."
437 | 
438 | 439 | 440 |
441 |
442 | 443 | 444 | 445 | 446 |

func GetStockTickerList

447 |
func GetStockTickerList() ([]string, []string)
448 |

449 | GetStockTickerList gets all the Quandl codes and tickers 450 |

451 | 452 | 453 | 454 | 455 | 456 | 457 |
func Search(query string) ([]byte, error)
458 |

459 | Search executes a query against the Quandl API and returns the JSON object 460 | as a byte stream. In future releases of this Go (golang) Quandl package 461 | this will return a native object instead of the json 462 |

463 | 464 | 465 | 466 | 467 | 468 |

func SetAuthToken

469 |
func SetAuthToken(token string)
470 |

471 | SetAuthToken sets the auth token globally so that all subsequent calls that 472 | retrieve data from the Quandl API will use the auth token. 473 |

474 | 475 |
476 | 479 |
480 |

Example

481 | 482 | 483 | 484 |

Code:

485 |
SetAuthToken("")
486 | 
487 | GetData("WIKI/AAPL", "2013-01-01", "2013-01-05")
488 | 
489 | 
490 | 491 |

Output:

492 |
&{WIKI Quandl Open Data AAPL daily 1980-12-12 2014-05-12 [Date Open High Low Close Volume Ex-Dividend Split Ratio Adj. Open Adj. High Adj. Low Adj. Close Adj. Volume] [[2013-01-04 %!s(float64=536.97) %!s(float64=538.63) %!s(float64=525.83) %!s(float64=527) %!s(float64=2.12262e+07) %!s(float64=0) %!s(float64=1) %!s(float64=514.9749775418) %!s(float64=516.56698168118) %!s(float64=504.29128711251) %!s(float64=505.41336231918) %!s(float64=2.12262e+07)] [2013-01-03 %!s(float64=547.88) %!s(float64=549.67) %!s(float64=541) %!s(float64=542.1) %!s(float64=1.26059e+07) %!s(float64=0) %!s(float64=1) %!s(float64=525.43808908431) %!s(float64=527.15476824665) %!s(float64=518.83990325366) %!s(float64=519.89484575565) %!s(float64=1.26059e+07)] [2013-01-02 %!s(float64=553.82) %!s(float64=555) %!s(float64=541.63) %!s(float64=549.03) %!s(float64=2.00185e+07) %!s(float64=0) %!s(float64=1) %!s(float64=531.13477859508) %!s(float64=532.26644418813) %!s(float64=519.44409759571) %!s(float64=526.54098351822) %!s(float64=2.00185e+07)]]}
493 | 
494 | 495 | 496 |
497 |
498 | 499 | 500 | 501 | 502 | 503 |

type QuandlResponse

504 |
type QuandlResponse struct {
505 |     SourceCode string      `json:"source_code"`
506 |     SourceName string      `json:"source_name"`
507 |     Code       string      `json:"code"`
508 |     Frequency  string      `json:"frequency"`
509 |     FromDate   string      `json:"from_date"`
510 |     ToDate     string      `json:"to_date"`
511 |     Columns    []string    `json:"column_names"`
512 |     Data       interface{} `json:"data"`
513 | }
514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 |

func GetAllHistory

525 |
func GetAllHistory(identifier string) (*QuandlResponse, error)
526 |

527 | GetAllHistory is similar to GetData except that it does not restrict a date range 528 |

529 | 530 |
531 | 534 |
535 |

Example

536 | 537 | 538 | 539 |

Code:

540 |
GetAllHistory("DMDRN/MSFT_MKT_CAP")
541 | 
542 | 
543 | 544 |

Output:

545 |
&{DMDRN Damodaran Financial Data MSFT_MKT_CAP annual 2000-06-30 2013-06-30 [Date Market Capitalization] [[2013-06-30 %!s(float64=312297.5)] [2012-06-30 %!s(float64=227057.1)] [2011-06-30 %!s(float64=217062.1)] [2010-06-30 %!s(float64=241362.8)] [2009-06-30 %!s(float64=275188)] [2008-06-30 %!s(float64=172089.1)] [2007-06-30 %!s(float64=336499.4)] [2006-06-30 %!s(float64=294403.6)] [2005-06-30 %!s(float64=280921.5)] [2004-06-30 %!s(float64=292811.8)] [2003-06-30 %!s(float64=293355.8)] [2002-06-30 %!s(float64=300819.4)] [2001-06-30 %!s(float64=364524.4)] [2000-06-30 %!s(float64=281947.4)]]}
546 | 
547 | 548 | 549 |
550 |
551 | 552 | 553 | 554 |

func GetData

555 |
func GetData(identifier string, startDate string, endDate string) (*QuandlResponse, error)
556 |

557 | GetData gets Quandl data for a particular identifier and a date range. 558 | You can optionally set the auth token before running this function so that you 559 | can make unlimited API calls instead of being limited to 500/day. 560 |

561 | 562 | 563 | 564 | 565 | 566 | 567 |

func (*QuandlResponse) GetTimeSeries

568 |
func (q *QuandlResponse) GetTimeSeries(column string) ([]string, []float64)
569 |

570 | GetTimeSeries returns a date vector and the value vector for a particular 571 | column in the QuandlResponse 572 |

573 | 574 | 575 | 576 | 577 | 578 |

func (*QuandlResponse) GetTimeSeriesColumn

579 |
func (q *QuandlResponse) GetTimeSeriesColumn(column string) []float64
580 |

581 | GetTimeSeriesColumn returns the data from the Quandl response for a particular column. 582 | For some series, particularly stock data, multiple columns are returned. Using this 583 | method you can specify the specific column to extract. 584 |

585 | 586 | 587 | 588 | 589 | 590 |

func (*QuandlResponse) GetTimeSeriesData

591 |
func (q *QuandlResponse) GetTimeSeriesData() ([]float64, string)
592 |

593 | GetTimeSeriesData returns the most relevant data column from the Quandl response. 594 | In many cases you will not necessarily know beforehand what type of data is being 595 | requested and therefore cannot determine if it's stock data vs. economic data. In 596 | such cases, you can use this function to grab the column that is most likely relevant. 597 | The method also returns the most relevant 598 |

599 | 600 | 601 | 602 | 603 | 604 |

func (*QuandlResponse) GetTimeSeriesDate

605 |
func (q *QuandlResponse) GetTimeSeriesDate() []string
606 |

607 | GetTimeSeriesDate returns the series of dates in the time series 608 |

609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | -------------------------------------------------------------------------------- /quandl/quandl.go: -------------------------------------------------------------------------------- 1 | package quandl 2 | 3 | import ( 4 | "bufio" 5 | "encoding/csv" 6 | "encoding/json" 7 | "fmt" 8 | "io" 9 | "io/ioutil" 10 | "log" 11 | "net/http" 12 | "strings" 13 | ) 14 | 15 | const ( 16 | quandlApiRoot = "http://www.quandl.com/api/v1/datasets/" 17 | quandlSearchRoot = "http://www.quandl.com/api/v1/datasets.json" 18 | 19 | quandlStockList = "https://s3.amazonaws.com/quandl-static-content/quandl-stock-code-list.csv" 20 | quandlStockWikiList = "https://s3.amazonaws.com/quandl-static-content/Ticker+CSV%27s/WIKI_tickers.csv" 21 | sectorList = "https://s3.amazonaws.com/quandl-static-content/Ticker+CSV%27s/Stock+Exchanges/stockinfo.csv" 22 | etfList = "https://s3.amazonaws.com/quandl-static-content/Ticker+CSV%27s/ETFs.csv" 23 | stockIndexList = "https://s3.amazonaws.com/quandl-static-content/Ticker+CSV%27s/Stock+Exchanges/Indicies.csv" 24 | mutualFundList = "https://s3.amazonaws.com/quandl-static-content/Ticker+CSV%27s/Stock+Exchanges/funds.csv" 25 | 26 | // Code already contains the source 27 | commoditiesList = "https://s3.amazonaws.com/quandl-static-content/Ticker+CSV%27s/commodities.csv" 28 | 29 | // Source is in the file and needs to be pre-pended 30 | currencyList = "https://s3.amazonaws.com/quandl-static-content/Ticker+CSV%27s/currencies.csv" 31 | 32 | spxConstituents = "https://s3.amazonaws.com/quandl-static-content/Ticker+CSV%27s/Indicies/SP500.csv" 33 | dowConstituents = "https://s3.amazonaws.com/quandl-static-content/Ticker+CSV%27s/Indicies/dowjonesIA.csv" 34 | nasdaqCompositeConstituents = "https://s3.amazonaws.com/quandl-static-content/Ticker+CSV%27s/Indicies/NASDAQComposite.csv" 35 | nasdaq100Constituents = "https://s3.amazonaws.com/quandl-static-content/Ticker+CSV%27s/Indicies/nasdaq100.csv" 36 | ftse100Constituents = "https://s3.amazonaws.com/quandl-static-content/Ticker+CSV%27s/Indicies/FTSE100.csv" 37 | 38 | // Note that this data is pipe-delimited rather than comma delimited 39 | economicData = "https://s3.amazonaws.com/quandl-static-content/Ticker+CSV%27s/FRED/fred_allcodes.csv" 40 | 41 | format = ".json" 42 | ) 43 | 44 | var authToken string 45 | 46 | type QuandlResponse struct { 47 | SourceCode string `json:"source_code"` 48 | SourceName string `json:"source_name"` 49 | Code string `json:"code"` 50 | Frequency string `json:"frequency"` 51 | FromDate string `json:"from_date"` 52 | ToDate string `json:"to_date"` 53 | Columns []string `json:"column_names"` 54 | Data interface{} `json:"data"` 55 | } 56 | 57 | /*type TimeSeriesDataPoint struct { 58 | Date string 59 | Data float64 60 | } 61 | 62 | type TimeSeries struct { 63 | Data []TimeSeriesDataPoint 64 | }*/ 65 | 66 | // SetAuthToken sets the auth token globally so that all subsequent calls that 67 | // retrieve data from the Quandl API will use the auth token. 68 | func SetAuthToken(token string) { 69 | authToken = token 70 | } 71 | 72 | func assembleQueryURL(query string) string { 73 | var url string 74 | 75 | if authToken == "" { 76 | fmt.Printf("No auth token set. API calls are limited.\n") 77 | url = fmt.Sprintf("%s?query=%s", quandlSearchRoot, query) 78 | } else { 79 | url = fmt.Sprintf("%s?query=%s&auth_token=%s", quandlSearchRoot, query, authToken) 80 | } 81 | return url 82 | } 83 | 84 | func assembleURLwithDates(identifier string, startDate string, endDate string) string { 85 | var url string 86 | 87 | if authToken == "" { 88 | fmt.Printf("No auth token set. API calls are limited.\n") 89 | url = fmt.Sprintf("%s%s%s?trim_start=%s&trim_end=%s", quandlApiRoot, identifier, format, startDate, endDate) 90 | } else { 91 | url = fmt.Sprintf("%s%s%s?trim_start=%s&trim_end=%s&auth_token=%s", quandlApiRoot, identifier, format, startDate, endDate, authToken) 92 | } 93 | return url 94 | } 95 | 96 | func assembleURLwithoutDates(identifier string) string { 97 | var url string 98 | if authToken == "" { 99 | fmt.Printf("No auth token set. API calls are limited.\n") 100 | url = fmt.Sprintf("%s%s%s", quandlApiRoot, identifier, format) 101 | } else { 102 | url = fmt.Sprintf("%s%s%s?auth_token=%s", quandlApiRoot, identifier, format, authToken) 103 | } 104 | return url 105 | } 106 | 107 | func readBytesFromUrl(url string) ([]byte, error) { 108 | resp, err := http.Get(url) 109 | if err != nil { 110 | log.Fatal(err) 111 | return nil, err 112 | } 113 | 114 | defer resp.Body.Close() 115 | body, err := ioutil.ReadAll(resp.Body) 116 | 117 | return body, err 118 | } 119 | 120 | func getDataFromURL(url string) (*QuandlResponse, error) { 121 | //fmt.Printf("%s\n", url) 122 | 123 | body, err := readBytesFromUrl(url) 124 | if err != nil { 125 | log.Fatal(err) 126 | return nil, err 127 | } 128 | 129 | var quandlResponse *QuandlResponse 130 | 131 | err = json.Unmarshal(body, &quandlResponse) 132 | if err != nil { 133 | log.Fatal(err) 134 | return nil, err 135 | } 136 | 137 | //fmt.Printf("%s\n", quandlResponse) 138 | return quandlResponse, nil 139 | } 140 | 141 | // GetData gets Quandl data for a particular identifier and a date range. 142 | // You can optionally set the auth token before running this function so that you 143 | // can make unlimited API calls instead of being limited to 500/day. 144 | func GetData(identifier string, startDate string, endDate string) (*QuandlResponse, error) { 145 | url := assembleURLwithDates(identifier, startDate, endDate) 146 | 147 | return getDataFromURL(url) 148 | } 149 | 150 | // GetAllHistory is similar to GetData except that it does not restrict a date range 151 | func GetAllHistory(identifier string) (*QuandlResponse, error) { 152 | url := assembleURLwithoutDates(identifier) 153 | 154 | return getDataFromURL(url) 155 | } 156 | 157 | // GetTimeSeriesColumn returns the data from the Quandl response for a particular column. 158 | // For some series, particularly stock data, multiple columns are returned. Using this 159 | // method you can specify the specific column to extract. 160 | func (q *QuandlResponse) GetTimeSeriesColumn(column string) []float64 { 161 | _, data := q.GetTimeSeries(column) 162 | 163 | return data 164 | } 165 | 166 | // GetTimeSeriesData returns the most relevant data column from the Quandl response. 167 | // In many cases you will not necessarily know beforehand what type of data is being 168 | // requested and therefore cannot determine if it's stock data vs. economic data. In 169 | // such cases, you can use this function to grab the column that is most likely relevant. 170 | // The method also returns the most relevant 171 | func (q *QuandlResponse) GetTimeSeriesData() ([]float64, string) { 172 | column := q.getLikelyDataColumnName() 173 | 174 | _, data := q.GetTimeSeries(column) 175 | 176 | return data, column 177 | } 178 | 179 | // GetTimeSeriesDate returns the series of dates in the time series 180 | func (q *QuandlResponse) GetTimeSeriesDate() []string { 181 | column := q.getLikelyDataColumnName() 182 | 183 | date, _ := q.GetTimeSeries(column) 184 | 185 | return date 186 | } 187 | 188 | // GetTimeSeries returns a date vector and the value vector for a particular 189 | // column in the QuandlResponse 190 | func (q *QuandlResponse) GetTimeSeries(column string) ([]string, []float64) { 191 | if q.Data == nil { 192 | return nil, nil 193 | } 194 | 195 | dataArray := q.Data.([]interface{}) 196 | 197 | dateVector := make([]string, 0, len(dataArray)) 198 | dataVector := make([]float64, 0, len(dataArray)) 199 | dateColumnNum := q.getColumnNum("Date") 200 | dataColumnNum := q.getColumnNum(column) 201 | 202 | for k, v := range dataArray { 203 | switch vv := v.(type) { 204 | case []interface{}: 205 | // Check that 0 is the date 206 | switch vv[dateColumnNum].(type) { 207 | case string: 208 | dateVector = append(dateVector, vv[dateColumnNum].(string)) 209 | default: 210 | fmt.Printf("Problem reading %q as a string.\n", vv[dateColumnNum]) 211 | return nil, nil 212 | } 213 | 214 | // Match the right column with the requested column 215 | switch vv[dataColumnNum].(type) { 216 | case float64: 217 | dataVector = append(dataVector, vv[dataColumnNum].(float64)) 218 | case nil: 219 | dataVector = append(dataVector, 0) 220 | default: 221 | fmt.Printf("Problem reading %q as a float64.\n", vv[dataColumnNum]) 222 | return nil, nil 223 | } 224 | default: 225 | fmt.Println(k, "is of a type I don't know how to handle") 226 | return nil, nil 227 | } 228 | } 229 | 230 | return dateVector, dataVector 231 | } 232 | 233 | // getLikelyDataColumnName finds the column most likely to be the "data" 234 | // column. It either uses adjusted close or just takes the last column in the series 235 | func (q *QuandlResponse) getLikelyDataColumnName() string { 236 | adjustedCloseColumn := q.getColumnNum("Adj. Close") 237 | 238 | if len(q.Columns) < 1 { 239 | return "N/A" 240 | } else if adjustedCloseColumn == -1 { 241 | return q.Columns[len(q.Columns)-1] 242 | } else { 243 | return q.Columns[adjustedCloseColumn] 244 | } 245 | } 246 | 247 | // getColumnNum returns the column number associated with a particular column name. 248 | // It returns -1 if the column is not found. 249 | func (q *QuandlResponse) getColumnNum(column string) int { 250 | for i, v := range q.Columns { 251 | if v == column { 252 | return i 253 | } 254 | } 255 | 256 | return -1 257 | } 258 | 259 | // Search executes a query against the Quandl API and returns the JSON object 260 | // as a byte stream. In future releases of this Go (golang) Quandl package 261 | // this will return a native object instead of the json 262 | func Search(query string) ([]byte, error) { 263 | query = strings.Replace(query, " ", "+", -1) 264 | 265 | url := assembleQueryURL(query) 266 | 267 | body, err := readBytesFromUrl(url) 268 | 269 | return body, err 270 | } 271 | 272 | func loadPipeDelimited(url string) [][]string { 273 | resp, err := http.Get(url) 274 | if err != nil { 275 | log.Fatal(err) 276 | return nil 277 | } 278 | 279 | defer resp.Body.Close() 280 | 281 | reader := csv.NewReader(resp.Body) 282 | reader.Comma = '|' 283 | 284 | records, _ := reader.ReadAll() 285 | 286 | return records 287 | } 288 | 289 | type linefeedConverter struct { 290 | r *bufio.Reader 291 | } 292 | 293 | func newLinefeedConverter(r io.Reader) io.Reader { 294 | return linefeedConverter{bufio.NewReader(r)} 295 | } 296 | 297 | func (r linefeedConverter) Read(b []byte) (int, error) { 298 | n, err := r.r.Read(b) 299 | if err != nil { 300 | return n, err 301 | } 302 | b = b[:n] 303 | for i := range b { 304 | if b[i] == '\r' { 305 | var next byte 306 | if j := i + 1; j < len(b) { 307 | next = b[j] 308 | } else { 309 | next, err = r.r.ReadByte() 310 | if err == nil { 311 | r.r.UnreadByte() 312 | } 313 | } 314 | if next != '\n' { 315 | b[i] = '\n' 316 | } 317 | // } else if b[i] == '!' { // ! character confuses cvsReader 318 | // // fmt.Print("!FOUND!") 319 | // b[i] = '_' 320 | } 321 | // fmt.Printf("%c", b[i]) 322 | } 323 | fmt.Println("buffer", string(b), "length", n) 324 | return n, err 325 | } 326 | 327 | func loadCSVMac(url string) (records [][]string) { 328 | resp, err := http.Get(url) 329 | if err != nil { 330 | log.Fatal(err) 331 | return nil 332 | } 333 | 334 | defer resp.Body.Close() 335 | 336 | c, err := ioutil.ReadAll(resp.Body) 337 | if err != nil { 338 | log.Fatal(err) 339 | return nil 340 | } 341 | cs := strings.Replace(string(c), "\r", "\n", -1) 342 | 343 | reader := csv.NewReader(strings.NewReader(cs)) 344 | 345 | // for i := 0; ; i++ { 346 | // record, err := reader.Read() 347 | // if err == io.EOF { 348 | // break 349 | // } else if err != nil { 350 | // fmt.Println("line", i, "error", err) 351 | // break 352 | // } 353 | // records = append(records, record) 354 | // } 355 | records, _ = reader.ReadAll() 356 | 357 | return records 358 | } 359 | 360 | func loadCSV(url string) [][]string { 361 | //file, err := os.Open(fileName) 362 | resp, err := http.Get(url) 363 | if err != nil { 364 | log.Fatal(err) 365 | return nil 366 | } 367 | 368 | defer resp.Body.Close() 369 | 370 | reader := csv.NewReader(resp.Body) 371 | 372 | // for i := 0; true; i++ { 373 | // record, err := reader.Read() 374 | 375 | // if err == io.EOF { 376 | // break 377 | // } else if err != nil { 378 | // log.Fatal(err) 379 | // return nil 380 | // } else { 381 | // if i <= 1 { 382 | // fmt.Printf("%q\n", record) 383 | // } 384 | // } 385 | // } 386 | 387 | records, _ := reader.ReadAll() 388 | 389 | return records 390 | } 391 | 392 | func getCsvColumnNumber(csvArray [][]string, column string) int { 393 | for i, v := range csvArray[0][:] { 394 | if v == column { 395 | return i 396 | } 397 | } 398 | 399 | return -1 400 | } 401 | 402 | // Get various lists 403 | func extractColumns(csvArray [][]string, column1 int, column2 int, skipHeader bool) ([]string, []string) { 404 | identifier := make([]string, 0, len(csvArray)) 405 | description := make([]string, 0, len(csvArray)) 406 | 407 | for i, v := range csvArray[:] { 408 | for j, v2 := range v { 409 | // If the header is included then we use the first row 410 | // otherwise we skip the first row 411 | if (!skipHeader && i == 0) || i > 0 { 412 | if j == column1 { 413 | identifier = append(identifier, v2) 414 | } else if j == column2 { 415 | description = append(description, v2) 416 | } 417 | } 418 | } 419 | } 420 | 421 | return identifier, description 422 | } 423 | 424 | // GetAllSecurityList gets all the security identifiers and descriptions 425 | func GetAllSecurityList() ([]string, []string) { 426 | 427 | identifier, description := GetStockList() 428 | 429 | tempIdentifier, tempDescription := GetStockTickerList() 430 | identifier = append(identifier, tempIdentifier...) 431 | description = append(description, tempDescription...) 432 | 433 | tempIdentifier, tempDescription = GetETFList() 434 | identifier = append(identifier, tempIdentifier...) 435 | description = append(description, tempDescription...) 436 | 437 | tempIdentifier, tempDescription = GetETFTickerList() 438 | identifier = append(identifier, tempIdentifier...) 439 | description = append(description, tempDescription...) 440 | 441 | tempIdentifier, tempDescription = GetStockIndexList() 442 | identifier = append(identifier, tempIdentifier...) 443 | description = append(description, tempDescription...) 444 | 445 | tempIdentifier, tempDescription = GetCommoditiesList() 446 | identifier = append(identifier, tempIdentifier...) 447 | description = append(description, tempDescription...) 448 | 449 | tempIdentifier, tempDescription = GetBitcoinList() 450 | identifier = append(identifier, tempIdentifier...) 451 | description = append(description, tempDescription...) 452 | 453 | return identifier, description 454 | } 455 | 456 | // GetStockList gets all the Quandl stock codes and descriptions 457 | func GetStockList() ([]string, []string) { 458 | list := loadCSV(quandlStockWikiList) 459 | 460 | return extractColumns(list, 0, 1, true) 461 | } 462 | 463 | // GetStockTickerList gets all the Quandl codes and tickers 464 | func GetStockTickerList() ([]string, []string) { 465 | list := loadCSV(quandlStockList) 466 | 467 | return extractColumns(list, 2, 0, true) 468 | } 469 | 470 | // GetETFList gets all the Quandl codes and ETF descriptions 471 | func GetETFList() ([]string, []string) { 472 | list := loadCSV(etfList) 473 | 474 | return extractColumns(list, 1, 2, true) 475 | } 476 | 477 | // GetETFTickerList gets all the Quandl codes and ETF tickers 478 | func GetETFTickerList() ([]string, []string) { 479 | list := loadCSV(etfList) 480 | 481 | return extractColumns(list, 1, 0, true) 482 | } 483 | 484 | // GetStockIndexList gets all the Quandl codes and stock index descriptions 485 | func GetStockIndexList() ([]string, []string) { 486 | list := loadCSV(stockIndexList) 487 | 488 | return extractColumns(list, 1, 2, true) 489 | } 490 | 491 | // GetCommoditiesList gets all the Quandl codes and commodity descriptions 492 | func GetCommoditiesList() ([]string, []string) { 493 | list := loadCSV(commoditiesList) 494 | 495 | return extractColumns(list, 1, 0, true) 496 | } 497 | 498 | // GetBitcoinList just returns http://www.quandl.com/api/v1/datasets/BITCOIN/BITSTAMPUSD 499 | func GetBitcoinList() ([]string, []string) { 500 | identifier := make([]string, 1, 1) 501 | description := make([]string, 1, 1) 502 | 503 | identifier[0] = "BITCOIN/BITSTAMPUSD" 504 | description[0] = "Bitcoin Exchange Rate (BTC vs. USD) on Bitstamp" 505 | return identifier, description 506 | } 507 | 508 | // Data item identifier 509 | // GetAllDataItemList 510 | 511 | // GetFinancialRatiosList returns the list of Damordoran financial ratios. Currently 512 | // this list is hard-coded into the file because Quandl does not provide a file from 513 | // where to read. A caveat about using these is that you need to append the ticker 514 | // in a particular way to use these ratios 515 | func GetFinancialRatiosList() ([]string, []string) { 516 | test := [][]string{{"FLOAT", "Number of Shares Outstanding"}, 517 | {"INSIDER", "Insider Holdings"}, 518 | {"CAPEX", "Capital Expenditures"}, 519 | {"NET_MARG", "Net Margin"}, 520 | {"INV_CAP", "Invested Capital"}, 521 | {"P_S", "Price to Sales Ratio"}, 522 | {"ROC", "Return on Capital"}, 523 | {"STOCK_PX", "Stock Price"}, 524 | {"MKT_DE", "Market Debt to Equity Ratio"}, 525 | {"CORREL", "Correlation with the Market"}, 526 | {"PE_FWD", "Forward PE Ratio"}, 527 | {"REV_GRO", "Previous Year Growth in Revenues"}, 528 | {"EBIT_1T", "EBIT for Previous Period"}, 529 | {"DIV", "Dividends"}, 530 | {"EPS_FWD", "Forward Earnings Per Share"}, 531 | {"CHG_NCWC", "Change in Non-Cash Working Capital"}, 532 | {"CASH_FV", "Cash as Percentage of Firm Value"}, 533 | {"INST_HOLD", "Institutional Holdings"}, 534 | {"EFF_TAX", "Effective Tax Rate"}, 535 | {"CASH_ASSETS", "Cash as Percentage of Total Assets"}, 536 | {"FIXED_TOT", "Ratio of Fixed Assets to Total Assets"}, 537 | {"BETA_VL", "Value Line Beta"}, 538 | {"BV_ASSETS", "Book Value of Assets"}, 539 | {"BV_EQTY", "Book Value of Equity"}, 540 | {"FCFF", "Free Cash Flow to Firm"}, 541 | {"CASH_REV", "Cash as Percentage of Revenues"}, 542 | {"MKT_CAP", "Market Capitalization"}, 543 | {"EFF_TAX_INC", "Effective Tax Rate on Income"}, 544 | {"EV_SALES", "EV To Sales Ratio"}, 545 | {"TOT_DEBT", "Total Debt"}, 546 | {"INTANG_TOT", "Ratio of Intangible Assets to Total Assets"}, 547 | {"PE_G", "PE to Growth Ratio"}, 548 | {"REINV_RATE", "Reinvestment Rate"}, 549 | {"BOOK_DC", "Book Debt to Capital Ratio"}, 550 | {"EPS_GRO_EXP", "Expected Growth in Earnings Per Share"}, 551 | {"EV_EBIT", "EV to EBIT Ratio"}, 552 | {"PE_CURR", "Current PE Ratio"}, 553 | {"MKT_DC", "Market Debt to Capital Ratio"}, 554 | {"NCWC_REV", "Non-Cash Working Capital as Percentage of Revenues"}, 555 | {"REV_12M", "Trailing 12-month Revenues"}, 556 | {"REV_GRO_EXP", "Expected Growth in Revenues"}, 557 | {"REV_TRAIL", "Trailing Revenues"}, 558 | {"ROE", "Return on Equity"}, 559 | {"EV_EBITDA", "EV to EBITDA Ratio"}, 560 | {"EBITDA", "Earnings Before Interest Taxes Depreciation and Amortization"}, 561 | {"BETA", "3-Year Regression Beta"}, 562 | {"DEPREC", "Depreciation"}, 563 | {"EV_SALESTR", "EV to Trailing Sales Ratio"}, 564 | {"EPS_GRO", "Growth in Earnings Per Share"}, 565 | {"P_BV", "Price to Book Value Ratio"}, 566 | {"NET_INC_TRAIL", "Trailing Net Income"}, 567 | {"PE_TRAIL", "Trailing PE Ratio"}, 568 | {"OP_MARG", "Pre-Tax Operating Margin"}, 569 | {"FIRM_VAL", "Firm Value"}, 570 | {"STDEV", "3-year Standard Deviation of Stock Price"}, 571 | {"TRAD_VOL", "Trading Volume"}, 572 | {"CASH", "Cash"}, 573 | {"DIV_YLD", "Dividend Yield"}, 574 | {"REV_LAST", "Revenues"}, 575 | {"NET_INC", "Net Income"}, 576 | {"EV_BV", "EV to Book Value Ratio"}, 577 | {"REINV", "Reinvestment Amount"}, 578 | {"EBIT", "Earnings Before Interest and Taxes"}, 579 | {"EV_CAP", "EV to Invested Capital Ratio"}, 580 | {"PAYOUT", "Payout Ratio"}, 581 | {"HILO", "Hi-Lo Risk"}, 582 | {"ALLFINANCIALRATIOS", "All Financial Ratios"}, 583 | {"SGA", "Sales General and Administration Expenses"}, 584 | {"EV", "Enterprise Value"}, 585 | {"NCWC", "Non-Cash Working Capital"}, 586 | } 587 | 588 | return extractColumns(test, 0, 1, false) 589 | } 590 | 591 | // Economic data (doesn't pertain to a particular security) 592 | // GetEconomicDataList 593 | func GetEconomicDataList() ([]string, []string) { 594 | list := loadPipeDelimited(economicData) 595 | 596 | identifier, description := extractColumns(list, 0, 1, true) 597 | 598 | return prependList("FRED/", identifier), description 599 | } 600 | 601 | // Index membership 602 | // GetSP500Constituents 603 | func GetSP500Constituents() ([]string, []string) { 604 | //fmt.Printf("%s\n", spxConstituents) 605 | list := loadCSVMac(spxConstituents) 606 | /*need to prepend col 0 ticker with WIKI*/ 607 | 608 | identifier, description := extractColumns(list, 0, 2, true) 609 | 610 | return prependList("WIKI/", identifier), description 611 | } 612 | 613 | // GetDowConstituents 614 | func GetDowConstituents() ([]string, []string) { 615 | list := loadCSV(dowConstituents) 616 | /*need to prepend col 0 ticker with WIKI*/ 617 | 618 | identifier, description := extractColumns(list, 0, 2, true) 619 | 620 | return prependList("WIKI/", identifier), description 621 | } 622 | 623 | // GetNasdaqCompositeConstituents 624 | func GetNasdaqCompositeConstituents() ([]string, []string) { 625 | list := loadCSV(nasdaqCompositeConstituents) 626 | /*need to prepend col 0 ticker with WIKI*/ 627 | 628 | identifier, description := extractColumns(list, 0, 2, true) 629 | 630 | return prependList("WIKI/", identifier), description 631 | } 632 | 633 | // GetNasdaq100Constituents 634 | func GetNasdaq100Constituents() ([]string, []string) { 635 | list := loadCSV(nasdaq100Constituents) 636 | /*need to prepend col 0 ticker with WIKI*/ 637 | 638 | identifier, description := extractColumns(list, 0, 2, true) 639 | 640 | return prependList("WIKI/", identifier), description 641 | } 642 | 643 | // GetFTSE100Constituents 644 | func GetFTSE100Constituents() ([]string, []string) { 645 | list := loadCSV(ftse100Constituents) 646 | 647 | identifier, description := extractColumns(list, 1, 2, true) 648 | 649 | return identifier, description 650 | } 651 | 652 | // Sector mappings 653 | // GetSP500SectorMappings 654 | func GetSP500SectorMappings() ([]string, []string) { 655 | list := loadCSVMac(spxConstituents) 656 | 657 | identifier, description := extractColumns(list, 0, 3, true) 658 | 659 | return prependList("WIKI/", identifier), description 660 | } 661 | 662 | func prependList(prefix string, list []string) []string { 663 | newList := make([]string, len(list), len(list)) 664 | 665 | for i, v := range list { 666 | newList[i] = fmt.Sprintf("%s%s", prefix, v) 667 | } 668 | 669 | return newList 670 | } 671 | -------------------------------------------------------------------------------- /quandl/quandl_test.go: -------------------------------------------------------------------------------- 1 | package quandl 2 | 3 | import "fmt" 4 | 5 | func ExampleSetAuthToken() { 6 | SetAuthToken("") 7 | 8 | x, _ := GetData("WIKI/AAPL", "2013-01-01", "2013-01-05") 9 | x.ToDate = "2014-05-22" 10 | fmt.Printf("%s\n", x) 11 | 12 | // Output: 13 | // &{WIKI Quandl Open Data AAPL daily 1980-12-12 2014-05-22 [Date Open High Low Close Volume Ex-Dividend Split Ratio Adj. Open Adj. High Adj. Low Adj. Close Adj. Volume] [[2013-01-04 %!s(float64=536.97) %!s(float64=538.63) %!s(float64=525.83) %!s(float64=527) %!s(float64=2.12262e+07) %!s(float64=0) %!s(float64=1) %!s(float64=73.613294063499) %!s(float64=73.840863700808) %!s(float64=72.086109870961) %!s(float64=72.24650533822) %!s(float64=1.485834e+08)] [2013-01-03 %!s(float64=547.88) %!s(float64=549.67) %!s(float64=541) %!s(float64=542.1) %!s(float64=1.26059e+07) %!s(float64=0) %!s(float64=1) %!s(float64=75.108947523158) %!s(float64=75.354338879051) %!s(float64=74.165767339615) %!s(float64=74.316566496868) %!s(float64=8.82413e+07)] [2013-01-02 %!s(float64=553.82) %!s(float64=555) %!s(float64=541.63) %!s(float64=549.03) %!s(float64=2.00185e+07) %!s(float64=0) %!s(float64=1) %!s(float64=75.923262972321) %!s(float64=76.08502934101) %!s(float64=74.252134129678) %!s(float64=75.266601187558) %!s(float64=1.401295e+08)]]} 14 | } 15 | 16 | func ExampleGetDataStockPrice() { 17 | x, _ := GetData("WIKI/AAPL", "2013-01-01", "2013-01-05") 18 | x.ToDate = "2014-05-22" 19 | fmt.Printf("%s\n", x) 20 | 21 | // Output: 22 | // &{WIKI Quandl Open Data AAPL daily 1980-12-12 2014-05-22 [Date Open High Low Close Volume Ex-Dividend Split Ratio Adj. Open Adj. High Adj. Low Adj. Close Adj. Volume] [[2013-01-04 %!s(float64=536.97) %!s(float64=538.63) %!s(float64=525.83) %!s(float64=527) %!s(float64=2.12262e+07) %!s(float64=0) %!s(float64=1) %!s(float64=73.613294063499) %!s(float64=73.840863700808) %!s(float64=72.086109870961) %!s(float64=72.24650533822) %!s(float64=1.485834e+08)] [2013-01-03 %!s(float64=547.88) %!s(float64=549.67) %!s(float64=541) %!s(float64=542.1) %!s(float64=1.26059e+07) %!s(float64=0) %!s(float64=1) %!s(float64=75.108947523158) %!s(float64=75.354338879051) %!s(float64=74.165767339615) %!s(float64=74.316566496868) %!s(float64=8.82413e+07)] [2013-01-02 %!s(float64=553.82) %!s(float64=555) %!s(float64=541.63) %!s(float64=549.03) %!s(float64=2.00185e+07) %!s(float64=0) %!s(float64=1) %!s(float64=75.923262972321) %!s(float64=76.08502934101) %!s(float64=74.252134129678) %!s(float64=75.266601187558) %!s(float64=1.401295e+08)]]} 23 | } 24 | 25 | func ExampleGetDataStockFundamentals() { 26 | x, _ := GetData("DMDRN/MSFT_MKT_CAP", "2000-01-01", "2013-01-05") 27 | fmt.Printf("%s\n", x) 28 | 29 | // Output: 30 | // &{DMDRN Damodaran Financial Data MSFT_MKT_CAP annual 2000-06-30 2013-06-30 [Date Market Capitalization] [[2012-06-30 %!s(float64=227057.1)] [2011-06-30 %!s(float64=217062.1)] [2010-06-30 %!s(float64=241362.8)] [2009-06-30 %!s(float64=275188)] [2008-06-30 %!s(float64=172089.1)] [2007-06-30 %!s(float64=336499.4)] [2006-06-30 %!s(float64=294403.6)] [2005-06-30 %!s(float64=280921.5)] [2004-06-30 %!s(float64=292811.8)] [2003-06-30 %!s(float64=293355.8)] [2002-06-30 %!s(float64=300819.4)] [2001-06-30 %!s(float64=364524.4)] [2000-06-30 %!s(float64=281947.4)]]} 31 | } 32 | 33 | func ExampleGetTimeSeriesDate() { 34 | q, _ := GetData("DMDRN/MSFT_MKT_CAP", "2000-01-01", "2013-01-05") 35 | 36 | dates := q.GetTimeSeriesDate() 37 | 38 | fmt.Printf("%q\n", dates) 39 | 40 | // Output: 41 | // ["2012-06-30" "2011-06-30" "2010-06-30" "2009-06-30" "2008-06-30" "2007-06-30" "2006-06-30" "2005-06-30" "2004-06-30" "2003-06-30" "2002-06-30" "2001-06-30" "2000-06-30"] 42 | } 43 | 44 | func ExampleGetTimeSeriesData() { 45 | q, _ := GetData("DMDRN/MSFT_MKT_CAP", "2000-01-01", "2013-01-05") 46 | 47 | dates, column := q.GetTimeSeriesData() 48 | 49 | fmt.Printf("%s: %v\n", column, dates) 50 | 51 | // Output: 52 | // Market Capitalization: [227057.1 217062.1 241362.8 275188 172089.1 336499.4 294403.6 280921.5 292811.8 293355.8 300819.4 364524.4 281947.4] 53 | } 54 | 55 | func ExampleGetAllHistory() { 56 | x, _ := GetAllHistory("DMDRN/MSFT_MKT_CAP") 57 | fmt.Printf("%s\n", x) 58 | 59 | // Output: 60 | // &{DMDRN Damodaran Financial Data MSFT_MKT_CAP annual 2000-06-30 2013-06-30 [Date Market Capitalization] [[2013-06-30 %!s(float64=312297.5)] [2012-06-30 %!s(float64=227057.1)] [2011-06-30 %!s(float64=217062.1)] [2010-06-30 %!s(float64=241362.8)] [2009-06-30 %!s(float64=275188)] [2008-06-30 %!s(float64=172089.1)] [2007-06-30 %!s(float64=336499.4)] [2006-06-30 %!s(float64=294403.6)] [2005-06-30 %!s(float64=280921.5)] [2004-06-30 %!s(float64=292811.8)] [2003-06-30 %!s(float64=293355.8)] [2002-06-30 %!s(float64=300819.4)] [2001-06-30 %!s(float64=364524.4)] [2000-06-30 %!s(float64=281947.4)]]} 61 | } 62 | 63 | func Example() { 64 | x, _ := GetData("BOE/XUDLBK73", "2013-01-01", "2013-01-05") 65 | x.ToDate = "2014-05-22" 66 | fmt.Printf("%s\n", x) 67 | 68 | // Output: 69 | // &{BOE Bank of England XUDLBK73 daily 2005-04-01 2014-05-22 [Date Value] [[2013-01-04 %!s(float64=6.2303)] [2013-01-03 %!s(float64=6.2301)] [2013-01-02 %!s(float64=6.2301)]]} 70 | } 71 | 72 | func ExampleLoadCSV() { 73 | output := loadCSV(quandlStockList) 74 | 75 | fmt.Printf("%q\n", output[0:2][:]) 76 | 77 | // Output: 78 | // [["Ticker" "Stock Name" "Price Code" "Ratios Code" "In Market?"] ["A" "Agilent Technologies" "GOOG/NYSE_A" "DMDRN/A_ALLFINANCIALRATIOS" "Active"]] 79 | } 80 | 81 | func ExampleGetStockList() { 82 | identifier, description := GetStockList() 83 | 84 | fmt.Printf("%q : %q\n", identifier[0], description[0]) 85 | 86 | // Output: 87 | // "WIKI/ACT" : "Actavis, Inc." 88 | } 89 | 90 | func ExampleGetAllSecurityList() { 91 | identifier, description := GetAllSecurityList() 92 | 93 | fmt.Printf("len(identifier)=%v\n%q : %q\n", len(identifier), identifier[20000], description[20000]) 94 | 95 | // Output: 96 | // len(identifier)=21382 97 | // "GOOG/NYSEARCA_TDTT" : "TDTT" 98 | } 99 | 100 | // Commented out for now because the originating files use only \r instead of \r\n 101 | 102 | func ExampleGetSP500Constituents() { 103 | identifier, description := GetSP500Constituents() 104 | 105 | fmt.Printf("len(identifer)=%v\n", len(identifier)) 106 | fmt.Printf("len(description)=%v\n", len(description)) 107 | //fmt.Printf("%q : %q\n", identifier[0], description[0]) 108 | 109 | // Output: 110 | // len(identifer)=500 111 | // len(description)=500 112 | } 113 | 114 | func ExampleGetSP500SectorMappings() { 115 | identifier, description := GetSP500SectorMappings() 116 | 117 | fmt.Printf("len(identifer)=%v\n", len(identifier)) 118 | fmt.Printf("len(description)=%v\n", len(description)) 119 | //fmt.Printf("%q : %q\n", identifier[0], description[0]) 120 | 121 | // Output: 122 | // len(identifer)=500 123 | // len(description)=500 124 | } 125 | 126 | func ExampleGetEconomicDataList() { 127 | identifier, description := GetEconomicDataList() 128 | 129 | fmt.Printf("%q : %q\n", identifier[0], description[0]) 130 | 131 | // Output: 132 | // "FRED/LAWFIN" : "Finance and Insurance Wages and Salaries in Louisiana" 133 | } 134 | 135 | func ExampleGetFinancialRatiosList() { 136 | identifier, description := GetFinancialRatiosList() 137 | 138 | fmt.Printf("%q : %q\n", identifier[10], description[10]) 139 | 140 | // Output: 141 | // "PE_FWD" : "Forward PE Ratio" 142 | } 143 | 144 | func ExampleGetTimeSeriesColumn() { 145 | x, _ := GetData("WIKI/AAPL", "2013-01-01", "2013-01-05") 146 | c := x.GetTimeSeriesColumn("Open") 147 | fmt.Printf("%v\n", c) 148 | 149 | c = x.GetTimeSeriesColumn("High") 150 | fmt.Printf("%v\n", c) 151 | 152 | c = x.GetTimeSeriesColumn("Low") 153 | fmt.Printf("%v\n", c) 154 | 155 | c = x.GetTimeSeriesColumn("Close") 156 | fmt.Printf("%v\n", c) 157 | 158 | c = x.GetTimeSeriesColumn("Volume") 159 | fmt.Printf("%v\n", c) 160 | 161 | // Output: 162 | // [536.97 547.88 553.82] 163 | // [538.63 549.67 555] 164 | // [525.83 541 541.63] 165 | // [527 542.1 549.03] 166 | // [2.12262e+07 1.26059e+07 2.00185e+07] 167 | } 168 | 169 | func ExampleGetTimeSeriesColumnWithNil() { 170 | x, _ := GetData("GOOG/NYSEARCA_SPY", "2012-06-15", "2012-06-15") 171 | // returns [2012-06-15 133.57 0] 172 | 173 | c := x.GetTimeSeriesColumn("Open") 174 | fmt.Printf("%v\n", c) 175 | 176 | c = x.GetTimeSeriesColumn("High") 177 | fmt.Printf("%v\n", c) 178 | 179 | c = x.GetTimeSeriesColumn("Low") 180 | fmt.Printf("%v\n", c) 181 | 182 | c = x.GetTimeSeriesColumn("Close") 183 | fmt.Printf("%v\n", c) 184 | 185 | c = x.GetTimeSeriesColumn("Volume") 186 | fmt.Printf("%v\n", c) 187 | 188 | // Output: 189 | // [0] 190 | // [0] 191 | // [0] 192 | // [133.57] 193 | // [0] 194 | } 195 | --------------------------------------------------------------------------------