Skip to content

Commit efb8d57

Browse files
committed
Add README
1 parent 05e4bcd commit efb8d57

11 files changed

Lines changed: 151 additions & 146 deletions

File tree

README.md

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,71 @@
1-
# Tezos-Prediction
1+
# Tezos Prediction
2+
3+
This repository explores the use of technical indicators to predict the value
4+
of Tezos (XTZ) over time. Though technical analysis is often frowned upon in
5+
comparison with fundamental analysis, recent work
6+
[[1]](https://arxiv.org/pdf/1901.05237.pdf)
7+
[[2]](http://www.ieee-jas.org/fileZDHXBEN/journal/article/zdhxbywb/2020/3/PDF/JAS-2019-0392.pdf)
8+
has demonstrated the effectiveness of CNN's on market prediction tasks - without
9+
the need for extra-market data sources (e.g. sentiment analysis of headlines).
10+
11+
Since early 2020, I've been collecting data on Bitcoin and Tezos every 6
12+
minutes. This includes:
13+
- Rank (based on Market Cap)
14+
- Market Cap
15+
- Price
16+
- 24 Hour Volume
17+
- Percent Change (last hour)
18+
- Percent Change (last week)
19+
20+
You can download the dataset and trained models
21+
[here](https://drive.google.com/drive/folders/1m8Km28rn6RPEPKIJ_gAsp8aV6TJU2Sfq?usp=sharing).
22+
23+
## Architecture
24+
The models I've released here look only at price over time. Specifically,
25+
they see 40 time steps and predict the next 5. At 6 minutes per time step,
26+
that's like knowing the past 4 hours and predicting the next half hour.
27+
28+
The CNN architecture receives Grammian Angular Fields as input. This is
29+
basically a transformation from the time domain to the frequency domain
30+
in polar coordinates (at least that's how I think of it).The LSTM, on the
31+
other hand, see the raw time series.
32+
33+
For comparison purposes, both networks train for 6 epochs with batch sizes
34+
of 16. Both use the mean squared error as their loss function, and are
35+
similar in terms of parameter count (277k vs 159k). Obviously, it's
36+
possible that optimizations could be made to improve the accuracy of each
37+
model, but I'm really just doing this as an exploratory exercise.
38+
39+
## Findings
40+
Model | Mean Squared Error | Mean Absolute Error
41+
--- | :---: | :---: |
42+
CNN | 0.275 | 0.4458
43+
LSTM | 1.095 | 0.6432
44+
45+
It's clear that the CNN with GAF images outperforms the LSTM on this dataset
46+
(at least with these hyperparameters). This result is in line with recent
47+
research in the field.
48+
49+
## Prerequisites
50+
To run this code, you will need `numpy`, `scipy`, and `tensorflow.keras`. I
51+
recommend installing via a package manager like conda, but that's up to you.
52+
53+
## Usage
54+
Download the dataset from the link above, unzip it, and place the 'dataset'
55+
folder in the repository's root directory (on the same level as 'models',
56+
'testing', 'training', and 'transforms').
57+
58+
Once you have the dataset, you can replicate my results by calling `python
59+
main.py`, which will train (1) a CNN on GAF images and (2) an LSTM on 1D
60+
sequences. It will then save the model weights to disk and evaluate both
61+
architectures on the test set.
62+
63+
If you want to dig deeper or run your own experiments, start with the files
64+
in the 'training' and 'testing' folders. You'll be able to modify all of the
65+
hyperparameters. If you want to change the architecture itself, look in the
66+
'models' folder.
67+
68+
## Disclaimer
69+
I don't recommend using these models in combination with any sort of trading
70+
bot or trading strategy. This work is for research purposes only. Use at your
71+
own risk.

main.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
from training.train_cnn_timeseries import main as train_cnn_timeseries
2+
from training.train_lstm import main as train_lstm
3+
from testing.test_cnn_timeseries import main as test_cnn_timeseries
4+
from testing.test_lstm import main as test_lstm
5+
6+
7+
if __name__ == '__main__':
8+
# train_cnn_timeseries('dataset/train')
9+
# train_lstm('dataset/train')
10+
11+
cnn_results = test_cnn_timeseries('models/cnn_timeseries_16_40_5_1.h5', 'dataset/test')
12+
lstm_results = test_lstm('models/lstm_16_40_5.h5', 'dataset/test')
13+
14+
print('CNN Results \t|\t\tmse: {},\t\tmae: {}'.format(*cnn_results[:2]))
15+
print('LSTM Results\t|\t\tmse: {},\t\tmae: {}'.format(*lstm_results[:2]))

models/lstm.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,5 +32,5 @@ def build(self):
3232
super().build()
3333

3434
def compile(self):
35-
self.model.compile(optimizer='sgd', loss='mse', metrics=['mae'])
35+
self.model.compile(optimizer='sgd', loss='mse', metrics=['mae', 'accuracy'])
3636
super().compile()

predict.py

Lines changed: 0 additions & 47 deletions
This file was deleted.

see_results.py

Lines changed: 0 additions & 21 deletions
This file was deleted.

testing/test_cnn_timeseries.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
from tensorflow.keras import models
2+
3+
from training.train_cnn_timeseries import MyData
4+
5+
6+
def main(model_dir, data_dir):
7+
BATCH_SIZE = 16
8+
N_SAMPLES_IN = 40 # divide by 10 to get # hours the sequence covers
9+
N_SAMPLES_OUT = 5
10+
PROB_DISTRIB = 1
11+
12+
generator = MyData(
13+
data_dir,
14+
BATCH_SIZE,
15+
N_SAMPLES_IN,
16+
N_SAMPLES_OUT,
17+
PROB_DISTRIB
18+
)
19+
20+
cnn = models.load_model(model_dir)
21+
cnn.summary()
22+
return cnn.evaluate(generator, verbose=1)
23+
24+
25+
if __name__ == '__main__':
26+
print(main('../models/cnn_timeseries_16_40_5_1.h5', '../dataset/test'))

testing/test_lstm.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
from tensorflow.keras import models
2+
3+
from training.train_lstm import MyData
4+
5+
6+
def main(model_dir, data_dir):
7+
BATCH_SIZE = 16
8+
N_SAMPLES_IN = 40 # divide by 10 to get # hours the sequence covers
9+
N_SAMPLES_OUT = 5
10+
11+
generator = MyData(
12+
data_dir,
13+
BATCH_SIZE,
14+
N_SAMPLES_IN,
15+
N_SAMPLES_OUT
16+
)
17+
18+
lstm = models.load_model(model_dir)
19+
lstm.summary()
20+
return lstm.evaluate(generator, verbose=1)
21+
22+
23+
if __name__ == '__main__':
24+
print(main('../models/lstm_16_40_5.h5', '../dataset/test'))

training/train_cnn_timeseries.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
"""
2-
TRAIN
3-
"""
41
import os
52

63
from scipy import stats
@@ -65,16 +62,14 @@ def __getitem__(self, idx):
6562
return X, Y
6663

6764

68-
if __name__ == '__main__':
69-
70-
DATA_DIR = '../dataset/train'
65+
def main(data_dir):
7166
BATCH_SIZE = 16
7267
N_SAMPLES_IN = 40 # divide by 10 to get # hours the sequence covers
7368
N_SAMPLES_OUT = 5
7469
PROB_DISTRIB = 1
7570

7671
generator = MyData(
77-
DATA_DIR,
72+
data_dir,
7873
BATCH_SIZE,
7974
N_SAMPLES_IN,
8075
N_SAMPLES_OUT,
@@ -95,6 +90,10 @@ def __getitem__(self, idx):
9590
verbose=1,
9691
steps_per_epoch=len(generator))
9792

98-
cnn.model.save('cnn_%d_%d_%d_%d.h5' % (
93+
cnn.model.save('models/cnn_timeseries_%d_%d_%d_%d.h5' % (
9994
BATCH_SIZE, N_SAMPLES_IN, N_SAMPLES_OUT, PROB_DISTRIB
10095
))
96+
97+
98+
if __name__ == '__main__':
99+
main('../dataset/train')

training/train_lstm.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
"""
2-
TRAIN
3-
"""
41
import os
52

63
import numpy as np
@@ -57,15 +54,13 @@ def __getitem__(self, idx):
5754
return X, Y
5855

5956

60-
if __name__ == '__main__':
61-
62-
DATA_DIR = '../dataset/train'
57+
def main(data_dir):
6358
BATCH_SIZE = 16
6459
N_SAMPLES_IN = 40 # divide by 10 to get # hours the sequence covers
6560
N_SAMPLES_OUT = 5
6661

6762
generator = MyData(
68-
DATA_DIR,
63+
data_dir,
6964
BATCH_SIZE,
7065
N_SAMPLES_IN,
7166
N_SAMPLES_OUT
@@ -81,6 +76,10 @@ def __getitem__(self, idx):
8176
verbose=1,
8277
steps_per_epoch=len(generator))
8378

84-
lstm.model.save('lstm_%d_%d_%d.h5' % (
79+
lstm.model.save('models/lstm_%d_%d_%d.h5' % (
8580
BATCH_SIZE, N_SAMPLES_IN, N_SAMPLES_OUT
8681
))
82+
83+
84+
if __name__ == '__main__':
85+
main('../dataset/train')

util.py

Lines changed: 0 additions & 26 deletions
This file was deleted.

0 commit comments

Comments
 (0)