polarsを使った仮想通貨の時系列データの前処理と可視化まとめ(執筆途中)
polarsのimport
import polars as pl
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from datetime import timedelta
%matplotlib inline
plt.style.use('ggplot')
csvデータの読み込み
bitflyerの2023/1/18~2023/1/22日分の約定履歴を読み込みexec_dateをdatetime型に変換してprintで出力
この方法ではscan_csvで遅延評価しても変わらなかった。dtypeでdatetimeに変換する方法では効果があったが下記方法の方が速度が速かった。
path = "bitflyer/FX_BTC_JPY/trades/2023-01-22.csv"
date_target = "exec_date"
df = (
pl.read_csv(path)
.with_columns(pl.col(date_target)
.str
.strptime(pl.Datetime, strict=False))
)
print(df[:3])
┌────────┬────────────┬──────┬────────────┬──────────┬───────────────┬──────────────┬──────────────┐
│ ┆ id ┆ side ┆ price ┆ size ┆ exec_date ┆ buy_child_or ┆ sell_child_o │
│ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ der_acceptan ┆ rder_accepta │
│ i64 ┆ i64 ┆ str ┆ f64 ┆ f64 ┆ str ┆ ce_id ┆ nce_id │
│ ┆ ┆ ┆ ┆ ┆ ┆ --- ┆ --- │
│ ┆ ┆ ┆ ┆ ┆ ┆ str ┆ str │
╞════════╪════════════╪══════╪════════════╪══════════╪═══════════════╪══════════════╪══════════════╡
│ 888999 ┆ 2427730923 ┆ SELL ┆ 2.65905e6 ┆ 0.02 ┆ 2023-01-18 ┆ JRF20230118- ┆ JRF20230118- │
│ ┆ ┆ ┆ ┆ ┆ 23:58:53.543 ┆ 235852-05515 ┆ 235853-13018 │
│ ┆ ┆ ┆ ┆ ┆ ┆ 5 ┆ 0 │
│ 888998 ┆ 2427730924 ┆ SELL ┆ 2.65905e6 ┆ 0.020716 ┆ 2023-01-18 ┆ JRF20230118- ┆ JRF20230118- │
│ ┆ ┆ ┆ ┆ ┆ 23:58:53.543 ┆ 235852-05515 ┆ 235853-11943 │
│ ┆ ┆ ┆ ┆ ┆ ┆ 5 ┆ 1 │
│ 888997 ┆ 2427730925 ┆ SELL ┆ 2.658996e6 ┆ 0.000004 ┆ 2023-01-18 ┆ JRF20230118- ┆ JRF20230118- │
│ ┆ ┆ ┆ ┆ ┆ 23:58:53.543 ┆ 235820-13432 ┆ 235853-11943 │
│ ┆ ┆ ┆ ┆ ┆ ┆ 5 ┆ 1 │
└────────┴────────────┴──────┴────────────┴──────────┴───────────────┴──────────────┴──────────────┘
961 ms ± 43.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
年月日、曜日を新たなデータとして追加
dt.day()で日付、alias()でcolumn追加できます。aliasがない場合はexec_dateに上書きされる。
df.with_columns(pl.col(date_target).dt.day().alias("day"))
┌────────┬────────────┬──────┬────────────┬─────┬──────────────┬──────────────┬──────────────┬─────┐
│ ┆ id ┆ side ┆ price ┆ ... ┆ exec_date ┆ buy_child_or ┆ sell_child_o ┆ day │
│ --- ┆ --- ┆ --- ┆ --- ┆ ┆ --- ┆ der_acceptan ┆ rder_accepta ┆ --- │
│ i64 ┆ i64 ┆ str ┆ f64 ┆ ┆ datetime[μs] ┆ ce_id ┆ nce_id ┆ u32 │
│ ┆ ┆ ┆ ┆ ┆ ┆ --- ┆ --- ┆ │
│ ┆ ┆ ┆ ┆ ┆ ┆ str ┆ str ┆ │
╞════════╪════════════╪══════╪════════════╪═════╪══════════════╪══════════════╪══════════════╪═════╡
│ 888999 ┆ 2427730923 ┆ SELL ┆ 2.65905e6 ┆ ... ┆ 2023-01-18 ┆ JRF20230118- ┆ JRF20230118- ┆ 18 │
│ ┆ ┆ ┆ ┆ ┆ 23:58:53.543 ┆ 235852-05515 ┆ 235853-13018 ┆ │
│ ┆ ┆ ┆ ┆ ┆ ┆ 5 ┆ 0 ┆ │
│ 888998 ┆ 2427730924 ┆ SELL ┆ 2.65905e6 ┆ ... ┆ 2023-01-18 ┆ JRF20230118- ┆ JRF20230118- ┆ 18 │
│ ┆ ┆ ┆ ┆ ┆ 23:58:53.543 ┆ 235852-05515 ┆ 235853-11943 ┆ │
│ ┆ ┆ ┆ ┆ ┆ ┆ 5 ┆ 1 ┆ │
│ 888997 ┆ 2427730925 ┆ SELL ┆ 2.658996e6 ┆ ... ┆ 2023-01-18 ┆ JRF20230118- ┆ JRF20230118- ┆ 18 │
│ ┆ ┆ ┆ ┆ ┆ 23:58:53.543 ┆ 235820-13432 ┆ 235853-11943 ┆ │
│ ┆ ┆ ┆ ┆ ┆ ┆ 5 ┆ 1 ┆ │
│ 888996 ┆ 2427730926 ┆ SELL ┆ 2.658996e6 ┆ ... ┆ 2023-01-18 ┆ JRF20230118- ┆ JRF20230118- ┆ 18 │
│ ┆ ┆ ┆ ┆ ┆ 23:58:53.543 ┆ 235820-13432 ┆ 235853-13453 ┆ │
│ ┆ ┆ ┆ ┆ ┆ ┆ 5 ┆ 3 ┆ │
│ ... ┆ ... ┆ ... ┆ ... ┆ ... ┆ ... ┆ ... ┆ ... ┆ ... │
│ 3 ┆ 2429121037 ┆ SELL ┆ 2.946067e6 ┆ ... ┆ 2023-01-22 ┆ JRF20230122- ┆ JRF20230122- ┆ 22 │
│ ┆ ┆ ┆ ┆ ┆ 23:59:50.707 ┆ 235950-01629 ┆ 235950-04815 ┆ │
│ ┆ ┆ ┆ ┆ ┆ ┆ 6 ┆ 0 ┆ │
│ 2 ┆ 2429121038 ┆ SELL ┆ 2.945864e6 ┆ ... ┆ 2023-01-22 ┆ JRF20230122- ┆ JRF20230122- ┆ 22 │
...
│ 0 ┆ 2429121040 ┆ SELL ┆ 2.945656e6 ┆ ... ┆ 2023-01-22 ┆ JRF20230122- ┆ JRF20230122- ┆ 22 │
│ ┆ ┆ ┆ ┆ ┆ 23:59:52.150 ┆ 235948-01112 ┆ 235952-01113 ┆ │
│ ┆ ┆ ┆ ┆ ┆ ┆ 2 ┆ 9 ┆ │
└────────┴────────────┴──────┴────────────┴─────┴──────────────┴──────────────┴──────────────┴─────┘
複数同時に追加する場合はwith_columns()内にリストで表記する。
カラム数が増えすぎたのでselect()で新しいデータ表を作って見やすくした。
因みに
with_columns()で既存のデータに保存
select()で新しいデータ表を作成して保存
となる
df_dt = df.select(
[
pl.col(date_target),
pl.col(date_target).dt.year().alias("year"),
pl.col(date_target).dt.month().alias("month"),
pl.col(date_target).dt.day().alias("day"),
pl.col(date_target).dt.hour().alias("hour"),
pl.col(date_target).dt.minute().alias("minute"),
pl.col(date_target).dt.second().alias("second"),
pl.col(date_target).dt.epoch().alias("epoch"),
]
)
))
┌─────────────────────────┬──────┬───────┬─────┬──────┬────────┬────────┬──────────────────┐
│ exec_date ┆ year ┆ month ┆ day ┆ hour ┆ minute ┆ second ┆ epoch │
│ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │
│ datetime[μs] ┆ i32 ┆ u32 ┆ u32 ┆ u32 ┆ u32 ┆ u32 ┆ i64 │
╞═════════════════════════╪══════╪═══════╪═════╪══════╪════════╪════════╪══════════════════╡
│ 2023-01-21 23:58:21.487 ┆ 2023 ┆ 1 ┆ 21 ┆ 23 ┆ 58 ┆ 21 ┆ 1674345501487000 │
│ 2023-01-21 23:58:21.487 ┆ 2023 ┆ 1 ┆ 21 ┆ 23 ┆ 58 ┆ 21 ┆ 1674345501487000 │
│ 2023-01-21 23:58:22.183 ┆ 2023 ┆ 1 ┆ 21 ┆ 23 ┆ 58 ┆ 22 ┆ 1674345502183000 │
│ 2023-01-21 23:58:22.183 ┆ 2023 ┆ 1 ┆ 21 ┆ 23 ┆ 58 ┆ 22 ┆ 1674345502183000 │
│ ... ┆ ... ┆ ... ┆ ... ┆ ... ┆ ... ┆ ... ┆ ... │
│ 2023-01-22 23:59:50.707 ┆ 2023 ┆ 1 ┆ 22 ┆ 23 ┆ 59 ┆ 50 ┆ 1674431990707000 │
│ 2023-01-22 23:59:50.707 ┆ 2023 ┆ 1 ┆ 22 ┆ 23 ┆ 59 ┆ 50 ┆ 1674431990707000 │
│ 2023-01-22 23:59:52.150 ┆ 2023 ┆ 1 ┆ 22 ┆ 23 ┆ 59 ┆ 52 ┆ 1674431992150000 │
│ 2023-01-22 23:59:52.150 ┆ 2023 ┆ 1 ┆ 22 ┆ 23 ┆ 59 ┆ 52 ┆ 1674431992150000 │
└─────────────────────────┴──────┴───────┴─────┴──────┴────────┴────────┴──────────────────┘
特定の年月日や曜日だけをとりだす
filterを使ってpl.col(カラム名)で取り出せます。
例: second が 5 の行を取り出す
df_dt.filter(pl.col("second") == 5).head()
┌─────────────────────────┬──────┬───────┬─────┬──────┬────────┬────────┬──────────────────┐
│ exec_date ┆ year ┆ month ┆ day ┆ hour ┆ minute ┆ second ┆ epoch │
│ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │
│ datetime[μs] ┆ i32 ┆ u32 ┆ u32 ┆ u32 ┆ u32 ┆ u32 ┆ i64 │
╞═════════════════════════╪══════╪═══════╪═════╪══════╪════════╪════════╪══════════════════╡
│ 2023-01-22 00:00:05.490 ┆ 2023 ┆ 1 ┆ 22 ┆ 0 ┆ 0 ┆ 5 ┆ 1674345605490000 │
│ 2023-01-22 00:01:05.117 ┆ 2023 ┆ 1 ┆ 22 ┆ 0 ┆ 1 ┆ 5 ┆ 1674345665117000 │
│ 2023-01-22 00:01:05.383 ┆ 2023 ┆ 1 ┆ 22 ┆ 0 ┆ 1 ┆ 5 ┆ 1674345665383000 │
│ 2023-01-22 00:01:05.383 ┆ 2023 ┆ 1 ┆ 22 ┆ 0 ┆ 1 ┆ 5 ┆ 1674345665383000 │
│ 2023-01-22 00:02:05.233 ┆ 2023 ┆ 1 ┆ 22 ┆ 0 ┆ 2 ┆ 5 ┆ 1674345725233000 │
└─────────────────────────┴──────┴───────┴─────┴──────┴────────┴────────┴──────────────────┘
時間ごとの動きを確認
棒グラフ表記 y軸に取引回数
plt.figure(figsize=(15,7))
plt.hist(df_dt['hour'], bins=len(df_dt['hour'].value_counts()), width=0.5)
plt.xlabel('Hour')
plt.ylabel('FX_BTC_JPY')
時間の増減
pandas同様datetime型から比較増減もできます。
例: exec_date-30日
df_dt.with_columns(
(pl.col("exec_date") - timedelta(days=30)).alias("date_30")
)
┌──────────────┬──────┬───────┬─────┬─────┬────────┬────────┬──────────────────┬──────────────┐
│ exec_date ┆ year ┆ month ┆ day ┆ ... ┆ minute ┆ second ┆ epoch ┆ date_30 │
│ --- ┆ --- ┆ --- ┆ --- ┆ ┆ --- ┆ --- ┆ --- ┆ --- │
│ datetime[μs] ┆ i32 ┆ u32 ┆ u32 ┆ ┆ u32 ┆ u32 ┆ i64 ┆ datetime[μs] │
╞══════════════╪══════╪═══════╪═════╪═════╪════════╪════════╪══════════════════╪══════════════╡
│ 2023-01-21 ┆ 2023 ┆ 1 ┆ 21 ┆ ... ┆ 58 ┆ 21 ┆ 1674345501487000 ┆ 2022-12-22 │
│ 23:58:21.487 ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ 23:58:21.487 │
│ 2023-01-21 ┆ 2023 ┆ 1 ┆ 21 ┆ ... ┆ 58 ┆ 21 ┆ 1674345501487000 ┆ 2022-12-22 │
│ 23:58:21.487 ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ 23:58:21.487 │
│ 2023-01-21 ┆ 2023 ┆ 1 ┆ 21 ┆ ... ┆ 58 ┆ 22 ┆ 1674345502183000 ┆ 2022-12-22 │
│ 23:58:22.183 ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ 23:58:22.183 │
│ 2023-01-21 ┆ 2023 ┆ 1 ┆ 21 ┆ ... ┆ 58 ┆ 22 ┆ 1674345502183000 ┆ 2022-12-22 │
│ 23:58:22.183 ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ 23:58:22.183 │
│ 2023-01-21 ┆ 2023 ┆ 1 ┆ 21 ┆ ... ┆ 58 ┆ 22 ┆ 1674345502183000 ┆ 2022-12-22 │
│ 23:58:22.183 ┆ ┆ ┆ ┆ ┆ ┆ ┆ ┆ 23:58:22.183 │
└──────────────┴──────┴───────┴─────┴─────┴────────┴────────┴──────────────────┴──────────────┘
リサンプリング
約定履歴からohlcv作成
df_ohlcv = (
df
.with_columns(pl.when(pl.col('side') == 'BUY').then(pl.col('size')).otherwise(0).alias('buy_size'))
.with_columns(pl.when(pl.col('side') == 'SELL').then(pl.col('size')).otherwise(0).alias('sell_size'))
.groupby_dynamic('exec_date', every='1m')
.agg([
pl.col('price').first().alias('open'),
pl.col('price').max().alias('high'),
pl.col('price').min().alias('low'),
pl.col('price').last().alias('close'),
pl.col('size').sum().alias('volume'),
pl.col('buy_size').sum().alias('buy_vol'),
pl.col('sell_size').sum().alias('sell_vol'),
])
)
shape: (5, 8)
┌────────────┬────────────┬────────────┬───────────┬───────────┬───────────┬───────────┬───────────┐
│ exec_date ┆ open ┆ high ┆ low ┆ close ┆ volume ┆ buy_vol ┆ sell_vol │
│ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │
│ datetime[μ ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 │
│ s] ┆ ┆ ┆ ┆ ┆ ┆ ┆ │
╞════════════╪════════════╪════════════╪═══════════╪═══════════╪═══════════╪═══════════╪═══════════╡
│ 2023-01-18 ┆ 2.65905e6 ┆ 2.659707e6 ┆ 2.658865e ┆ 2.659704e ┆ 0.60019 ┆ 0.386514 ┆ 0.213676 │
│ 23:58:00 ┆ ┆ ┆ 6 ┆ 6 ┆ ┆ ┆ │
│ 2023-01-18 ┆ 2.659707e6 ┆ 2.6606e6 ┆ 2.657831e ┆ 2.658154e ┆ 8.7166 ┆ 2.947514 ┆ 5.769086 │
│ 23:59:00 ┆ ┆ ┆ 6 ┆ 6 ┆ ┆ ┆ │
│ 2023-01-19 ┆ 2.658686e6 ┆ 2.661062e6 ┆ 2.655583e ┆ 2.66045e6 ┆ 31.59459 ┆ 12.815024 ┆ 18.779565 │
│ 00:00:00 ┆ ┆ ┆ 6 ┆ ┆ ┆ ┆ │
│ 2023-01-19 ┆ 2.660304e6 ┆ 2.661604e6 ┆ 2.657973e ┆ 2.660257e ┆ 12.014875 ┆ 5.463205 ┆ 6.551669 │
│ 00:01:00 ┆ ┆ ┆ 6 ┆ 6 ┆ ┆ ┆ │
│ 2023-01-19 ┆ 2.65947e6 ┆ 2.663093e6 ┆ 2.657845e ┆ 2.658557e ┆ 11.309212 ┆ 6.788335 ┆ 4.520876 │
│ 00:02:00 ┆ ┆ ┆ 6 ┆ 6 ┆ ┆ ┆ │
└────────────┴────────────┴────────────┴───────────┴───────────┴───────────┴───────────┴───────────┘
csv読み込みからリサンプリングするまでワンライナーでやるなら遅延評価有りの方が良い
path = "bitflyer/FX_BTC_JPY/trades/2023-01-17_2023-02-24.csv"
df = (
pl.scan_csv(path)
.with_columns([pl.col("exec_date").str.strptime(pl.Datetime, strict=False),
pl.when(pl.col('side') == 'BUY').then(pl.col('size')).otherwise(0).alias('buy_size'),
pl.when(pl.col('side') == 'SELL').then(pl.col('size')).otherwise(0).alias('sell_size')])
.groupby_dynamic('exec_date', every='1m')
.agg([
pl.col('price').first().alias('open'),
pl.col('price').max().alias('high'),
pl.col('price').min().alias('low'),
pl.col('price').last().alias('close'),
pl.col('size').sum().alias('volume'),
pl.col('buy_size').sum().alias('buy_vol'),
pl.col('sell_size').sum().alias('sell_vol'),
])
.collect()
)
スライス
pandasではdf["2023-02-01 00:00:00": "2023-02-10 00:00:00"]といった感じでスライスしてたのをpolarsでやる場合はfilterを使う。
start_date = datetime(2023, 1, 19, 00, 00, 00) # 始点
end_date = datetime(2023, 1, 20, 00, 00, 00) # 終点
# datetimeがstart_date以上 & datetimeがend_date以下
df.filter((pl.col("exec_date") >= start_date) & (pl.col("exec_date") <= end_date))
┌─────────────┬────────────┬────────────┬────────────┬────────────┬──────────┬──────────┬──────────┐
│ exec_date ┆ open ┆ high ┆ low ┆ close ┆ volume ┆ buy_vol ┆ sell_vol │
│ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │
│ datetime[μs ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 ┆ f64 │
│ ] ┆ ┆ ┆ ┆ ┆ ┆ ┆ │
╞═════════════╪════════════╪════════════╪════════════╪════════════╪══════════╪══════════╪══════════╡
│ 2023-01-19 ┆ 2.658686e6 ┆ 2.659096e6 ┆ 2.656967e6 ┆ 2.659096e6 ┆ 2.12 ┆ 0.08 ┆ 2.04 │
│ 00:00:00 ┆ ┆ ┆ ┆ ┆ ┆ ┆ │
│ 2023-01-19 ┆ 2.657724e6 ┆ 2.65985e6 ┆ 2.657724e6 ┆ 2.65985e6 ┆ 1.135364 ┆ 1.105364 ┆ 0.03 │
│ 00:00:01 ┆ ┆ ┆ ┆ ┆ ┆ ┆ │
│ 2023-01-19 ┆ 2.658704e6 ┆ 2.659023e6 ┆ 2.658282e6 ┆ 2.658282e6 ┆ 0.14866 ┆ 0.065 ┆ 0.08366 │
│ 00:00:02 ┆ ┆ ┆ ┆ ┆ ┆ ┆ │
│ 2023-01-19 ┆ 2.658918e6 ┆ 2.659406e6 ┆ 2.658151e6 ┆ 2.659406e6 ┆ 0.21 ┆ 0.1 ┆ 0.11 │
│ 00:00:03 ┆ ┆ ┆ ┆ ┆ ┆ ┆ │
│ ... ┆ ... ┆ ... ┆ ... ┆ ... ┆ ... ┆ ... ┆ ... │
│ 2023-01-19 ┆ 2.708e6 ┆ 2.708e6 ┆ 2.708e6 ┆ 2.708e6 ┆ 0.64899 ┆ 0.64899 ┆ 0.0 │
│ 23:59:47 ┆ ┆ ┆ ┆ ┆ ┆ ┆ │
│ 2023-01-19 ┆ 2.708063e6 ┆ 2.708063e6 ┆ 2.707909e6 ┆ 2.707909e6 ┆ 0.1 ┆ 0.0 ┆ 0.1 │
│ 23:59:51 ┆ ┆ ┆ ┆ ┆ ┆ ┆ │
│ 2023-01-19 ┆ 2.708474e6 ┆ 2.708474e6 ┆ 2.708474e6 ┆ 2.708474e6 ┆ 0.020273 ┆ 0.015 ┆ 0.005273 │
│ 23:59:59 ┆ ┆ ┆ ┆ ┆ ┆ ┆ │
│ 2023-01-20 ┆ 2.708176e6 ┆ 2.708176e6 ┆ 2.708176e6 ┆ 2.708176e6 ┆ 0.02 ┆ 0.02 ┆ 0.0 │
│ 00:00:00 ┆ ┆ ┆ ┆ ┆ ┆ ┆ │
└─────────────┴────────────┴────────────┴────────────┴────────────┴──────────┴──────────┴──────────┘
バックテストか分析で複数データフレームが欲しいときの関数用意しました。
連続する日付毎に区切ることができます。
df: データフレーム
start_date: 始まりの時間
interval: 間隔
quantity: 数
dt_col: datetimeなカラム
days=intervalの部分をseconds=intervalとかに変えてもok
def df_list(df: pl.DataFrame, start_date: datetime, interval: int, quantity: int, dt_col: str=""):
# 日付リストを生成する
date_list = [start_date + timedelta(days=interval*i)
for i in range(quantity)
if start_date + timedelta(days=interval*i) <= df[dt_col].max()]
# DataFrameリストを生成する
return [df.filter((pl.col(dt_col).ge(start_date)) & (pl.col(dt_col).lt(end_date)))
for start_date, end_date in [(date_list[i], date_list[i+1])
for i in range(0, len(date_list)-1, interval)] + ([ (date_list[-2], date_list[-1]) ]
if len(date_list) % interval != 1 else [])]
talib
0.4.22からpl.dataframeにも対応
だがto_numpy()で変換してからの方が速い
high=df.get_column("high").to_numpy()
low=df.get_column("low").to_numpy()
close=df.get_column("close").to_numpy()
df.with_columns(
[
pl.Series(talib.SMA(close, 30)).alias("SMA"),
pl.Series(talib.KAMA(close, 30)).alias("KAMA"),
pl.Series(talib.ATR(high, low, close, 30)).alias('ATR'),
]
)
マージ
先行指標を探索する際に使う
binance = pl.DataFrame([{'datetime': datetime(2023, 2, 11, 0, 0), 'close_bi': 21616.4},
{'datetime': datetime(2023, 2, 11, 0, 1), 'close_bi': 21622.6},
{'datetime': datetime(2023, 2, 11, 0, 2), 'close_bi': 21616.2},
{'datetime': datetime(2023, 2, 11, 0, 3), 'close_bi': 21616.6},
{'datetime': datetime(2023, 2, 11, 0, 4), 'close_bi': 21615.4}])
┌─────────────────────┬──────────┐
│ datetime ┆ close_bi │
│ --- ┆ --- │
│ datetime[μs] ┆ f64 │
╞═════════════════════╪══════════╡
│ 2023-02-11 00:00:00 ┆ 21616.4 │
│ 2023-02-11 00:01:00 ┆ 21622.6 │
│ 2023-02-11 00:02:00 ┆ 21616.2 │
│ 2023-02-11 00:03:00 ┆ 21616.6 │
│ 2023-02-11 00:04:00 ┆ 21615.4 │
└─────────────────────┴──────────┘
bitflyer = pl.DataFrame([{'datetime': datetime(2023, 2, 11, 0, 0), 'close_bf': 2846642.0},
{'datetime': datetime(2023, 2, 11, 0, 1), 'close_bf': 2847064.0},
{'datetime': datetime(2023, 2, 11, 0, 2), 'close_bf': 2846381.0},
{'datetime': datetime(2023, 2, 11, 0, 3), 'close_bf': 2846301.0},
{'datetime': datetime(2023, 2, 11, 0, 4), 'close_bf': 2846222.0}])
┌─────────────────────┬────────────┐
│ datetime ┆ close_bf │
│ --- ┆ --- │
│ datetime[μs] ┆ f64 │
╞═════════════════════╪════════════╡
│ 2023-02-11 00:00:00 ┆ 2.846642e6 │
│ 2023-02-11 00:01:00 ┆ 2.847064e6 │
│ 2023-02-11 00:02:00 ┆ 2.846381e6 │
│ 2023-02-11 00:03:00 ┆ 2.846301e6 │
│ 2023-02-11 00:04:00 ┆ 2.846222e6 │
└─────────────────────┴────────────┘
# left,rightはデータフレーム,onは重ねたいカラム,
# nullに前の行の値を適用する,nullに後の行の値を適用する
def pl_merge(left, right, col):
return left.join(right ,on=col, how="left").fill_null(strategy="forward").fill_null(strategy="backward")
pl_merge(binance, bitflyer, "datetime")
┌─────────────────────┬──────────┬────────────┐
│ datetime ┆ close_bi ┆ close_bf │
│ --- ┆ --- ┆ --- │
│ datetime[μs] ┆ f64 ┆ f64 │
╞═════════════════════╪══════════╪════════════╡
│ 2023-02-11 00:00:00 ┆ 21616.4 ┆ 2.846642e6 │
│ 2023-02-11 00:01:00 ┆ 21622.6 ┆ 2.847064e6 │
│ 2023-02-11 00:02:00 ┆ 21616.2 ┆ 2.846381e6 │
│ 2023-02-11 00:03:00 ┆ 21616.6 ┆ 2.846301e6 │
│ 2023-02-11 00:04:00 ┆ 21615.4 ┆ 2.846222e6 │
└─────────────────────┴──────────┴────────────┘
Discussion