Skip to content

Commit

Permalink
Merge pull request #1054 from ashis2004/44
Browse files Browse the repository at this point in the history
Optimizing_Dividend_Capture_Strategies_Using_Genetics_Algorithms added
  • Loading branch information
invigorzz313 authored Aug 9, 2024
2 parents caf1ec5 + 4da06bf commit 6ebb9c8
Show file tree
Hide file tree
Showing 3 changed files with 312 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,272 @@
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"provenance": []
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3"
},
"language_info": {
"name": "python"
}
},
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"id": "mIQHuRd1S9oz"
},
"outputs": [],
"source": [
"import pandas as pd\n",
"import numpy as np\n",
"import datetime\n",
"\n",
"# Generate synthetic data for dividend capture strategies\n",
"np.random.seed(42)\n",
"dates = pd.date_range(start='2020-01-01', end='2023-12-31', freq='D')\n",
"stock_prices = np.random.uniform(50, 150, len(dates))\n",
"dividends = np.zeros(len(dates))\n",
"dividend_dates = np.random.choice(dates, size=30, replace=False)\n",
"dividends[[dates.get_loc(date) for date in dividend_dates]] = np.random.uniform(0.5, 2.0, len(dividend_dates))\n",
"\n",
"# Create DataFrame\n",
"data_dividend = pd.DataFrame({\n",
" 'Date': dates,\n",
" 'Stock_Price': stock_prices,\n",
" 'Dividend': dividends\n",
"})\n",
"\n",
"# Save to CSV\n",
"data_dividend.to_csv('dividend_data.csv', index=False)\n"
]
},
{
"cell_type": "code",
"source": [
"import pandas as pd\n",
"import numpy as np\n",
"\n",
"# Load data\n",
"data_dividend = pd.read_csv('dividend_data.csv')\n",
"print(data_dividend.head())\n"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "gjjU7SRuTeQ4",
"outputId": "776eb83d-9f8a-4ea6-beb4-79b033474682"
},
"execution_count": 2,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
" Date Stock_Price Dividend\n",
"0 2020-01-01 87.454012 0.0\n",
"1 2020-01-02 145.071431 0.0\n",
"2 2020-01-03 123.199394 0.0\n",
"3 2020-01-04 109.865848 0.0\n",
"4 2020-01-05 65.601864 0.0\n"
]
}
]
},
{
"cell_type": "code",
"source": [
"def fitness_function(individual, data):\n",
" buy_signal = individual[0]\n",
" sell_signal = individual[1]\n",
"\n",
" capital = 100000 # Starting capital\n",
" position = 0\n",
" returns = 0\n",
"\n",
" for i in range(len(data)):\n",
" if data['Dividend'][i] > buy_signal and position == 0:\n",
" position = capital / data['Stock_Price'][i]\n",
" capital = 0\n",
"\n",
" if data['Dividend'][i] < sell_signal and position > 0:\n",
" capital = position * data['Stock_Price'][i]\n",
" returns += capital - 100000 # Net returns\n",
" position = 0\n",
"\n",
" return returns\n"
],
"metadata": {
"id": "gRes_Ds2Tgu5"
},
"execution_count": 3,
"outputs": []
},
{
"cell_type": "code",
"source": [
"def initialize_population(pop_size):\n",
" population = []\n",
" for _ in range(pop_size):\n",
" individual = np.random.uniform(0.01, 2.0, 2) # Random buy and sell signals\n",
" population.append(individual)\n",
" return population\n"
],
"metadata": {
"id": "JeS6oOJ0Ti_4"
},
"execution_count": 4,
"outputs": []
},
{
"cell_type": "code",
"source": [
"def selection(population, fitness_scores, num_parents):\n",
" parents = [population[idx] for idx in np.argsort(fitness_scores)[-num_parents:]]\n",
" return parents\n"
],
"metadata": {
"id": "cIw1EoJ3TkwW"
},
"execution_count": 5,
"outputs": []
},
{
"cell_type": "code",
"source": [
"def crossover(parents, offspring_size):\n",
" offspring = []\n",
" for _ in range(offspring_size):\n",
" parent1 = parents[np.random.randint(len(parents))]\n",
" parent2 = parents[np.random.randint(len(parents))]\n",
" crossover_point = np.random.randint(1, len(parent1))\n",
" child = np.concatenate((parent1[:crossover_point], parent2[crossover_point:]))\n",
" offspring.append(child)\n",
" return offspring\n"
],
"metadata": {
"id": "R0iURKc-TmtA"
},
"execution_count": 6,
"outputs": []
},
{
"cell_type": "code",
"source": [
"def mutation(offspring, mutation_rate):\n",
" for individual in offspring:\n",
" if np.random.rand() < mutation_rate:\n",
" mutation_point = np.random.randint(len(individual))\n",
" individual[mutation_point] = np.random.uniform(0.01, 2.0)\n",
" return offspring\n"
],
"metadata": {
"id": "0A3HvpApTpHS"
},
"execution_count": 7,
"outputs": []
},
{
"cell_type": "code",
"source": [
"def genetic_algorithm(data, num_generations, pop_size, num_parents, mutation_rate):\n",
" population = initialize_population(pop_size)\n",
"\n",
" for generation in range(num_generations):\n",
" fitness_scores = [fitness_function(individual, data) for individual in population]\n",
" parents = selection(population, fitness_scores, num_parents)\n",
" offspring_size = pop_size - len(parents)\n",
" offspring = crossover(parents, offspring_size)\n",
" offspring = mutation(offspring, mutation_rate)\n",
" population = parents + offspring\n",
"\n",
" best_fitness = np.max(fitness_scores)\n",
" print(f\"Generation {generation}: Best Fitness = {best_fitness}\")\n",
"\n",
" best_individual = population[np.argmax(fitness_scores)]\n",
" return best_individual\n",
"\n",
"# Run the genetic algorithm\n",
"num_generations = 50\n",
"pop_size = 100\n",
"num_parents = 20\n",
"mutation_rate = 0.01\n",
"\n",
"best_params = genetic_algorithm(data_dividend, num_generations, pop_size, num_parents, mutation_rate)\n",
"print(f\"Best Parameters (Buy Signal, Sell Signal): {best_params}\")\n"
],
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "RRwHYs15Troe",
"outputId": "98efbe20-c945-4bac-86bb-320dc4924314"
},
"execution_count": 8,
"outputs": [
{
"output_type": "stream",
"name": "stdout",
"text": [
"Generation 0: Best Fitness = 1065823.8186480976\n",
"Generation 1: Best Fitness = 1340050.1052260087\n",
"Generation 2: Best Fitness = 1340050.1052260087\n",
"Generation 3: Best Fitness = 1340050.1052260087\n",
"Generation 4: Best Fitness = 1340050.1052260087\n",
"Generation 5: Best Fitness = 1340050.1052260087\n",
"Generation 6: Best Fitness = 1340050.1052260087\n",
"Generation 7: Best Fitness = 1340050.1052260087\n",
"Generation 8: Best Fitness = 1340050.1052260087\n",
"Generation 9: Best Fitness = 1340050.1052260087\n",
"Generation 10: Best Fitness = 1340050.1052260087\n",
"Generation 11: Best Fitness = 1340050.1052260087\n",
"Generation 12: Best Fitness = 1340050.1052260087\n",
"Generation 13: Best Fitness = 1340050.1052260087\n",
"Generation 14: Best Fitness = 1340050.1052260087\n",
"Generation 15: Best Fitness = 1340050.1052260087\n",
"Generation 16: Best Fitness = 1340050.1052260087\n",
"Generation 17: Best Fitness = 1340050.1052260087\n",
"Generation 18: Best Fitness = 1340050.1052260087\n",
"Generation 19: Best Fitness = 1340050.1052260087\n",
"Generation 20: Best Fitness = 1340050.1052260087\n",
"Generation 21: Best Fitness = 1340050.1052260087\n",
"Generation 22: Best Fitness = 1340050.1052260087\n",
"Generation 23: Best Fitness = 1340050.1052260087\n",
"Generation 24: Best Fitness = 1340050.1052260087\n",
"Generation 25: Best Fitness = 1340050.1052260087\n",
"Generation 26: Best Fitness = 1340050.1052260087\n",
"Generation 27: Best Fitness = 1340050.1052260087\n",
"Generation 28: Best Fitness = 1340050.1052260087\n",
"Generation 29: Best Fitness = 1340050.1052260087\n",
"Generation 30: Best Fitness = 1340050.1052260087\n",
"Generation 31: Best Fitness = 1340050.1052260087\n",
"Generation 32: Best Fitness = 1340050.1052260087\n",
"Generation 33: Best Fitness = 1340050.1052260087\n",
"Generation 34: Best Fitness = 1340050.1052260087\n",
"Generation 35: Best Fitness = 1340050.1052260087\n",
"Generation 36: Best Fitness = 1340050.1052260087\n",
"Generation 37: Best Fitness = 1340050.1052260087\n",
"Generation 38: Best Fitness = 1340050.1052260087\n",
"Generation 39: Best Fitness = 1340050.1052260087\n",
"Generation 40: Best Fitness = 1340050.1052260087\n",
"Generation 41: Best Fitness = 1340050.1052260087\n",
"Generation 42: Best Fitness = 1340050.1052260087\n",
"Generation 43: Best Fitness = 1340050.1052260087\n",
"Generation 44: Best Fitness = 1340050.1052260087\n",
"Generation 45: Best Fitness = 1340050.1052260087\n",
"Generation 46: Best Fitness = 1340050.1052260087\n",
"Generation 47: Best Fitness = 1340050.1052260087\n",
"Generation 48: Best Fitness = 1340050.1052260087\n",
"Generation 49: Best Fitness = 1340050.1052260087\n",
"Best Parameters (Buy Signal, Sell Signal): [0.49135888 1.6493184 ]\n"
]
}
]
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Optimizing Dividend Capture Strategies Using Genetic Algorithms

This project focuses on optimizing dividend capture strategies through the use of genetic algorithms. Dividend capture strategy involves buying a stock just before its ex-dividend date and selling it after the dividend is paid out. The objective is to maximize the returns by optimizing the entry and exit points and other parameters using genetic algorithms.

## Table of Contents

- [Introduction](#introduction)
- [Requirements](#requirements)
- [Installation](#installation)
- [Usage](#usage)
- [Dataset](#dataset)
- [Methodology](#methodology)
- [Results](#results)

## Introduction

Dividend capture strategy aims to exploit the predictable drop in stock prices after the dividend is paid out. By using genetic algorithms, we can optimize the parameters involved in this strategy to maximize returns. Genetic algorithms simulate the process of natural selection by generating a population of potential solutions and evolving them over multiple generations.

## Requirements

- Python 3.8+
- pandas
- numpy
- matplotlib
- deap (Distributed Evolutionary Algorithms in Python)

Methodology
Initialization: Generate an initial population of potential solutions.
Evaluation: Evaluate the fitness of each solution based on the returns of the dividend capture strategy.
Selection: Select the best-performing solutions to form a new population.
Crossover: Combine pairs of solutions to create offspring with mixed characteristics.
Mutation: Introduce random changes to some solutions to maintain diversity.
Iteration: Repeat the evaluation, selection, crossover, and mutation steps for multiple generations.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
## Requirements

- Python 3.8+
- pandas
- numpy
- matplotlib
- deap (Distributed Evolutionary Algorithms in Python)

0 comments on commit 6ebb9c8

Please sign in to comment.