Sample Codes

Input:

Weight Generator

  • Weight Part

import pandas as pd
import numpy as np
import itertools

def generate_weights_with_constraints_25(num_weights, num_simulation=70):
    possible_values = [0, 0.25, 0.5, 0.75, 1]
    simulations = []
    
    # Generate all possible combinations
    all_combinations = list(itertools.product(possible_values, repeat=num_weights))
    valid_combinations = [combo for combo in all_combinations if np.isclose(sum(combo), 1)]
    
    simulations = np.random.choice(len(valid_combinations), num_simulation, replace=False)
    simulations = [valid_combinations[i] for i in simulations]

    return simulations

# For 0.25 interval, total number of simulation are 70
num_weights = 5
num_simulation = 70

simulations = generate_weights_with_constraints_25(num_weights, num_simulation)
simulations = pd.DataFrame(simulations
  • Allocation Part

def generate_allcations_with_constraints_10(num_allocations, num_simulation=70):
    possible_values = [0, 0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0]
    simulations = []
    
    # Generate all possible combinations
    all_combinations = list(itertools.product(possible_values, repeat=num_allocations))
    valid_combinations = [combo for combo in all_combinations if np.isclose(sum(combo), 1)]
    
    simulations = np.random.choice(len(valid_combinations), num_simulation, replace=False)
    simulations = [valid_combinations[i] for i in simulations]

    return simulations

# For 0.1 interval, total number of allocations are 66
num_allocations = 3
num_simulation = 66

allocations_simulation = generate_allcations_with_constraints_10(num_allocations, num_simulation)
allocations_simulation = pd.DataFrame(allocations_simulation)
  • Data Combination

simulations['Re-Balance Frequence Day'] = 3
allocations_simulation['Re-Balance Frequence Day'] = 3


simulations_df = pd.merge(simulations, allocations_simulation, on='Re-Balance Frequence Day')
simulations_df = simulations_df.reset_index()

simulations_df = simulations_df.rename(columns={'index': 'Simulation ID',
                                       '0_y':'% Allocation for Priority 1', 
                                       '1_y':'% Allocation for Priority 2', 
                                       '2_y': '% Allocation for Priority 3',
                                       '0_x': 'Previous Funding Rate APR Weight',
                                       '1_x': 'Next Funding Rate APR Weight',
                                       '2_x': '3 Day Cum Funding APR Weight',
                                       3: '7 Day Cum Funding APR Weight',
                                       4: '30 Day Cum Funding APR Weight'
                                       })

simulations_df.to_csv('new_funding_rate_weight_df_2.csv', index=False)

Simulation Configurations Input:

  • funding rate weights input

  • allocation weights input

Historical Funding Rates Data:

simulations_df = pd.read_csv('/~path/funding_rate_weight_df.csv')

# Define the weights by properly calling tolist() with parentheses
W3 = simulations_df['3 Day Cum Funding APR Weight'].tolist()
W7 = simulations_df['7 Day Cum Funding APR Weight'].tolist()
W30 = simulations_df['30 Day Cum Funding APR Weight'].tolist()
W_next = simulations_df['Next Funding Rate APR Weight'].tolist()
W_prev = simulations_df['Previous Funding Rate APR Weight'].tolist()
A1 = simulations_df['% Allocation for Priority 1'].tolist()
A2 = simulations_df['% Allocation for Priority 2'].tolist()
A3 = simulations_df['% Allocation for Priority 3'].tolist()
F = simulations_df['Re-Balance Frequence Day'].tolist()

# Global weights for APR calculation
WEIGHTS = [W3, W7, W30, W_prev, W_next]
ALLOCATIONS = [A1, A2, A3]

Creating feasible DataFrame

# Load the data
with open('historical_funding_rates_0707.json', 'r') as file:
    data = json.load(file)

frames = []
for symbol, records in data.items():
    df = pd.json_normalize(records)
    df['symbol'] = symbol
    
    # Check if 'fundingRate' exists in the dataframe and convert to numeric
    if 'fundingRate' in df.columns:
        df['fundingRate'] = pd.to_numeric(df['fundingRate'], errors='coerce')
    else:
        df['fundingRate'] = pd.NA  # Assign a missing value indicator if 'fundingRate' is not present
    
    frames.append(df)

# Concatenate all frames into a single DataFrame
df = pd.concat(frames, ignore_index=True)

# Convert 'fundingTime' from milliseconds to a datetime object
df['fundingTime'] = pd.to_datetime(df['fundingTime'], unit='ms')

# Split 'fundingTime' into separate date and time components
df['date'] = df['fundingTime'].dt.date
df['time'] = df['fundingTime'].dt.time

# Drop rows where any column has NaN values
df = df.dropna()

# Sort by 'date' in descending order
df = df.sort_values(by='date', ascending=False)

# Display the first few rows to verify
df = df[['symbol', 'date', 'time', 'fundingRate', 'markPrice']]

Math functions & formulas:

  • Token Scores Function:

    'token_score_func(symbol, simulations_id, model_num)'

  • Simulation Realized APR Function:

    'simulation_apr_func(Tokens_names, simulations_id, model_num)'

def token_score_func(symbol, simulations_id, model_num):

    group = df.loc[df['symbol'] == symbol, 'fundingRate']
    i = len(group) % 90 + (model_num - 1) * 9

    aprs = [
        group.iloc[i : i + 9].mean() * 3 * 360 * 100,
        group.iloc[i : 21 + i].mean() * 3 * 360 * 100,
        group.iloc[i : 90 + i].mean() * 3 * 360 * 100,
        group.iloc[1 + i] * 3 * 360 * 100,
        group.iloc[i] * 3 * 360 * 100 
    ]
    
    #simulations_id = simulations_id - 1 
    weights = [W[simulations_id] for W in WEIGHTS]  # Gather weights for each APR based on simulation ID
    
    # Calculate the weighted APR score
    apr_score = sum(apr * weight for apr, weight in zip(aprs, weights))
    
    return apr_score
def simulation_apr_func(Tokens_names, simulations_id, model_num):
    top3_rates = []

    for symbol in Tokens_names:
        group = df.loc[df['symbol'] == symbol, 'fundingRate']
        i = len(group) % 90 + (model_num - 1) * 9
        rates = group.iloc[i - 9 : i ].mean()
        top3_rates.append(rates)
    
    allocations = [A[simulations_id] for A in ALLOCATIONS]
    sim_apr = sum(rate * allocation for rate, allocation in zip(top3_rates, allocations)) * 360 * 3
    
    return sim_apr
token_score = {}
simulaiton_id = simulations_df.index.tolist()
model_nums = range(1,11)
token_score_rank = []
simulation_avg_apr = {}

for id in simulaiton_id:
    simulation_total_apr = 0  

    for i in model_nums:
        token_score = {}
        simulation_apr = {}

        for symbol in symbols:        
            score = token_score_func(symbol, id, i)
            token_score[(symbol, id, i)] = score

        top3_score = dict(sorted(token_score.items(), key=lambda item: item[1],reverse=True)[:3])

        Token_names = [key[0] for key in top3_score.keys()]

        cal_apr = simulation_apr_func(Token_names, id, i)

        simulation_apr[(f'Model Num {i}', f'Simulation {id}')] = cal_apr
        simulation_total_apr += cal_apr 

    simulation_avg_apr[id] = simulation_total_apr / len(model_nums)


sorted_simulation_avg_apr = dict(sorted(simulation_avg_apr.items(), key=lambda item: item[1], reverse=True))
sorted_simulation_avg_apr

Output

  • Funding rate weight and Portfolio allocation configurations for monitor

max_realized_apr = [
    {'Simulation ID': key, 'Realized APR': value}
    for key, value in sorted_simulation_avg_apr.items()
]

max_realized_apr_token = [
    {'Simulation ID': key, 'Tokens': value}
    for key, value in simulation_top3_token.items()
]

max_realized_apr = pd.DataFrame(max_realized_apr)
max_realized_apr.reset_index(drop=True, inplace=True)

max_realized_apr_token = pd.DataFrame(max_realized_apr_token)

max_realized_apr = pd.merge(max_realized_apr, max_realized_apr_token, on='Simulation ID')
max_realized_apr.to_csv('max_realized_apr_may.csv', index=False)
max_realized_apr