Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion components/black_scholes_options_pricing.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def __init__(
def get_put_option_price(self):
d1 = (
np.log(self.current_asset_price / self.strike_price)
+ (self.risk_free_rate + self.sigma ** 2 / 2) * self.option_expiration
+ (self.risk_free_rate + self.sigma**2 / 2) * self.option_expiration
) / (self.sigma * np.sqrt(self.option_expiration))
d2 = d1 - self.sigma * np.sqrt(self.option_expiration)
return self.strike_price * np.exp(
Expand Down
1,018 changes: 973 additions & 45 deletions files/aave_results.csv

Large diffs are not rendered by default.

1,018 changes: 973 additions & 45 deletions files/dydx_results.csv

Large diffs are not rendered by default.

31,000 changes: 1,000 additions & 30,000 deletions files/stgy.historical_data.csv

Large diffs are not rendered by default.

200 changes: 200 additions & 0 deletions hedge_scripts/Long_short/aave.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,200 @@
class Aave(object):

def __init__(self, config):
# assert self.dydx_class_instance == isinstance(dydx)
# assert config['debt'] == config['collateral_eth'] * config['borrowed_pcg']
self.market_price = config['market_price']

self.entry_price = config['entry_price']

self.collateral_eth_initial = config['collateral_eth']
self.collateral_eth = config['collateral_eth']
self.collateral_usdc = config['collateral_usdc']

self.reserve_margin_eth = 0
self.reserve_margin_usdc = 0

self.borrowed_percentage = config['borrowed_pcg']
self.usdc_status = config['usdc_status']

self.debt = config['debt']
self.debt_initial = config['debt']

self.ltv = config['ltv']
self.price_to_ltv_limit = config['price_to_ltv_limit']

self.lending_rate = 0
self.lending_rate_hourly = 0
self.interest_on_lending_eth = 0 # aggregated fees
self.interest_on_lending_usd = 0
self.lending_fees_eth = 0 # fees between last 2 prices
self.lending_fees_usd = 0

self.borrowing_rate = 0
self.borrowing_rate_hourly = 0
self.interest_on_borrowing = 0 # aggregated fees
self.borrowing_fees = 0 # fees between last 2 prices

self.lend_minus_borrow_interest = 0

self.costs = 0
# self.historical = pd.DataFrame()
# self.dydx_class_instance = dydx_class_instance
# self.staked_in_protocol = stk

# def update_costs(self):
# """
# it requires having called borrowing_fees_calc() in order to use updated values of last earned fees
# """
# # We have to substract lend_minus_borrow in order to increase the cost (negative cost means profit)
# self.costs = self.costs - self.lend_minus_borrow_interest

def collateral_usd(self):
return self.collateral_eth * self.market_price

def update_debt(self):
"""
it requires having called borrowing_fees_calc() in order to use updated values of last earned fees
"""
self.debt = self.debt + self.borrowing_fees

def update_collateral(self):
"""
it requires having called lending_fees_calc() in order to use updated values of last earned fees
"""
self.collateral_eth = self.collateral_eth + self.lending_fees_eth
self.collateral_usdc = self.collateral_usd()

def track_lend_borrow_interest(self):
"""
it requires having called borrowing_fees_calc() and lending_fees_calc()
in order to use updated values of last earned fees
"""
self.lend_minus_borrow_interest = self.interest_on_lending_usd - self.interest_on_borrowing

def lending_fees_calc(self, freq):
self.simulate_lending_rate()
self.lending_rate_freq = self.lending_rate / freq

# fees from lending are added to collateral? YES
# lending rate is applied to coll+lend fees every time or just to initial coll? COLL+LEND ie LAST VALUE
self.lending_fees_eth = self.collateral_eth * self.lending_rate_freq
self.lending_fees_usd = self.lending_fees_eth * self.market_price
self.interest_on_lending_eth = self.interest_on_lending_eth + self.lending_fees_eth
self.interest_on_lending_usd = self.interest_on_lending_usd + self.lending_fees_usd

def borrowing_fees_calc(self, freq):
self.simulate_borrowing_rate()
self.borrowing_rate_freq = self.borrowing_rate / freq

# fees from borrow are added to debt? YES
# borrowing rate is applied to debt+borrow fees every time or just to initial debt? DEBT+BORROW ie LAST VALUE
self.borrowing_fees = self.debt * self.borrowing_rate_freq
self.interest_on_borrowing = self.interest_on_borrowing + self.borrowing_fees

def simulate_lending_rate(self):
# self.lending_rate = round(random.choice(list(np.arange(0.5/100, 1.5/100, 0.25/100))), 6) # config['lending_rate']

# best case
# self.lending_rate = 1.5 / 100

# worst case
self.lending_rate = 0.5 / 100

def simulate_borrowing_rate(self):
# self.borrowing_rate = round(random.choice(list(np.arange(1.5/100, 2.5/100, 0.25/100))), 6) # config['borrowing_rate']

# best case
# self.borrowing_rate = 1.5/100

# worst case
self.borrowing_rate = 2.5/100

def ltv_calc(self):
if self.collateral_usd() == 0:
return 0
else:
return self.debt / self.collateral_usd()

def price_to_liquidation(self, dydx_class_instance):
return self.entry_price - (dydx_class_instance.short_pnl()
+ self.debt - self.lend_minus_borrow_interest) / self.collateral_eth

def price_to_ltv_limit_calc(self):
return round(self.entry_price * self.borrowed_percentage / self.ltv_limit(), 3)

def buffer_for_repay(self):
return 0.01

def ltv_limit(self):
return 0.5

# Actions to take
def return_usdc(self, stgy_instance):
gas_fees = stgy_instance.gas_fees
time = 0
if self.usdc_status:
# simulate 2min delay for tx
# update parameters
# AAVE parameters
self.usdc_status = False
# self.collateral_eth = 0
# self.collateral_usdc = 0
self.debt = 0
self.ltv = 0
self.price_to_ltv_limit = 0
# self.lending_rate = 0
# self.borrowing_rate = 0

# fees
self.costs = self.costs + gas_fees

time = 1
return time

def repay_aave(self, stgy_instance):
gas_fees = stgy_instance.gas_fees
dydx_class_instance = stgy_instance.dydx
# aave_class_instance = stgy_instance.aave
# dydx_client_class_instance = stgy_instance.dydx_client
#
time = 0
if self.usdc_status:
# update parameters
short_size_for_debt = self.debt / (self.market_price - dydx_class_instance.short_entry_price)
new_short_size = dydx_class_instance.short_size - short_size_for_debt

# pnl_for_debt = dydx_class_instance.pnl()
# We have to repeat the calculations for pnl and notional methods, but using different size_eth
pnl_for_debt = short_size_for_debt * (self.market_price - dydx_class_instance.short_entry_price)
self.debt = self.debt - pnl_for_debt
self.ltv = self.ltv_calc()

self.price_to_ltv_limit = round(self.entry_price * (self.debt / self.collateral_usdc) / self.ltv_limit(), 3)
self.costs = self.costs + gas_fees

dydx_class_instance.short_size = new_short_size
dydx_class_instance.short_notional = dydx_class_instance.short_notional_calc()
dydx_class_instance.short_equity = dydx_class_instance.short_equity_calc()
dydx_class_instance.short_leverage = dydx_class_instance.short_leverage_calc()
dydx_class_instance.short_pnl = dydx_class_instance.short_pnl_calc()
# dydx_class_instance.price_to_liquidation = \
# dydx_class_instance.price_to_liquidation_calc(dydx_client_class_instance)

# fees
# withdrawal_fees = pnl_for_debt * dydx_class_instance.withdrawal_fees
dydx_class_instance.simulate_maker_taker_fees()
notional_for_fees = abs(short_size_for_debt) * self.market_price
dydx_class_instance.short_costs = dydx_class_instance.short_costs \
+ dydx_class_instance.maker_taker_fees * notional_for_fees \
+ pnl_for_debt * dydx_class_instance.withdrawal_fees

# Note that a negative self.debt is actually a profit
# We update the parameters
if self.debt > 0:
self.usdc_status = True
else:
self.usdc_status = False
# simulate 2min delay for tx
time = 1
return time
137 changes: 137 additions & 0 deletions hedge_scripts/Long_short/command_center.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
import os
import json


from hedge_scripts.Short_only.stgyapp import StgyApp


def run_sim(period, slippage, floor, pcg):
global ocs
# Initialize everything
with open("Files/StgyApp_config.json") as json_file:
config = json.load(json_file)

# Initialize stgyApp
stgy = StgyApp(config)
# Period of Simulations
# period = ["2019-09-01","2019-12-31"]
stgy.historical_data = historical_data.loc[period[0] + ' 00:00:00':period[1] + ' 00:00:00']
# For vol updates we take all data up to the last date
stgy.launch(config)
# Load target_prices + intervals in stgy.historical_data
# First we calculate weighted vol
last_date = period[1] + ' 00:00:00'
vol = stgy.parameter_manager.calc_vol(last_date, historical_data)
mu, sigma = vol
# floor just in order to get triger_price['open_close_1'] = open_close_1
# Now we define prices and intervals given K and vol
stgy.parameter_manager.define_target_prices(stgy, slippage, vol, floor, pcg)
#########################
# Save historical data with trigger prices and thresholds loaded
# checking if the directory demo_folder
# exist or not.
if not os.path.exists("Files/From_%s_to_%s_open_close_at_%s" % (period[0], period[1], floor)):
# if the demo_folder directory is not present
# then create it.
os.makedirs("Files/From_%s_to_%s_open_close_at_%s" % (period[0], period[1], floor))
stgy.historical_data.to_csv("Files/From_%s_to_%s_open_close_at_%s/stgy.historical_data.csv"
% (period[0], period[1], floor))
#########################
# Here we define initial parameters for AAVE and DyDx depending on the price at which we are starting simulations

# Define initial and final index if needed in order to only run simulations in periods of several trigger prices
# As we calculate vol using first week of data, we initialize simulations from that week on
initial_index = 1

# Stk eth
stgy.stk = 1000000 / stgy.historical_data['close'][initial_index]

# AAVE
stgy.aave.market_price = stgy.historical_data['close'][initial_index]

# What is the price at which we place the collateral in AAVE given our initial_index?
stgy.aave.entry_price = stgy.aave.market_price
# We place 90% of staked as collateral and save 10% as a reserve margin
stgy.aave.collateral_eth = round(stgy.stk * 0.9, 3)
stgy.aave.collateral_eth_initial = round(stgy.stk * 0.9, 3)
stgy.reserve_margin_eth = stgy.stk * 0.1
# We calculate collateral and reserve current value
stgy.aave.collateral_usdc = stgy.aave.collateral_eth * stgy.aave.market_price
stgy.reserve_margin_usdc = stgy.aave.reserve_margin_eth * stgy.aave.market_price

# What is the usdc_status for our initial_index?
stgy.aave.usdc_status = True
stgy.aave.debt = (stgy.aave.collateral_eth_initial * stgy.aave.entry_price) * stgy.aave.borrowed_percentage
stgy.aave.debt_initial = (stgy.aave.collateral_eth_initial * stgy.aave.entry_price) * stgy.aave.borrowed_percentage
# debt_initial
stgy.aave.price_to_ltv_limit = round(stgy.aave.entry_price * stgy.aave.borrowed_percentage / stgy.aave.ltv_limit(),
3)
# stgy.total_costs = 104

# DyDx
stgy.dydx.market_price = stgy.historical_data['close'][initial_index]
# stgy.dydx.interval_current = stgy.historical_data['interval'][initial_index]
stgy.dydx.short_collateral = stgy.aave.debt
stgy.dydx.short_equity = stgy.dydx.short_equity_calc()
stgy.dydx.short_collateral_status = True
#########################
# Clear previous csv data for aave and dydx
stgy.data_dumper.delete_results(period, floor)
#########################
# add header to csv of aave and dydx
stgy.data_dumper.add_header(period, floor)
##################################
# Run through dataset
#########################
# import time
# # run simulations
# starttime = time.time()
# print('starttime:', starttime)
# for i in range(initial_index, len(stgy.historical_data)):
i = initial_index

maker_fees_counter = []
while (i < len(stgy.historical_data)):
# for i in range(initial_index, len(stgy.historical_data)):
# pass

# We reset costs in every instance
stgy.parameter_manager.reset_costs(stgy)
previous_market_price = stgy.historical_data["close"][i-1]
market_price = stgy.historical_data["close"][i]
#########################
# Update parameters
# First we update everything in order to execute scenarios with updated values
# We have to update
# AAVE: market_price, interval_current, lending and borrowing fees (and the diference),
# debt value, collateral value and ltv value
# DyDx: market_price, interval_current, notional, equity, leverage and pnl
stgy.parameter_manager.update_parameters(stgy, market_price)
##############################
stgy.parameter_manager.find_scenario(stgy, market_price, previous_market_price)
##############################
# Funding rates
# We add funding rates every 8hs (we need to express those 8hs based on our historical data time frequency)
# Moreover, we nee.named to call this method after find_scenarios in order to have all costs updated.
# Calling it before find_scenarios will overwrite the funding by 0
# We have to check all the indexes between old index i and next index i+time_used
# for index in range(i, i+time_used):
if (i % (8 * 60) == 0) and (stgy.dydx.short_status):
stgy.dydx.add_funding_rates()
# stgy.total_costs = stgy.total_costs + stgy.dydx.funding_rates
#########################
# Add costs
stgy.parameter_manager.add_costs(stgy)
stgy.parameter_manager.update_pnl(stgy)
#########################
# Write data
# We write the data into the google sheet or csv file acording to sheet value
# (sheet = True --> sheet, sheet = False --> csv)
stgy.data_dumper.write_data(stgy,
period, floor,
sheet=False)
#########################
# we increment index by the time consumed in executing actions
# i += time_used
i += 1
return maker_fees_counter
Loading