APPENDIX:
Taker Fees Discussion Section Generator:
from tabulate import tabulate
from decimal import Decimal, getcontext
import textwrap
getcontext().prec = 100
ONE = Decimal("1")
TWO = Decimal("2")
# Curve Parameters
P_a = Decimal("2.3456")
P_b = Decimal("1.2345")
B = Decimal.sqrt(P_b)
S = Decimal.sqrt(P_a) - Decimal.sqrt(P_b)
y_int = Decimal("1000")
y = Decimal("500")
fee = Decimal("0.002")
def print_parameter_table():
table = (("Curve Parameter", "Value", "Notes"),
("$B$", f"{B:.6f}", "The highest ask (y = BASE), or lowest bid (y = QUOTE) boundary metric, depending on context."),
("$S$", f"{S:.6f}", "The range width parameter."),
("$y_{int}$", f"{y_int:.6f}", "The curve capacity metric."),
("$y$", f"{y:.6f}", "The remaining token balance"),
("$fee$", f"{fee:.6f}", "The protocol fee setting."))
print(tabulate(table, headers = "firstrow", tablefmt = "pipe", floatfmt = ".6f", numalign = "right", stralign = "left"))
print("\n")
return(None)
def print_summary_table(scenario_1, scenario_2):
table = (("Scenario", "Taker Sent", "Taker Received", "Maker Sent", "Maker Received", "Protocol Fee Collected"), scenario_1, scenario_2)
print(tabulate(table, headers = "firstrow", tablefmt = "pipe", floatfmt = ".6f", numalign = "right", stralign = "right"))
print("\n")
return(None)
def print_trade_by_target_text(taker_sends_1, maker_sends_1, taker_receives_1, protocol_receives_1):
text = (f"The taker requests to send exactly {taker_sends_1:.6f} QUOTE tokens to the protocol, all of which is swapped against the maker's order, and returns a value of {maker_sends_1:.6f} BASE tokens. Of the {maker_sends_1:.6f} BASE tokens relinquished by the maker's order, the taker keeps {taker_receives_1:.6f} BASE, and the protocol keeps {protocol_receives_1:.6f} BASE.")
print(textwrap.fill(text, width = 132))
print("\n")
return(None)
def print_trade_by_source_text(taker_receives_2, maker_receives_2, taker_sends_2, protocol_receives_2):
text = (f"The taker requests to receive exactly {taker_receives_2:.6f} BASE tokens from the protocol. To satisfy the requirements of the maker's order, exactly {maker_receives_2:.6f} QUOTE tokens must be exchanged (ignoring the fee). After adjusting for the protocol fee, the taker must send a total of {taker_sends_2:.6f} QUOTE tokens to the protocol. The protocol keeps {protocol_receives_2:.6f} QUOTE tokens, and the remaining {maker_receives_2:.6f} QUOTE tokens are exchanged with the maker's order for {taker_receives_2:.6f} BASE tokens, which are sent from the protocol to the taker.")
print(textwrap.fill(text, width = 132))
print("\n")
return(None)
text_functions = [print_trade_by_target_text, print_trade_by_source_text]
def trade_by_target(maker_receives):
maker_sends = maker_receives*(B*y_int + S*y)**TWO/(maker_receives*S*(B*y_int + S*y) + y_int**TWO)
return(maker_sends)
def trade_by_source(maker_sends):
maker_receives = (maker_sends*y_int**TWO)/((S*y + B*y_int)*(B*y_int + S*(y - maker_sends)))
return(maker_receives)
swap_functions = [trade_by_target, trade_by_source]
def apply_fee_trade_by_target(maker_sends):
taker_receives = maker_sends*(ONE - fee)
protocol_receives = maker_sends*fee
return(taker_receives, protocol_receives)
def apply_fee_trade_by_source(maker_receives):
taker_sends = maker_receives/(ONE - fee)
protocol_receives = taker_sends - maker_receives
return(taker_sends, protocol_receives)
fee_functions = [apply_fee_trade_by_target, apply_fee_trade_by_source]
protocol_fees = ["BASE", "QUOTE"]
def perform_swap(input_array):
scenarios = []
for i, j in enumerate(input_array):
print(f"##### *Scenario {i + 1}:*")
output = swap_functions[i](j)
fee_adjusted_outputs = fee_functions[i](output)
scenario_template = [f"{i + 1}", f"{j:.6f} QUOTE", f"{j:.6f} BASE", f"{j:.6f} BASE", f"{j:.6f} QUOTE", f"{fee_adjusted_outputs[1]:.6f} {'BASE' if i == 0 else 'QUOTE'}"]
scenario_template[2 - i] = f"{fee_adjusted_outputs[0]:.6f} {'BASE' if i == 0 else 'QUOTE'}"
scenario_template[3 + i] = f"{output:.6f} {'BASE' if i == 0 else 'QUOTE'}"
scenarios.append(tuple(scenario_template))
text_functions[i](j, output, fee_adjusted_outputs[0], fee_adjusted_outputs[1])
return(scenarios)
def numerator(seed_input, fee_multiplier):
return(seed_input*fee_multiplier*(B*y_int + S*y)**TWO)
def denominator(seed_input, fee_multiplier):
return(S*seed_input*fee_multiplier*(B*y_int + S*y) + y_int**TWO)
def create_examples(seed_input):
example_1_scenario_1 = example_2_scenario_1 = example_3_scenario_1 = seed_input
example_1_scenario_2 = numerator(seed_input, ONE)/denominator(seed_input, ONE)
example_2_scenario_2 = numerator(seed_input, ONE - fee)/denominator(seed_input, ONE)
example_3_scenario_2 = numerator(seed_input, ONE - fee)/denominator(seed_input, ONE - fee)
return((example_1_scenario_1, example_1_scenario_2),
(example_2_scenario_1, example_2_scenario_2),
(example_3_scenario_1, example_3_scenario_2))
def write_taker_fees_proposal_section(seed_input = Decimal('10')):
swaps = create_examples(seed_input)
subheadings = ("Constant Maker Send and Receive Amounts.",
"Constant Taker Receive Amount.",
"Constant Taker Send Amount.")
print_parameter_table()
for i, input_array in enumerate(swaps):
print(f"#### Example {i + 1}: {subheadings[i]}")
scenario_1, scenario_2 = perform_swap(input_array)
print(f"##### *Example {i + 1} Summary:*")
print_summary_table(scenario_1, scenario_2)
return(None)
write_taker_fees_proposal_section()