View file src/colab/grid_trading_lt.py - Download
# -*- coding: utf-8 -*-
"""grid_trading_lt.ipynb
Automatically generated by Colab.
Original file is located at
https://colab.research.google.com/drive/10boTTuWsljdZ3KrnFBbmCKBBthS5BqsF
SIMULATION OF GRID TRADING
Get the prices here : https://www.binance.com/en/landing/data
and upload them to your Google Drive.
"""
import numpy as np
from datetime import datetime, timedelta
debut = datetime(2000, 1, 1, 0, 0)
fin = datetime(2025, 1, 1, 0, 0)
!pip install yfinance
import yfinance as yf
ticker = yf.Ticker('BTC-USD')
data = ticker.history(interval='60m', start='2024-03-01', end='2024-10-02')
print(len(data))
print(data)
price_hist = {}
n = 0
for i in range(len(data)):
ts = data.index[i]
dt_str = str(ts)[0:16]
dt = datetime.strptime(dt_str, "%Y-%m-%d %H:%M")
if dt >= debut and dt <= fin:
open = data.Open[ts]
high = data.High[ts]
low = data.Low[ts]
close = data.Close[ts]
if open <= close: # up candle
first = low
second = high
else: # down candle
first = high
second = low
price_hist[dt] = open
price_hist[dt + timedelta(minutes=15)] = first
price_hist[dt + timedelta(minutes=30)] = second
price_hist[dt + timedelta(minutes=45)] = close
n = n+1
print(f"{n} candles loaded")
import matplotlib.pyplot as plt
plt.figure(figsize=(15,6))
plt.plot(list(price_hist.keys()), list(price_hist.values()))
plt.show()
import math
def compute_params():
global price_step
global llow
global lhigh
global lprice_step
global order_amount
global order_amount_crypto
global fees
price_step = (high - low) / steps
llow = math.log(low)
lhigh = math.log(high)
lprice_step = (lhigh - llow) / steps
#order_amount = (usdt_amount - reserved) / ((steps * 1.054) + 1.05)
#order_amount = (usdt_amount - reserved) / (steps + 1)
order_amount = 0
order_amount_crypto = usdt_amount / (steps + 1) / list(price_hist.values())[0]
fees = order_amount * fees_rate
mode = "geometric" # @param ["arithmetic", "geometric"]
low = 53000 # @param {type:"number"}
high = 73000 # @param {type:"number"}
steps = 20 # @param {type:"number"}
usdt_amount = 165.5 # @param {type:"number"}
stop_loss = 1 # @param {type:"number"}
take_profit = 90000 # @param {type:"number"}
reserved = 0 # @param {type:"number"}
fees_rate = 0.002 # @param {type:"number"}
# Calculated values
compute_params()
#order_amount = 0
#order_amount_crypto = 0.000206
print(f"Price Step: {price_step:7.2f}")
print(f"Order Amount: {order_amount:7.2f}")
print(f"Order Amount crypto: {order_amount_crypto:7.5f}")
print(f"Fees: {fees:7.4f}")
import math
def level_of_price(price):
if price < low: return -1
if price > high: return steps
if mode == "arithmetic":
l = math.floor((price - low) / price_step)
elif mode == "geometric":
l = math.floor((math.log(price) - llow) / lprice_step)
return l
level_of_price(61000)
def price_of_level(level):
if mode == "arithmetic":
price = low + level * price_step
elif mode == "geometric":
price = math.exp(llow + level * lprice_step)
return price
price_of_level(3)
init_price = list(price_hist.values())[0]
print(init_price)
# Commented out IPython magic to ensure Python compatibility.
# %%script echo Disabled
#
# # Répartir usdt_amount proportionnellement au nombre de lignes en dessous du cours initial pour usdt et au dessus du cours initial pour crypto
# usdt = usdt_amount * 6 / 20
# crypto = (usdt_amount * 14 / 20) / init_price
# print(f"Start with {usdt} USDT and {crypto} BTC")
print(list(price_hist.keys())[0])
print(list(price_hist.keys())[-1])
dt1 = list(price_hist.keys())[1000]
print(dt1)
dt_begin = list(price_hist.keys())[0]
dt_end = list(price_hist.keys())[-1]
duration = dt_end - dt_begin
print(duration)
if duration.total_seconds() / 3600 <= 48:
first_hour = dt_begin.replace(minute=0, second=0, hour=dt_begin.hour+1)
else:
first_hour = dt_begin.replace(hour=0, minute=0, second=0, day=dt_begin.day+1)
print(first_hour)
print(first_hour + timedelta(hours=1))
!pip install python-dateutil
from dateutil.relativedelta import relativedelta
def draw_chart():
plt.figure(figsize=(15,6))
plt.plot(list(price_hist.keys()), list(price_hist.values()))
print(duration.total_seconds() / 3600)
print(24 * 365)
hour = first_hour
while hour < dt_end:
plt.axvline(x=hour, color='grey', linestyle='-')
if duration.total_seconds() / 3600 <= 48:
hour = hour + timedelta(hours=1)
elif duration.total_seconds() / 3600 <= 24 * 30:
hour = hour + timedelta(days=1)
else:
hour = hour + relativedelta(months=1)
for i in range(steps+1):
plt.axhline(y=price_of_level(i), color='grey', linestyle='-')
plt.show()
crypto_hist = {}
usdt_hist = {}
trade_price_hist = {}
position_hist = {}
achats = []
ventes = []
pairs = []
def trade(price_hist, disp=False):
#global usdt
#global crypto
global crypto_hist
global usdt_hist
global trade_price_hist
global position_hist
global achats
global ventes
global pairs
# Répartir usdt_amount proportionnellement au nombre de lignes en dessous du cours initial pour usdt et au dessus du cours initial pour crypto
init_price = list(price_hist.values())[0]
usdt = usdt_amount * (init_price - low) / (high - low)
crypto = (usdt_amount - usdt) / init_price
total = usdt + crypto * init_price
crypto_hist = {}
usdt_hist = {}
trade_price_hist = {}
position_hist = {}
achats = []
ventes = []
pairs = []
if disp:
print(f"Initial price: {init_price:9.2f}, USDT: {usdt:9.2f}, crypto: {crypto:9.6f}")
level = level_of_price(init_price)
trend = 0
nt = 0
for dt, price in price_hist.items():
if price < stop_loss: break
if price > take_profit: break
previous_level = level
level = level_of_price(price)
if level < previous_level:
for i in range(previous_level, level, -1):
previous_trend = trend
trend = -1
if trend == previous_trend or previous_trend == 0:
nt = nt + 1
trade_price = price_of_level(i)
crypto_hist[dt - timedelta(milliseconds=100)] = crypto
usdt_hist[dt - timedelta(milliseconds=100)] = usdt
trade_price_hist[dt - timedelta(milliseconds=100)] = trade_price
if order_amount != 0:
# Buy cryptos for order_amount USDT
tr = [dt, 1, order_amount, order_amount / trade_price, trade_price]
# usdt = usdt - order_amount - fees
# crypto = crypto + order_amount / trade_price
usdt = usdt - order_amount
crypto = crypto + order_amount / trade_price * (1 - fees_rate)
elif order_amount_crypto != 0:
# Buy order_amount_crypto
tr = [dt, 1, order_amount_crypto * trade_price, order_amount_crypto, trade_price]
# crypto = crypto + order_amount_crypto
# usdt = usdt - order_amount_crypto * trade_price - fees
usdt = usdt - order_amount_crypto * trade_price
crypto = crypto + order_amount_crypto * (1 - fees_rate)
crypto_hist[dt] = crypto
usdt_hist[dt] = usdt
trade_price_hist[dt] = trade_price
total = usdt + crypto * price
if len(ventes) == 0:
achats.append(tr)
else:
vente = ventes.pop()
pairs.append([vente, tr])
if disp:
print(f"{dt.strftime('%Y-%m-%d %H:%M:%S')} L{i:3d} ({trade_price:9.2f} ) baisse: {nt:3d} ACHAT -> USDT:{usdt:9.2f}, crypto:{crypto:9.6f}, total:{total:9.2f} gain:{total-usdt_amount:9.2f}")
elif level > previous_level:
for i in range(previous_level, level):
previous_trend = trend
trend = 1
if trend == previous_trend or previous_trend == 0:
nt = nt + 1
trade_price = price_of_level(i+1)
crypto_hist[dt - timedelta(milliseconds=100)] = crypto
usdt_hist[dt - timedelta(milliseconds=100)] = usdt
trade_price_hist[dt - timedelta(milliseconds=100)] = trade_price
if order_amount != 0:
# Sell cryptos for order_amount USDT
tr = [dt, -1, order_amount, order_amount / trade_price, trade_price]
# usdt = usdt + order_amount - fees
usdt = usdt + order_amount * (1 - fees_rate)
crypto = crypto - order_amount / trade_price
elif order_amount_crypto != 0:
# Sell order_amount_crypto cryptos
tr = [dt, -1, order_amount_crypto * trade_price, order_amount_crypto, trade_price]
# usdt = usdt + order_amount_crypto * trade_price - fees
usdt = usdt + order_amount_crypto * trade_price * (1 - fees_rate)
crypto = crypto - order_amount_crypto
crypto_hist[dt] = crypto
usdt_hist[dt] = usdt
trade_price_hist[dt] = trade_price
total = usdt + crypto * price
if len(achats) == 0:
ventes.append(tr)
else:
achat = achats.pop()
pairs.append([achat, tr])
if disp:
print(f"{dt.strftime('%Y-%m-%d %H:%M:%S')} L{i:3d} ({trade_price:9.2f} ) hausse: {nt:3d} VENTE -> USDT:{usdt:9.2f}, crypto:{crypto:9.6f}, total:{total:9.2f} gain:{total-usdt_amount:9.2f}")
# store position
# position_hist[dt] = Position(dt, usdt, crypto)
return total - usdt_amount
def print_trade(tr):
dt = tr[0].strftime("%d/%m %H:%M")
direction = tr[1]
if direction == 1:
type = "Achat"
elif direction == -1:
type = "Vente"
usdt = tr[2]
crypto = tr[3]
trade_price = tr[4]
print(f"{dt}: {type} price:{trade_price:9.2f} - {usdt:8.2f} USDT ; {crypto:8.6f} crypto")
def print_pair(pair):
print_trade(pair[0])
print_trade(pair[1])
direction0 = pair[0][1]
direction1 = pair[1][1]
price = pair[1][4]
if (direction0 == 1 and direction1 == -1):
achat_usdt = pair[0][2]
achat_crypto = pair[0][3]
achat_price = pair[0][4]
vente_usdt = pair[1][2]
vente_crypto = pair[1][3]
vente_price = pair[1][4]
elif (direction0 == -1 and direction1 == 1):
vente_usdt = pair[0][2]
vente_crypto = pair[0][3]
vente_price = pair[0][4]
achat_usdt = pair[1][2]
achat_crypto = pair[1][3]
achat_price = pair[1][4]
benefice = - achat_usdt + vente_usdt * (1 - fees_rate) + (achat_crypto * (1 - fees_rate) - vente_crypto) * price
print(f"Bénéfice: {benefice:8.2f}")
print("")
def draw_crypto_hist():
plt.figure(figsize=(15,6))
x_values = list(crypto_hist.keys())
y_values = list(crypto_hist.values())
plt.plot(x_values, y_values)
plt.show()
def draw_usdt_hist():
plt.figure(figsize=(15,6))
x_values = list(usdt_hist.keys())
y_values = list(usdt_hist.values())
plt.plot(x_values, y_values)
plt.show()
def draw_trajectory(display_dt=False):
plt.figure(figsize=(12,9))
keys = list(crypto_hist.keys())
x_values = [init_price * x for x in list(crypto_hist.values())]
y_values = list(usdt_hist.values())
n = len(x_values)
u_values = [x_values[i] - y_values[i] for i in range(n)]
v_values = [x_values[i] + y_values[i] for i in range(n)]
plt.plot(u_values, v_values)
if display_dt:
for i in range(n//2):
plt.text(u_values[i*2+1], v_values[i*2+1], keys[i*2+1])
plt.show()
gains = [0 for i in range(0, 30)]
max_gain = 0
max_steps = 2
for steps in range(2, 30):
compute_params()
gain = trade(price_hist, False)
if gain > max_gain:
max_gain = gain
max_steps = steps
gains[steps] = gain
print(f"{steps:3d} steps: price step:{price_step:8.2f} gain:{gain:8.2f}")
plt.figure(figsize=(15,6))
plt.plot(gains)
plt.show()
steps = max_steps
print(f"{steps} steps")
compute_params()
for i in range(steps+1):
print(f"{i:3} {price_of_level(i):9.2f}")
draw_chart()
trade(price_hist, True)
draw_crypto_hist()
draw_usdt_hist()
draw_trajectory()
for achat in achats:
print(achat)
for vente in ventes:
print(vente)
for pair in pairs:
print_pair(pair)