[Ruby/AWS]alpha vantage APIを使って株のデータをRedshiftに入れる

株のデータを分析してダッシュボードを作るため、今回はAWSのデータウェアハウスサービスであるRedshiftを使うことにした。

GoogleのBig QueryやSnowFlakeのようなサービスで、以下のブログの説明がわかりやすかった。

https://qiita.com/rm_zeal/items/b77818daff6f92fc5cd3

今回の実装で割と迷うところが多かったため、備忘録として残してみた。

## まずは株のデータを取得
株のデータはAlpha Vantageという無料の株APIから取得することに。

https://www.alphavantage.co/

メインページから`GET FREE API KEY`をクリック

![スクリーンショット 2024-09-15 21.54.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754242/18d5acfe-8225-e44e-75f0-a2a4141f9204.png)

情報を入れてGETボタンを押すと簡単にキーが取得できる。

![スクリーンショット 2024-09-15 21.55.18.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754242/ee58c4ed-7f25-e3f7-8e72-a7f509427ada.png)

## APIのデータをcsvに変換
Pythonのpandasあたりを使うことが一般的だが、今回はRubyで書いてみた。

``` ruby
require 'httparty'
require 'csv'
require 'json'
require 'date'
require 'concurrent'
require 'dotenv'

Dotenv.load

API_KEY = ENV['ALPHA_VANTAGE_API_KEY']
SYMBOLS = ["AAPL", "GOOGL", "MSFT", "AMZN", "FB"]

def fetch_stock_data(symbol)
  url = "https://www.alphavantage.co/query?function=TIME_SERIES_DAILY&symbol=#{symbol}&outputsize=full&apikey=#{API_KEY}"
  response = HTTParty.get(url)
  data = JSON.parse(response.body)

  unless data.key?("Time Series (Daily)")
    puts "Fail to fetch data: #{symbol}"
    return nil
  end

  daily_data = data["Time Series (Daily)"].map do |date, values|
    [
      date,
      symbol,
      values["1. open"],
      values["2. high"],
      values["3. low"],
      values["4. close"],
      values["5. volume"]
    ]
  end

  daily_data.sort_by! { |row| Date.parse(row[0]) }.reverse!
  daily_data
end

def fetch_all_stocks(symbols)
  all_data = Concurrent::Array.new

  Concurrent::Promise.zip(*symbols.map { |symbol|
    Concurrent::Promise.execute do
      data = fetch_stock_data(symbol)
      if data
        all_data.concat(data)
        puts "Fetched #{symbol}"
      end
      sleep 12
    end
  }).wait

  all_data
end

result = fetch_all_stocks(SYMBOLS)

CSV.open("stock_data.csv", "wb") do |csv|
  csv << ["date", "symbol", "open", "high", "low", "close", "volume"]
  result.each { |row| csv << row }
end

puts "Fetched Data Completely!"
```

``` bash
$ ruby fetch_stock_data.rb

Fail to fetch data: FB
Fetched GOOGL
Fetched MSFT
Fetched AMZN
Fetched AAPL
Fetched Data Completely!
```

あ、そういえばFaceBookってMetaになったのだった。

以下のようなcsvが出力されていれば正解
``` csv
date,symbol,open,high,low,close,volume
2024-09-13,GOOGL,155.4300,158.3800,155.2100,157.4600,27509172
2024-09-12,GOOGL,153.8000,154.8200,152.6500,154.6900,29695048
2024-09-11,GOOGL,149.9200,151.5000,147.5200,151.1600,29607693
2024-09-10,GOOGL,150.4500,151.2700,148.3400,148.6600,31118765
2024-09-09,GOOGL,152.5100,153.4000,147.2150,148.7100,39260451
2024-09-06,GOOGL,157.3000,157.8300,150.5500,150.9200,37912130
```

## AWS上で処理を行う
#### 1. S3にバケットを作って出力したcsvを入れる
ローカルでもアップロードはできそうだったけど、とりあえずS3に入れることが王道らしい。

#### 2. Redshiftにクラスタを作る
（すでに作っているクラスタがなければRedshiftのメイン画面でも作れる）

![スクリーンショット 2024-09-15 22.09.03.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754242/a46f790d-5148-9d76-4d38-2fb8dad2e131.png)

#### 3. IAMロールを作る
関連サービスでRedshiftを選んで、S3のコピーができるロールを追加で付与する

#### 4. 作ったロールをRedshiftに繋げる

少し迷ったところだった。名前空間の設定で`セキュリティと暗号化`タブに行くと設定できる。

![スクリーンショット 2024-09-15 22.12.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754242/831531df-78ca-cdc1-8e07-cd44ab898f1d.png)

#### 5. データベースを作る

query editorに入って、createボタンからデータベースをつくつことができる

![スクリーンショット 2024-09-15 22.17.59.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754242/95367ad0-4964-25c0-9b33-b014e654682d.png)

#### 6. データをロードする

query editorの`Load data`から以下のような画面が開く。

![スクリーンショット 2024-09-15 22.22.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754242/6f728808-af36-1c10-c31a-07307eb785fc.png)

今回S3に入れておいたcsvを指定して次に進むと、なんとcsvからテーブルを自動的に検知してくれる。

![スクリーンショット 2024-09-15 22.23.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3754242/13675569-6357-b141-4220-58724482365f.png)

今まで設定したDatabaseとSchema、IAMロールを選択して`Create table`を押すと完了！

## おわりに
AWSさんに300ドルのクレジットをもらえるので、色々遊ぶことができる。

個人でデータウェアハウスを運営することはなかなかないと思うが、サーバーレスオーバーエンジニアリングはただただ面白い。