|
import pandas as pd |
|
import numpy as np |
|
|
|
def f(z, c, n): |
|
return c * abs(z)**n * (np.cos(n * np.angle(z)) + 1j * np.sin(n * np.angle(z))) * (1 + np.log(abs(z))) |
|
|
|
def buy_signal(data, c, n): |
|
if f(data['Close'].iloc[-1], c, n) > 0: |
|
return True |
|
else: |
|
return False |
|
|
|
def sell_signal(data, c, n): |
|
if f(data['Close'].iloc[-1], c, n) < 0: |
|
return True |
|
else: |
|
return False |
|
|
|
def trade(data, c, n): |
|
bought = False |
|
for i in range(len(data)): |
|
if buy_signal(data.iloc[i:i+1], c, n): |
|
if not bought: |
|
bought = True |
|
data.loc[i, 'Action'] = 'Buy' |
|
elif sell_signal(data.iloc[i:i+1], c, n): |
|
if bought: |
|
bought = False |
|
data.loc[i, 'Action'] = 'Sell' |
|
|
|
def backtest(data, c, n): |
|
trade(data, c, n) |
|
data['Return'] = data['Close'].pct_change() |
|
data['Strategy Return'] = data['Action'].shift(1) * data['Return'] |
|
strategy_return = data['Strategy Return'].sum() |
|
return strategy_return |
|
|
|
def genetic_algorithm(population_size, num_generations): |
|
population = [] |
|
for i in range(population_size): |
|
c = np.random.uniform(0.01, 0.2) |
|
n = np.random.randint(2, 10) |
|
individual = (c, n) |
|
population.append(individual) |
|
|
|
for generation in range(num_generations): |
|
offspring = [] |
|
for i in range(int(population_size / 2)): |
|
parent1 = population[np.random.randint(0, population_size)] |
|
parent2 = population[np.random.randint(0, population_size)] |
|
|
|
offspring1 = parent1 |
|
offspring2 = parent2 |
|
|
|
if np.random.rand() < 0.5: |
|
offspring1 = (offspring1[0] + offspring2[0]) / 2, offspring1[1] |
|
else: |
|
offspring1 = offspring1[0], (offspring1[1] + offspring2[1]) / 2 |
|
|
|
offspring.append(offspring1) |
|
offspring.append(offspring2) |
|
|
|
population = offspring |
|
|
|
for i in range(len(population)): |
|
c = population[i][0] |
|
n = population[i][1] |
|
|
|
population[i] = (c, n) |
|
|
|
best_individual = population[0] |
|
for individual in population: |
|
data = pd.read_csv('data.csv', index_col='Date', parse_dates=True) |
|
strategy_return = backtest(data.iloc[i:i+1], individual[0], individual[1]) |
|
if strategy_return > best_individual[2]: |
|
best_individual = individual + (strategy_return,) |
|
|
|
print(f"Generation {generation + 1} Best Individual: {best_individual}") |
|
|
|
return best_individual |
|
|
|
best_individual = genetic_algorithm(population_size=100, num_generations=100) |
|
print(f"Overall Best Individual: {best_individual}") |