bitFlyer LightningのAPI経由でRからBitcoinを買う

すっかり放置していた

bitFlyer LightningのAPIをRから使う - My Life as a Mock Quant

の続き。
POST系のメソッドをやろうとして昔失敗して放置していたのだが、なんか今日やったらうまくいった。
こんなんでRからBitcoinを指値で発注できます(そして2018年6月16日22時現在の相場だと約定します)。

BITFLYER_KEY <- "<your key>"
BITFLYER_SECRET <- "<your secret>"
BITFLYER_URL <- "https://api.bitflyer.jp"
path <- "/v1/me/sendchildorder"
timestamp <- as.numeric(Sys.time())
body <- '{
  "product_code": "BTC_JPY",
  "child_order_type": "LIMIT",
  "side": "BUY",
  "price": 699000,
  "size": 0.001,
  "minute_to_expire": 10000,
  "time_in_force": "GTC"
}'
sign <- digest::hmac(paste0(timestamp, "POST", path, body), key=BITFLYER_SECRET, algo="sha256", serialize=FALSE)
header <- httr::add_headers(
  `ACCESS-KEY`=BITFLYER_KEY,
  `ACCESS-TIMESTAMP`=timestamp,
  `ACCESS-SIGN`=sign,
  `Content-Type`="application/json"
)
httr::content(httr::POST(paste0(BITFLYER_URL, path), body=body, header))

Batch処理用のCodeの書き方

適当な.jlファイル(hoge.jl)に対して

cd("path-to-source-code")
push!(LOAD_PATH, pwd())
workspace()

... great code...

と三行程度のおまじないを書いたうえで、

julia> include("path-to-souce-code/hoge.jl")

するのが楽そうか。
workspace()はなんかモジュールの被りをよし何やってくれる関数だったはず。

N個の独立な一様乱数(-1, 1)の和の標準偏差は1/3√N

手計算で確認&ボケ防止にRでチェック。

sizes <- 2**(1:15)
y <- numeric(length(sizes))
for(i in seq_along(sizes)){
  x <- numeric(10**3)
  for(j in seq_len(10**3)){
    x[j] <- sum(runif(sizes[i], min=-1, max=1))
  }
  y[i] <- sd(x)
}
plot(sizes, y)
lines(sizes, sqrt(1/3*sizes))

glue::glue()をちょっと便利に使う

glueパッケージのglue()は、いわばPythonでいう .format() を使えるようにするパッケージなわけで、以下のようにテンプレートの文字列 (ここでは"a is {a}" )を、その”傍にある”*1 変数で勝手に埋めてくれるので便利に使えるわけです。

> a <- 123
> glue::glue("a is {a}")
a is 123

このテンプレートの文字列に指定する変数は関数の引数になっててもよくて、以下のように使うこともできるのです、おお便利だ!

> f <- function(x)
+ {
+   hoge <- "aaa"
+   glue::glue("{hoge} + {x}")
+ }
> f(123)
aaa + 123

しかし、3連ドット(...)を引数にした場合、その中に所望の変数(ここではx)が入っていたとしても、うまく動きません。

> f <- function(...)
+ {
+   hoge <- "aaa"
+   glue::glue("{hoge} + {x}")
+ }
> f(x=23, y=32)
 Show Traceback
 
 Rerun with Debug
 Error in eval(parse(text = code, keep.source = FALSE), envir) : 
  object 'x' not found 

これを動かすには面倒ですが、

> f <- function(...)
+ {
+   args <- list(...)
+   for(name in names(args)){
+     assign(name, args[[name]])
+   }
+   hoge <- "aaa"
+   glue::glue("{hoge} + {x}")
+ }
> f(x=23, y=32)
aaa + 23

のように、一度3連ドット(...)が絡んでる変数を一度 "f()の環境の変数"としてassignしておく必要があります。
いやいや、これでうごいためでたい。

これを自動でやるようなPull Requestの1つでも出しましょうかねぇ。

*1:実際には (glue::glueの中から見た)parent.frame() = glueの呼び出しもとの環境

Juliaでlogsumexp

何も考えずにできた。

function logsumexp(x)
    xmax = maximum(x)
    xmax + log(sum(exp(x - xmax)))
end

> x = [1,2,3,10]
> log(sum(exp(x)))
> logsumexp(x)
> 10.001369815771387

Syntaxハイライトが効かないので、そろそろBLOG引越しの機運か。

purrr::map_dfr = lapply + dplyr::bind_rows

そういうことなんだよな〜シミュレーション系でよく使うのでメモ。

> dplyr::bind_rows(lapply(1:3, function(x){head(iris, 1)}))
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1          5.1         3.5          1.4         0.2  setosa
2          5.1         3.5          1.4         0.2  setosa
3          5.1         3.5          1.4         0.2  setosa
> purrr::map_dfr(1:3, ~ head(iris, 1))
  Sepal.Length Sepal.Width Petal.Length Petal.Width Species
1          5.1         3.5          1.4         0.2  setosa
2          5.1         3.5          1.4         0.2  setosa
3          5.1         3.5          1.4         0.2  setosa