-
Notifications
You must be signed in to change notification settings - Fork 70
Expand file tree
/
Copy pathfetch_bitcoin_data.py
More file actions
87 lines (72 loc) · 2.31 KB
/
fetch_bitcoin_data.py
File metadata and controls
87 lines (72 loc) · 2.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
import polars as pl
from api.coinmetrics_api import cm_fetch_asset_metrics
from utils import mark_days_since, mark_highs_lows
def fetch_coinmetrics_data():
"""
Fetch historical Bitcoin blockchain data from Coin Metrics Community API.
"""
df_cm = cm_fetch_asset_metrics(
asset='btc',
metrics=['BlkCnt', 'IssTotNtv', 'IssTotUSD', 'PriceUSD'],
start_time='2009-01-03',
)
df = df_cm.select(
Date=pl.col('Date'),
TotalBlocks=pl.col('BlkCnt'),
IssTotNtv=pl.col('IssTotNtv'),
IssTotUSD=pl.col('IssTotUSD'),
Price=pl.col('PriceUSD'),
)
avg_subsidy = (
pl
.when(pl.col('TotalBlocks') > 0)
.then(pl.col('IssTotNtv') / pl.col('TotalBlocks'))
.otherwise(None)
)
subsidy_floor = pl.lit(50.0) / (
pl.lit(2.0) ** (pl.lit(50.0) / avg_subsidy).log(base=2).ceil()
)
df = df.with_columns(
Halving=(
subsidy_floor.is_not_null()
& subsidy_floor.shift(1).is_not_null()
& (subsidy_floor != subsidy_floor.shift(1))
)
)
return df.select(
'Date',
'IssTotUSD',
'Price',
'Halving',
)
def fetch_bitcoin_data():
"""
Fetches historical Bitcoin data into a DataFrame.
Very early data is discarded due to high volatility.
"""
print('📈 Requesting historical Bitcoin data…')
df = fetch_coinmetrics_data()
df = df.with_columns(
PuellMultiple=(
pl.col('IssTotUSD')
/ pl.col('IssTotUSD').rolling_mean(window_size=365, min_samples=365)
),
Price730DMA=pl.col('Price').rolling_mean(window_size=730, min_samples=1),
)
df = df.filter(pl.col('Date') >= pl.datetime(2011, 6, 27, time_zone='UTC'))
df = df.with_columns(
PriceLog=pl.col('Price').log(),
)
df = mark_highs_lows(df, 'Price', False, 365 * 2, 180)
# move 2021' peak to the first price peak
df = df.with_columns(
PriceHigh=(
pl
.when(pl.col('Date') == pl.datetime(2021, 11, 8, time_zone='UTC'))
.then(False)
.when(pl.col('Date') == pl.datetime(2021, 4, 14, time_zone='UTC'))
.then(True)
.otherwise(pl.col('PriceHigh'))
)
)
return mark_days_since(df, ['PriceLow', 'Halving'])