In the last couple of blogs, I mentioned about work on my research papers and I wanted to take a moment and point out the work of "Time Series Prediction Using Genetic and Gene Expression Programming", a C# sample done by Kirillov at
http://www.codeproject.com/KB/recipes/aforge.aspx
Figure 1 shows the interface for obtaining the prediction of a growing siusoid.
http://www.codeproject.com/KB/recipes/aforge.aspx
Figure 1 shows the interface for obtaining the prediction of a growing siusoid.
Figure 1. Genetic Programming Interface

The application using three Aforge components, AForge, AForge.Genetic, AForge.Controls for the estimation and interface. Since the copyright permits re-distribution for non-commerical use, I wanted to include it here to give an idea how to quickly one can create an application from an existing framework for the prediction of univariate time series such as stock prices. Also, not the framework construction, the use of worker threads. There is a worker thread, SearchSolution, for find the solution and two delegates for asynchronous calls to set control properties.
private delegate void SetTextCallback( System.Windows.Forms.Control control, string text )
private delegate void AddSubItemCallback( System.Windows.Forms.ListView control, int item, string subitemText )
I have remove some of the code because of length, in the declation of controls region, and the initializeComponent() method.
// AForge Framework
// Time Series Prediction using Genetic Programming and Gene Expression Programming
//
// Copyright © Andrew Kirillov, 2006
// andrew.kirillov@gmail.com
//
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.IO;
using System.Threading;
using AForge;
using AForge.Genetic;
using AForge.Controls;
namespace TimeSeries
{
///
/// Summary description for Form1.
///
public class MainForm : System.Windows.Forms.Form
{
private System.Windows.Forms.GroupBox groupBox1;// remove the code for the sake of exposition
//
private double[] data = null;
private double[,] dataToShow = null;
private int populationSize = 40;
private int iterations = 100;
private int windowSize = 5;
private int predictionSize = 1;
private int selectionMethod = 0;
private int functionsSet = 0;
private int geneticMethod = 0;
private int headLength = 20;
private Thread workerThread = null;
private bool needToStop = false;
private double[,] windowDelimiter = new double[2, 2] { { 0, 0 }, { 0, 0 } };
private double[,] predictionDelimiter = new double[2, 2] { { 0, 0 }, { 0, 0 } };
// Constructor
public MainForm( )
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
//
chart.AddDataSeries( "data", Color.Red, Chart.SeriesType.Dots, 5 );
chart.AddDataSeries( "solution", Color.Blue, Chart.SeriesType.Line, 1 );
chart.AddDataSeries( "window", Color.LightGray, Chart.SeriesType.Line, 1, false );
chart.AddDataSeries( "prediction", Color.Gray, Chart.SeriesType.Line, 1, false );
selectionBox.SelectedIndex = selectionMethod;
functionsSetBox.SelectedIndex = functionsSet;
geneticMethodBox.SelectedIndex = geneticMethod;
UpdateSettings( );
}
///
/// Clean up any resources being used.
///
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows Form Designer generated code
///
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
///
private void InitializeComponent()
{
//
//Removed the code
//
this.components = new System.ComponentModel.Container();
}
#endregion
///
/// The main entry point for the application.
///
[STAThread]
static void Main( )
{
Application.Run( new MainForm( ) );
}
// Delegates to enable async calls for setting controls properties
private delegate void SetTextCallback( System.Windows.Forms.Control control, string text );
private delegate void AddSubItemCallback( System.Windows.Forms.ListView control, int item, string subitemText );
// Thread safe updating of control's text property
private void SetText( System.Windows.Forms.Control control, string text )
{
if ( control.InvokeRequired )
{
SetTextCallback d = new SetTextCallback( SetText );
Invoke( d, new object[] { control, text } );
}
else
{
control.Text = text;
}
}
// Thread safe adding of subitem to list control
private void AddSubItem( System.Windows.Forms.ListView control, int item, string subitemText )
{
if ( control.InvokeRequired )
{
AddSubItemCallback d = new AddSubItemCallback( AddSubItem );
Invoke( d, new object[] { control, item, subitemText } );
}
else
{
control.Items[item].SubItems.Add( subitemText );
}
}
// On main form closing
private void MainForm_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
// check if worker thread is running
if ( ( workerThread != null ) && ( workerThread.IsAlive ) )
{
needToStop = true;
while ( !workerThread.Join( 100 ) )
Application.DoEvents( );
}
}
// Update settings controls
private void UpdateSettings( )
{
populationSizeBox.Text = populationSize.ToString( );
iterationsBox.Text = iterations.ToString( );
windowSizeBox.Text = windowSize.ToString( );
predictionSizeBox.Text = predictionSize.ToString( );
}
// Load data
private void loadDataButton_Click(object sender, System.EventArgs e)
{
// show file selection dialog
if ( openFileDialog.ShowDialog( ) == DialogResult.OK )
{
StreamReader reader = null;
// read maximum 50 points
double[] tempData = new double[50];
try
{
// open selected file
reader = File.OpenText( openFileDialog.FileName );
string str = null;
int i = 0;
//Read Data method removed
//
// Update prediction size
private void UpdatePredictionSize( )
{
if ( data != null )
{
// get new prediction size value
try
{
predictionSize = Math.Max( 1, Math.Min( 10, int.Parse(
predictionSizeBox.Text ) ) );
}
catch
{
predictionSize = 1;
}
// check if we have too few data
if ( data.Length - predictionSize - 1 < predictionsize =" 1;" text =" string.Empty;" i =" 0," n =" dataList.Items.Count;"> 1 )
dataList.Items[i].SubItems.RemoveAt( 1 );
}
}
// On button "Start"
private void startButton_Click( object sender, System.EventArgs e )
{
ClearSolution( );
// get population size
try
{
populationSize = Math.Max( 10, Math.Min( 100, int.Parse( populationSizeBox.Text
) ) );
}
catch
{
populationSize = 40;
}
// iterations
try
{
iterations = Math.Max( 0, int.Parse( iterationsBox.Text ) );
}
catch
{
iterations = 100;
}
// update settings controls
UpdateSettings( );
selectionMethod = selectionBox.SelectedIndex;
functionsSet = functionsSetBox.SelectedIndex;
geneticMethod = geneticMethodBox.SelectedIndex;
// disable all settings controls except "Stop" button
EnableControls( false );
// run worker thread
needToStop = false;
workerThread = new Thread( new ThreadStart( SearchSolution ) );
workerThread.Start( );
}
// On button "Stop"
private void stopButton_Click( object sender, System.EventArgs e )
{
// stop worker thread
needToStop = true;
while ( !workerThread.Join( 100 ) )
Application.DoEvents( );
workerThread = null;
}
// Worker thread
void SearchSolution( )
{
// constants
double[] constants = new double[10] { 1, 2, 3, 5, 7, 11, 13, 17, 19, 23 };
// create fitness function
TimeSeriesPredictionFitness fitness = new TimeSeriesPredictionFitness(
data, windowSize, predictionSize, constants );
// create gene function
IGPGene gene = ( functionsSet == 0 ) ?
(IGPGene) new SimpleGeneFunction( windowSize + constants.Length ) :
(IGPGene) new ExtendedGeneFunction( windowSize + constants.Length );
// create population
Population population = new Population( populationSize, ( geneticMethod == 0 ) ?
(IChromosome) new GPTreeChromosome( gene ) :
(IChromosome) new GEPChromosome( gene, headLength ),
fitness, ( selectionMethod == 0 ) ? (ISelectionMethod) new EliteSelection( ) :
( selectionMethod == 1 ) ? (ISelectionMethod) new RankSelection( ) :
(ISelectionMethod) new RouletteWheelSelection( )
);
// iterations
int i = 1;
// solution array
int solutionSize = data.Length - windowSize;
double[,] solution = new double[solutionSize, 2];
double[] input = new double[windowSize + constants.Length];
// calculate X values to be used with solution function
for ( int j = 0; j < bestfunction =" population.BestChromosome.ToString(" learningerror =" 0.0;" predictionerror =" 0.0;" j =" 0," n =" data.Length" k =" 0," b =" j">= n - predictionSize )
{
predictionError += Math.Abs( solution[j, 1] - data
[windowSize + j] );
}
else
{
learningError += Math.Abs( solution[j, 1] - data
[windowSize + j] );
}
}
// update solution on the chart
chart.UpdateDataSeries( "solution", solution );
// set current iteration's info
SetText( currentIterationBox, i.ToString( ) );
SetText( currentLearningErrorBox, learningError.ToString( "F3" ) );
SetText( currentPredictionErrorBox, predictionError.ToString( "F3" ) );
}
catch
{
// remove any solutions from chart in case of any errors
chart.UpdateDataSeries( "solution", null );
}
// increase current iteration
i++;
//
if ( ( iterations != 0 ) && ( i > iterations ) )
break;
}
// show solution
SetText( solutionBox, population.BestChromosome.ToString( ) );
for ( int j = windowSize, k = 0, n = data.Length; j < n; j++, k++ ) {
AddSubItem( dataList, j, solution[k, 1].ToString( ) );
}
// enable settings controls EnableControls( true );
}
// On "More settings" button click
private void moreSettingsButton_Click( object sender, System.EventArgs e ) {
ExSettingsDialog settingsDlg = new ExSettingsDialog( );
// init the dialog
settingsDlg.MaxInitialTreeLevel = GPTreeChromosome.MaxInitialLevel; settingsDlg.MaxTreeLevel = GPTreeChromosome.MaxLevel;
settingsDlg.HeadLength = headLength;
// show the dialog
if ( settingsDlg.ShowDialog( ) == DialogResult.OK ) {
GPTreeChromosome.MaxInitialLevel = settingsDlg.MaxInitialTreeLevel; GPTreeChromosome.MaxLevel = settingsDlg.MaxTreeLevel;
headLength = settingsDlg.HeadLength;
}
}
}
}
Reading this code, one can see that it is easy to use these three components and create a GUI to perform univariate time series analysis with genetic algorithms. Thus, you can download historical price series from Yahoo Finance and plug it into this application or your own customization and write an article on using genetic algorithms for forecasting stock prices at different temporal intervals. Furthermore, you could build on the interface to add more features and/or update the methods in the AForge.Genetic component.
No comments:
Post a Comment