Home Blog First Stab at Genetic Algorithms for Forex trading
 

Long time, no update!  :)

I have settled on a platform for general Forex development, Open Forex Platform (http://www.openforexplatform.com/).  It is open source, it has extensive backtesting and charting capabilites, it currently integrates with MetaTrader 4, and can be made to integrate with just about any broker or data source.  It is also a .NET platform.  So it is not perfect :)  Given that Scala will soon be natively appearing on .NET (see here) and that IKVM allows for importing most Java libraries, the .NET-ness of it is not a major hurdle.

I have been playing around with the Java Genetic Algorithms Package v3.4.4 (http://jgap.sourceforge.net/) via C#, from within Visual Studio 2008.  Using IKVM it was actually pretty simple.

  1. Download the latest JGAP source from SourceForge.net.  Get the "Full" distro
  2. I used Eclipse for the next few steps, not because its Maven integration is so great, but because of the FatJar plugin. FatJar allows you to build one single jar file for a project that includes all of the external dependencies usually found in other jar files. (As the plugin author notes, sometimes doing this can be a license violation.  Use your best judgement.) Other IDEs probably have an equivalent but I don't know what they are.  So I used Eclipse :)
  3. Import the JGAP project into your Eclipse workspace, via the pom.xml
  4. Build a fatJar of JGAP using the right-click context menu. Verify the all of the  Mine was named JGAP_fat.jar.
  5. Compile a .NET assembly using IKVM.  The command i used was ikvmc -target:library JGAP_fat.jar. The output is JGAP_fat.dll
  6. Create a new solution in Visual Studio
  7. Create a new C# project
  8. Add assembly references to the C# project, for JGAP_fat.dll and all of the dlls found in the IKVM bin directory
  9. Voila, that's it!

To test whether JGAP would work properly in the .NET environment, I reimplemented the JGAP tutorial (found here) in C#.

Here is the output of a few runs:

JGAPTest.exe 75
The best solution contained the following:
3 quarters.
0 dimes.
0 nickels.
0 pennies.
For a total of 75 cents in 3 coins.

JGAPTest.exe 99
The best solution contained the following:
3 quarters.
2 dimes.
0 nickels.
4 pennies.
For a total of 99 cents in 9 coins.

Here is the source code:

<Click the article header to read the rest!>

 

using System;
using org.jgap;
using org.jgap.impl;


namespace JGAPTest
{
    class MinimizingMakeChangeFitnessFunction : FitnessFunction
    {
        private int m_targetAmount;

        public MinimizingMakeChangeFitnessFunction(int a_targetAmount)
        {
            if (a_targetAmount > 99 || a_targetAmount < 1 )
            {
                throw new ArgumentException("Amount greater than 99!");
            }
            m_targetAmount = a_targetAmount;
        }

        override protected  double evaluate(org.jgap.IChromosome a_subject)
        {
            int changeAmount = amountOfChange(a_subject);
            int totalCoins = getTotalNumberOfCoins(a_subject);
            int changeDifference = Math.Abs(m_targetAmount - changeAmount);

            // Step 1: Determine the distance of the amount represented by the
            // solution from the target amount. Since we know the maximum amount
            // of change is 99 cents, we'll subtract from that the difference
            // between the solution amount and the target amount. That will give
            // the desired effect of returning higher values for amounts close
            // to the target amount and lower values for amounts further away
            // from the target amount.
            // ------------------------------------------------------------------
            double fitness = (99 - changeDifference);

            // Step 2: If the solution amount equals the target amount, then
            // we add additional fitness points for solutions representing fewer
            // total coins.
            // -----------------------------------------------------------------
            if (changeAmount == m_targetAmount)
            {
                fitness += 100 - (10 * totalCoins);
            }

            if (fitness < 0)
            {
                fitness = 0;
            }
            return fitness;
        }

        /**
        * Calculates the total amount of change (in cents) represented by
        * the given chromosome and returns that amount.a
        */
        public static int amountOfChange(IChromosome a_potentialSolution)
        {
            int numQuarters = getNumberOfCoinsAtGene(a_potentialSolution, 0);
            int numDimes = getNumberOfCoinsAtGene(a_potentialSolution, 1);
            int numNickels = getNumberOfCoinsAtGene(a_potentialSolution, 2);
            int numPennies = getNumberOfCoinsAtGene(a_potentialSolution, 3);

            return (numQuarters * 25) + (numDimes * 10) + (numNickels * 5) +
                   numPennies;
        }

        public static int getNumberOfCoinsAtGene(IChromosome a_potentialSolution,
                                              int a_position)
        {
            java.lang.Integer anInt = (java.lang.Integer)
                a_potentialSolution.getGene(a_position).getAllele();
            return anInt.intValue();
        }

        public static int getTotalNumberOfCoins(IChromosome a_potentialsolution)
        {
            int totalCoins = 0;

            int numberOfGenes = a_potentialsolution.size();
            for (int i = 0; i < numberOfGenes; i++)
            {
                totalCoins += getNumberOfCoinsAtGene(a_potentialsolution, i);
            }

            return totalCoins;
        }
    }

    class MinimizingMakeChange
    {
        public static void Main(String[] args)
        {
            Configuration conf = new DefaultConfiguration();
            int targetAmount = Convert.ToInt32(args[0]);
            FitnessFunction myFunc =
              new MinimizingMakeChangeFitnessFunction(targetAmount);

            conf.setFitnessFunction(myFunc);

            Gene[] sampleGenes = new Gene[4];

            sampleGenes[0] = new IntegerGene(conf, 0, 3);  // Quarters
            sampleGenes[1] = new IntegerGene(conf, 0, 2);  // Dimes
            sampleGenes[2] = new IntegerGene(conf, 0, 1);  // Nickels
            sampleGenes[3] = new IntegerGene(conf, 0, 4);  // Pennies

            Chromosome sampleChromosome = new Chromosome(conf, sampleGenes);

            conf.setSampleChromosome(sampleChromosome);
            conf.setPopulationSize(500);

            Genotype population = Genotype.randomInitialGenotype(conf);

            for( int i = 0; i < 50; i++ )
            {
                population.evolve();
            }
            IChromosome bestSolutionSoFar = population.getFittestChromosome();

            Console.Out.WriteLine( "The best solution contained the following: " );

            Console.Out.WriteLine(
                MinimizingMakeChangeFitnessFunction.getNumberOfCoinsAtGene(
                    bestSolutionSoFar, 0 ) + " quarters." );

            Console.Out.WriteLine(
                MinimizingMakeChangeFitnessFunction.getNumberOfCoinsAtGene(
                    bestSolutionSoFar, 1 ) + " dimes." );

            Console.Out.WriteLine(
                MinimizingMakeChangeFitnessFunction.getNumberOfCoinsAtGene(
                    bestSolutionSoFar, 2 ) + " nickels." );

            Console.Out.WriteLine(
                MinimizingMakeChangeFitnessFunction.getNumberOfCoinsAtGene(
                    bestSolutionSoFar, 3 ) + " pennies." );

            Console.Out.WriteLine("For a total of " +
                MinimizingMakeChangeFitnessFunction.amountOfChange(
                    bestSolutionSoFar ) + " cents in " +
                MinimizingMakeChangeFitnessFunction.getTotalNumberOfCoins(
                    bestSolutionSoFar ) + " coins." );
        }
    }
}

 

 


Blog Navigation

The Latest

Scala on .NET

Posted by Eric Somdahl in Blog Entries

Towers of Hanoi in Scala

Posted by Eric Somdahl in Uncategorized
Joomla Templates by Joomlashack