def print_largest_absolute_savings_samples(per_pair_savings): for pair, trade_size, agg, pct_savings_list in data_import.pct_savings_gen( per_pair_savings): mean_savings = compute_mean(pct_savings_list) if abs(mean_savings) > 50: print( f"{pair} ${trade_size} vs {agg} mean_savings={mean_savings}%")
def print_avg_savings_per_pair_by_agg(per_pair_savings, only_trade_size=None, print_threshold=0, samples=False, min_stablecoins=0): for_trade_size = f"for Trade Size = {only_trade_size}" if only_trade_size else '' pair_agg_savings = defaultdict(lambda: defaultdict(list)) for pair, trade_size, agg, pct_savings in data_import.pct_savings_gen( per_pair_savings): if only_trade_size and trade_size != only_trade_size: continue if min_stablecoins == 1 and not has_stablecoin(pair): continue if min_stablecoins == 2 and not both_stablecoins(pair): continue pair_agg_savings[pair][agg] += pct_savings print( f"\n\nAverage Savings {for_trade_size} (min_stablecoins={min_stablecoins})" ) print(f"\nToken\tMean Pct. Savings") for pair, agg_savings in sorted(pair_agg_savings.items()): print(f"{pair[1]}\t{compute_mean(sum(agg_savings.values(), [])):.2f}") for agg, savings in agg_savings.items(): better_pct, worse_pct, same_pct = better_worse_same_pcts(savings) avg_savings = compute_mean(savings) if abs(avg_savings) > print_threshold: print( f" {agg:<8}\t{better_pct:>3}/{worse_pct:>3}/{same_pct:>3}\t{avg_savings:.2f}" ) if samples: print(f" {agg}:\t{savings}")
def print_savings_summary_by_pair_csv(per_pair_savings, only_trade_size, agg_names, only_token=None, min_stablecoins=0, label="Average Savings by ETH pair"): print(f"\n{label} trade size = {only_trade_size}") pair_agg_savings = defaultdict(lambda: defaultdict(list)) print(f"\nPair,{','.join(agg_names)}") for pair, trade_size, agg, pct_savings_list in data_import.pct_savings_gen( per_pair_savings): if trade_size != only_trade_size: continue # if only_token and only_token not in pair: continue # if only_token and pair[0] != only_token: continue if only_token and pair[1] != only_token: continue if min_stablecoins == 1 and not has_stablecoin(pair): continue if min_stablecoins == 2 and not both_stablecoins(pair): continue pair_agg_savings[pair][agg] += pct_savings_list for pair in sorted(pair_agg_savings): row = f"{pair[0]}/{pair[1]}" agg_savings = pair_agg_savings[pair] for agg in agg_names: if agg in agg_savings: row += f",{compute_mean(agg_savings[agg]) :.2f}" else: row += f"," print(row)
def aggregated_savings(per_token_savings): """Aggregates savings over all tokens for each trade_size""" per_trade_size_savings = defaultdict(lambda: defaultdict(list)) for token, trade_size, agg, totle_split_pct_savings_list in data_import.pct_savings_gen( per_token_savings): per_trade_size_savings[trade_size][agg] += totle_split_pct_savings_list return per_trade_size_savings
def do_neg_savings(per_token_savings, trade_sizes): neg_savings, pos_savings = defaultdict( lambda: defaultdict(int)), defaultdict(lambda: defaultdict(int)) neg_savings_without_fee = defaultdict(lambda: defaultdict(int)) for token, trade_size, agg, pct_savings in data_import.pct_savings_gen( per_token_savings): for pct in pct_savings: if pct > 0.0: pos_savings[agg][trade_size] += 1 else: neg_savings[agg][trade_size] += 1 if pct < -0.25: neg_savings_without_fee[agg][trade_size] += 1 neg_samples, pos_samples, neg_without_fee_samples = 0, 0, 0 aggs = sorted(list(set(neg_savings.keys()) | set(pos_savings.keys()))) for agg in aggs: neg_samples_agg = sum(neg_savings[agg].values()) neg_samples += neg_samples_agg neg_without_fee_samples_agg = sum( neg_savings_without_fee[agg].values()) neg_without_fee_samples += neg_without_fee_samples_agg pos_samples_agg = sum(pos_savings[agg].values()) pos_samples += pos_samples_agg total_samples_agg = neg_samples_agg + pos_samples_agg neg_pct_agg = 100.0 * neg_samples_agg / total_samples_agg neg_pct_without_fee_agg = 100.0 * neg_without_fee_samples_agg / total_samples_agg print( f"\nOut of {total_samples_agg} comparisons, Totle's price (without fees) was worse than {agg}'s {neg_without_fee_samples_agg} times, resulting in worse price {neg_pct_without_fee_agg:.1f}% of the time." ) # print(f"Out of {total_samples_agg} comparisons, Totle's fees exceeded the price savings {neg_samples_agg} times, resulting in negative price savings {neg_pct_agg:.1f}% of the time.") total_samples = neg_samples + pos_samples neg_pct = 100.0 * neg_samples / total_samples neg_pct_without_fee = 100.0 * neg_without_fee_samples / total_samples print( f"\n\nOut of {total_samples} comparisons, Totle's price (without fees) was worse than competitor's {neg_without_fee_samples} times, resulting in worse price {neg_pct_without_fee:.1f}% of the time." ) print( f"Out of {total_samples} comparisons, Totle's fees exceeded the price savings {neg_samples} times, resulting in negative price savings {neg_pct:.1f}% of the time." ) print_neg_savings_csv(pos_savings, neg_savings, aggs, trade_sizes, label="Negative Price Savings Pct. vs Competitors") print_neg_savings_csv(pos_savings, neg_savings_without_fee, aggs, trade_sizes, label="Worse price (without fees) vs Competitors")
def print_stablecoin_pcts(pair_savings): """counts what percent of savings were due to stablecoin/stablecoin pairs""" ss_count, all_count = 0, 0 for pair, trade_size, agg, pct_savings_list in data_import.pct_savings_gen( pair_savings): all_count += len(pct_savings_list) if has_stablecoin(pair): ss_count += len(pct_savings_list) # print(f"\n{ss_count}/{all_count} ({100*ss_count/all_count}%) outliers were stablecoin/stablecoin pairs") print( f"\n{ss_count}/{all_count} ({100*ss_count/all_count}%) involved a stablecoin" )
def print_avg_savings_per_pair_by_trade_size(per_pair_savings, only_trade_sizes): pairs_trade_size_savings = defaultdict(lambda: defaultdict(list)) for pair, trade_size, agg, pct_savings in data_import.pct_savings_gen( per_pair_savings): pairs_trade_size_savings[pair][trade_size] += pct_savings trade_size_strs = map(lambda ts: f"{ts:8.1f}", only_trade_sizes) print(f"Pair {''.join(trade_size_strs)}") for pair, trade_size_savings in pairs_trade_size_savings.items(): row = f"{str(pair):<16}" for ts in only_trade_sizes: row += f"{compute_mean(trade_size_savings[ts]):8.2f}" if ts in trade_size_savings else " " print(row)
def print_stablecoin_pairs(pair_savings, only_trade_sizes): pairs_trade_size_savings = defaultdict(lambda: defaultdict(list)) for pair, trade_size, agg, pct_savings_list in data_import.pct_savings_gen( pair_savings): if both_stablecoins(pair): pairs_trade_size_savings[pair][trade_size] += pct_savings_list mean_savings = compute_mean(pct_savings_list) # print(f"{pair} ${trade_size} vs {agg} mean_savings={mean_savings}%") trade_size_strs = map(lambda ts: f"{ts:8.1f}", only_trade_sizes) print(f"\nPair {''.join(trade_size_strs)}") for pair, trade_size_savings in sorted(pairs_trade_size_savings.items()): row = f"{str(pair):<16}" for ts in only_trade_sizes: row += f"{compute_mean(trade_size_savings[ts]):8.2f}" if ts in trade_size_savings else " " print(row)
def print_top_ten_pairs_savings(per_pair_savings, only_trade_size=None): for_trade_size = f"for Trade Size = {only_trade_size}" if only_trade_size else '' pair_savings = defaultdict(list) for pair, trade_size, exchange, pct_savings in data_import.pct_savings_gen( per_pair_savings): if only_trade_size and trade_size != only_trade_size: continue pair_savings[pair] += pct_savings avg_savings_pairs = {} for pair, savings_list in pair_savings.items(): avg_savings_pairs[compute_mean(savings_list)] = pair sorted_avg_savings_pairs = sorted(avg_savings_pairs.items()) print(f"\nTop 10 Negative Price Savings {for_trade_size}") for pct_savings, pair in sorted_avg_savings_pairs[0:10]: print(f"{pair[0]}/{pair[1]}\t{pct_savings:.2f}%") print(f"\nTop 10 Positive Price Savings {for_trade_size}") for pct_savings, pair in reversed(sorted_avg_savings_pairs[-10:-1]): print(f"{pair[0]}/{pair[1]}\t{pct_savings:.2f}%")
def print_avg_savings_by_pair(per_pair_savings, only_trade_size=None, only_aggs=None, show_only_to=False): token_savings = defaultdict(lambda: defaultdict(list)) for pair, trade_size, agg, pct_savings in data_import.pct_savings_gen( per_pair_savings): if only_trade_size and trade_size != only_trade_size: continue token_savings[pair][agg] += pct_savings print(f"\nAverage Savings by Pair for Trade Size={only_trade_size}") print(f"\nPair,{','.join(only_aggs)}") for pair, savings in sorted(token_savings.items()): row = f"{pair[1]}" if show_only_to else f"{pair[1]}>{pair[0]}" for agg in only_aggs: if agg in savings: row += f",{compute_mean(savings[agg]) :.2f}" else: row += f"," print(row)
def do_better_worse_same_by_trade_size(per_pair_savings, label): print(f"\n{label}") better_price, worse_price, same_price, total_samples = defaultdict( int), defaultdict(int), defaultdict(int), defaultdict(int) trade_sizes = set() total_samples for pair, trade_size, agg, pct_savings in data_import.pct_savings_gen( per_pair_savings): trade_sizes.add(trade_size) better_count, worse_count, same_count = better_worse_same_counts( pct_savings) better_price[trade_size] += better_count worse_price[trade_size] += worse_count same_price[trade_size] += same_count total_samples[trade_size] += better_count + worse_count + same_count better_pct, worse_pct, same_pct = {}, {}, {} for trade_size in trade_sizes: better_pct[trade_size] = 100.0 * better_price[ trade_size] / total_samples[trade_size] worse_pct[trade_size] = 100.0 * worse_price[ trade_size] / total_samples[trade_size] same_pct[trade_size] = 100.0 * same_price[trade_size] / total_samples[ trade_size] header = 'Totle price was better worse same' print(f"\n{header}") for trade_size in sorted(trade_sizes): print( f"{trade_size:<14} {better_pct[trade_size]:14.2f}% {worse_pct[trade_size]:14.2f}% {same_pct[trade_size]:14.2f}%" ) # do CSV *a, b, c, d = header.split() print(','.join([' '.join(a), b, c, d])) for trade_size in sorted(trade_sizes): print( f"{trade_size},{better_pct[trade_size]:.2f}%,{worse_pct[trade_size]:.2f}%,{same_pct[trade_size]:.2f}%" )
def do_better_worse_same_price(per_pair_savings, label, agg_breakdown=False): print(f"\n{label}") better_price, worse_price, same_price = defaultdict( lambda: defaultdict(int)), defaultdict( lambda: defaultdict(int)), defaultdict(lambda: defaultdict(int)) for token, trade_size, agg, pct_savings in data_import.pct_savings_gen( per_pair_savings): better_count, worse_count, same_count = better_worse_same_counts( pct_savings) better_price[agg][trade_size] += better_count worse_price[agg][trade_size] += worse_count same_price[agg][trade_size] += same_count better_price_samples, worse_price_samples, same_price_samples = 0, 0, 0 better_pct, worse_pct, same_pct = {}, {}, {} aggs = sorted( list( set(better_price.keys()) | set(worse_price.keys()) | set(worse_price.keys()))) for agg in aggs: better_price_samples_agg = sum(better_price[agg].values()) better_price_samples += better_price_samples_agg worse_price_samples_agg = sum(worse_price[agg].values()) worse_price_samples += worse_price_samples_agg same_price_samples_agg = sum(same_price[agg].values()) same_price_samples += same_price_samples_agg total_samples_agg = better_price_samples_agg + worse_price_samples_agg + same_price_samples_agg better_pct[agg] = 100.0 * better_price_samples_agg / total_samples_agg worse_pct[agg] = 100.0 * worse_price_samples_agg / total_samples_agg same_pct[agg] = 100.0 * same_price_samples_agg / total_samples_agg if agg_breakdown: header = 'Totle price was better worse same' print(f"\n{header}") for agg in aggs: print( f"{agg:<14} {better_pct[agg]:14.2f}% {worse_pct[agg]:14.2f}% {same_pct[agg]:14.2f}%" ) # do csv *a, b, c, d = header.split() print(','.join([' '.join(a), b, c, d])) for agg in aggs: print( f"{agg},{better_pct[agg]:.2f}%,{worse_pct[agg]:.2f}%,{same_pct[agg]:.2f}%" ) total_samples = better_price_samples + worse_price_samples + same_price_samples better_pct = 100.0 * better_price_samples / total_samples worse_pct = 100.0 * worse_price_samples / total_samples same_pct = 100.0 * same_price_samples / total_samples print("\n") print( f"Out of {total_samples} comparisons, Totle's price was better than competitor's {better_pct:.1f}% of the time, worse {worse_pct:.1f}% of the time, and the same {same_pct:.1f}% of the time." ) # print_neg_savings_csv(pos_savings, neg_savings, aggs, trade_sizes, label="Negative Price Savings Pct. vs Competitors") return total_samples