diff --git a/src/apiBroker.py b/src/apiBroker.py new file mode 100644 index 00000000..f88f38d8 --- /dev/null +++ b/src/apiBroker.py @@ -0,0 +1,17 @@ +import requests + + +def get_all_data(trading_pair): + (fst, snd) = trading_pair.split("-") + url = f"https://min-api.cryptocompare.com/data/v2/histoday?fsym={fst}&tsym={snd}&allData=true" + resp = requests.get(url) + if resp.status_code != 200: + raise ConnectionError('Error during fetching the data, Error code: {}'.format(resp.status_code)) + else: + return resp.json() + + +def get_data(trading_pair, timestamp_from, timestamp_to): + data = get_all_data(trading_pair) + return list( + filter(lambda data: float(timestamp_from) <= float(data["time"]) <= float(timestamp_to), data["Data"]["Data"])) \ No newline at end of file diff --git a/src/graphs.py b/src/graphs.py new file mode 100644 index 00000000..e7fd2e50 --- /dev/null +++ b/src/graphs.py @@ -0,0 +1,24 @@ +import apiBroker +import matplotlib.pyplot as plt +import pandas as pd + + +def draw(data, title): + + fig = plt.figure() + plt.style.use('seaborn') + ax1 = fig.add_subplot(211) + ax2 = fig.add_subplot(212) + dataset = pd.DataFrame(data) + dataset['time'] = pd.to_datetime(dataset['time'], unit='s') + ax1 = dataset.plot(kind='line' , x='time', y='open', title=title, ax=ax1) + ax1.set_xlabel("time") + ax1.set_ylabel("price") + ax1.legend(['price']) + ax2 = dataset.plot(kind="bar", x='time', y='volumefrom', stacked=True, ax=ax2) + ax2.legend(['volume']) + ax2.set_xlabel("time") + ax2.set_xticks([]) + ax2.set_ylabel("volume") + + plt.draw() \ No newline at end of file diff --git a/src/simulation.py b/src/simulation.py new file mode 100644 index 00000000..e04b2363 --- /dev/null +++ b/src/simulation.py @@ -0,0 +1,111 @@ +import apiBroker +import time +import datetime +import numpy as np +import pandas as pd +import graphs + + +pairs = [ + "BTC-USD", + "ETH-USD", + "LTC-USD" +] + + +# YYYY-MM_DD format +def convert_dates(human_readable_date): + (yyyy, mm, dd) = (human_readable_date.split("-")) + date = datetime.datetime(int(yyyy), int(mm), int(dd)) + return int(date.timestamp()) + + +def sim(trading_pair, starting_date, ending_date, count): + data_list = [] + for _ in range(count): + data_list.append(sim_one(trading_pair, starting_date, ending_date)) + return data_list + + +def sim_one(trading_pair, starting_date, ending_date): + starting_date = convert_dates(starting_date) + ending_date = convert_dates(ending_date) + if ending_date >= time.time() or starting_date >= ending_date: + raise ValueError("Wrong date range") + if trading_pair not in pairs: + raise ValueError("Wrong trading pair") + data = pd.DataFrame(apiBroker.get_data(trading_pair, starting_date, ending_date)) + data = data[['time', 'open', 'close', 'volumefrom']] + days = int((ending_date - starting_date) / (24 * 60 * 60)) + data['months'] = int(days / 30) + data['months'] = data['months'].clip(lower=1) + for i in range(days): + data = data.append(generate_entry(data), ignore_index=True) + data = data.drop(columns=['months', 'diff']) + return data + + +def generate_entry(data): + price_change = (decide_how_price_changes(data, count_rise_probability(data))) + new_volume = decide_volume_change(data, price_change) + last_entry = data.tail(1) + time = last_entry['time'] + (24 * 60 * 60) + open = last_entry['close'] + close = open + price_change + diff = np.abs(price_change) + new_entry = pd.DataFrame({'time': time, 'open': open, 'volumefrom': new_volume, 'close': close, 'diff': diff}) + return new_entry + + +def decide_volume_change(data, price_change): + diff = np.abs(price_change) + result_index = data['diff'].sub(diff).abs().idxmin() + return data.iloc[result_index, :]['volumefrom'] + + +def count_rise_probability(data): + data['diff'] = data['open'] - data['close'] + total_change_in_price = np.abs(data['diff']).sum() + return (data['diff'][data['diff'] > 0]).sum() / total_change_in_price + + +def decide_how_price_changes(data, probability_of_rise): + diffs = data['diff'].abs() + p = np.random.uniform(diffs.min(), diffs.max()) / data.iloc[0]['months'] + if np.random.rand() < probability_of_rise: + return p + else: + a = data.tail(1).iloc[0]['close'] - p + if a - p < 0: + return np.abs(a) + else: + return -p + + +def count_statistics(data): + return {'averages': data.mean(), 'median': data.median(), 'deviation': data.std()} + + +def mean_from_multiple_sims(data_list): + combined = pd.concat(data_list) + means = combined.groupby(combined.index).mean() + return means + + +if __name__ == '__main__': + print('Pick a pair') + for i in range(3): + print(f"{i} - {pairs[i]}") + pair = input() + start_date = input("Enter start date(YYYY-MM-DD): ") + end_date = input("Enter end date(YYYY-MM-DD): ") + one = sim_one(pairs[int(pair)], start_date, end_date) + graphs.draw(one, 'Simulation') + stats = count_statistics(one) + print("Statistics from simulation: ") + for stat in stats: + print(f"{stat}:") + print(stats[stat]) + data = sim(pairs[int(pair)], start_date, end_date, 100) + graphs.draw(mean_from_multiple_sims(data), 'Avg from 100 simulations') + graphs.plt.show()