Forex automatic trading with genetic algorithm Part 2 Evolving trading AI implementation

Previous article

FX automatic trading system made with python and genetic algorithm part 1

Things to make this time

In Part 1 of the last time, I wrote the basic AI and the whole mechanism, so this time I defined a complicated trading AI and actually genetic algorithm I will evolve it with.

Define complex trading AI

■ Specifications The current market price is divided into patterns according to the current rate, 4-hour average rate, 24-hour average rate, highest and lowest prices in the last 25 business days, and the highest and lowest prices in the last 25 business days. Place an appropriate order from 10 years of trading data (appropriate value is calculated by genetic algorithm and obtained from past data).

■ Operation example Currency: Dollar Yen Current time: October 1, 2015 10:00:00 Current rate: 120.00 yen 4-hour average rate: 119.80 yen 24-hour average rate: 119.40 yen Highest price in the last 25 business days: 121.75 yen Lowest price in the last 25 business days: 117.25 yen Days elapsed from the highest price in the last 25 business days: 2 days Elapsed days from the lowest price in the last 25 business days: 8 days Order details: 120 yen for 100 units BUY, profit taking 120.60 yen, loss cut 119.75 yen

genetic.py


# -*- coding: utf-8 -*-
import random
import datetime
from enum import Enum

def order(ai_order):
    _base = "OrderDone:{}, Limit:{}, Stop-Limit:{}"
    print _base.format(ai_order.order_type,
                       ai_order.limit,
                       ai_order.stop_limit)


class OrderType(Enum):
    Buy = 1
    Wait = 0
    Sell = -1


class Rate(object):
    start_at = datetime.datetime(2015, 10, 1, 10, 0, 0)
    bid = float(120.00)  #Current rate
    h4 = float(119.80)  #Average rate for the last 4 hours
    h24 = float(119.40)  #Average rate for the last 24 hours
    low_25d = float(117.25)  #Lowest price in the last 25 business days
    high_25d = float(121.75)  #Highest price in the last 25 business days
    low_25d_passed_day = 8  #How many days have passed since the lowest price in the last 25 business days
    high_25d_passed_day = 2  #How many days have passed since the highest price in the last 25 business days
    base_tick = float(0.01)  #Minimum trading unit per tick

    @classmethod
    def get(cls, currency=None, start_at=None):
        return Rate()

    def get_rate(self, tick, is_add):
        if is_add:
            return self.bid + float(tick * self.base_tick)
        else:
            return self.bid - float(tick * self.base_tick)


class AIOrder(object):
    def __init__(self, order_type, limit, stop_limit):
        self.order_type = order_type
        self.limit = limit
        self.stop_limit = stop_limit


class MarketKeyMixin(object):
    def get_key_h24(self):
        """
Returns a key that represents the difference between the current rate and the average over the last 24 hours
Example) H24:5
        :rtype: str
        """
        point = (self.rate.bid - self.rate.h24) / self.rate.base_tick
        return 'H24:{}'.format(int(point / self.standard_tick))

    def get_key_h4(self):
        """
Returns a key that represents the difference between the current rate and the average of the last 4 hours
Example) H4:0
        :rtype: str
        """
        point = (self.rate.bid - self.rate.h4) / self.rate.base_tick
        return 'H4:{}'.format(int(point / self.standard_tick))

    def get_key_low_25d(self):
        """
Returns a key that represents the discrepancy between the current rate and the lowest price in the last 25 business days
Example) LOW:3
        :rtype: str
        """
        point = (self.rate.bid - self.rate.low_25d) / self.rate.base_tick
        return 'LOW:{}'.format(int(point / self.standard_tick))

    def get_key_high_25d(self):
        """
Returns the key that represents the discrepancy between the current rate and the highest price in the last 25 business days
Example) HIGH:2
        :rtype: str
        """
        point = (self.rate.bid - self.rate.high_25d) / self.rate.base_tick
        return 'HIGH:{}'.format(int(point / self.standard_tick))

    def get_key_low_passed_day(self):
        """
How many days have passed since the lowest price in the last 25 business days
Example) LOW_PASSED_DAY:10
        :rtype: str
        """
        return 'LOW_PASSED_DAY:{}'.format(self.rate.low_25d_passed_day)

    def get_key_high_passed_day(self):
        """
How many days have passed since the highest price in the last 25 business days
Example) HIGH_PASSED_DAY:1
        :rtype: str
        """
        return 'HIGH_PASSED_DAY:{}'.format(self.rate.high_25d_passed_day)


class AIParamValue(object):
    """
Class that defines AI operation data
    """
    def __init__(self, value, _min, _max):
        self.value = value
        self._min = _min
        self._max = _max

    def __repr__(self):
        return "VALUE:{},MIN:{},MAX:{}".format(self.value,
                                               self._min,
                                               self._max)

    def mutation(self):
        """
mutation
        """
        self.value = random.randint(self._min, self._max)
        return self


class AIParamOrder(object):
    """
Class that defines the operation at the time of ordering in the AI operation data
    """
    def __init__(self, order_type, limit, stop_limit, _min, _max):
        self.order_type = order_type
        self.limit = limit
        self.stop_limit = stop_limit
        self._min = _min
        self._max = _max

    def __repr__(self):
        _base = "ORDER-TYPE:{},LIMIT:{},STOP-LIMIT:{},MIN:{},MAX:{}"
        return _base.format(self.order_type,
                            self.limit,
                            self.stop_limit,
                            self._min,
                            self._max)

    def mutation(self):
        """
mutation
        """
        self.order_type = random.choice(list(OrderType))
        self.limit = random.randint(self._min, self._max)
        self.stop_limit = random.randint(self._min, self._max)
        return self


class AI(MarketKeyMixin):
    DEFAULT_STANDARD_TICK = 30
    DEFAULT_MIN = 15
    DEFAULT_MAX = 120
    #Save AI operation data
    param = {
        'DEFAULT_STANDARD_TICK': AIParamValue(DEFAULT_STANDARD_TICK, DEFAULT_MIN, DEFAULT_MAX)
    }

    def __init__(self, rate):
        self.rate = rate

    def order(self):
        """
Order.
        """
        order(self._get_order())

    def get_key(self):
        """
Analyze and classify Rate and generate appropriate KEY

        # sample
        'H24:5,H4:0,LOW:4,LOW_PASSED_DAY:3,HIGH:3,HIGH_PASSED_DAY:6'
        """
        _base = [self.get_key_h24(),
                 self.get_key_h4(),
                 self.get_key_low_25d(),
                 self.get_key_high_25d(),
                 self.get_key_low_passed_day(),
                 self.get_key_high_passed_day()]
        return ",".join(_base)

    def _get_order(self):
        """
Return order class
        rtype: AIOrder
        """
        #Analyze Rate
        key = self.get_key()
        _o = self.param.get(key, None)
        if _o is None:
            #Randomly generate and save when AI order data does not exist
            _o = self._get_random_order()
            self.param[key] = _o

        #Generation of order data
        limit_rate = self.rate.get_rate(_o.limit, True)
        stop_limit_rate = self.rate.get_rate(_o.stop_limit, False)
        return AIOrder(_o.order_type, limit_rate, stop_limit_rate)

    def _get_random_order(self):
        """
Randomly generate initial data when AI order data does not exist
        """
        return AIParamOrder(random.choice(list(OrderType)),
                            0,
                            0,
                            self.DEFAULT_MIN,
                            self.DEFAULT_MAX).mutation()

    def _get_order_type(self):
        if self.rate.bid > self.rate.h24:
            return OrderType.Buy
        if self.rate.h24 > self.rate.bid:
            return OrderType.Sell
        return OrderType.Wait

    @property
    def standard_tick(self):
        return self.param.get('DEFAULT_STANDARD_TICK').value


#Get rate
rate = Rate.get(currency='USDJPY', start_at=datetime.datetime.now())

#AI generation
ai = AI(rate)

#Order
ai.order()

print ai.param

>>python genetic.py
>>OrderDone:OrderType.Sell, Limit:122.37, Stop-Limit:117.22
>>{'DEFAULT_STANDARD_TICK': VALUE:30,MIN:10,MAX:400, 'H24:1,H4:0,LOW:9,HIGH:-5,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:237,STOP-LIMIT:278,MIN:10,MAX:400}

There are two points in this program.

  1. AI is only implementing the current market price by patterning
  2. If the AI itself does not have trading data, the _get_random_order function defines the behavior at random by itself.

If you suppress these two points, you will be able to easily and beautifully write the self-evolving logic by the genetic algorithm in the next section.

Backtesting for the past 10 years with the created trading AI

Since the trading AI has been completed, we will carry out a back test with the data for the past 10 years. Since the first generation AI will be a random search, a sad AI that will lose 1 million yen per year mainly for commissions has been born in transactions in units of 10,000 dollars.

genetic.py


print ai.param

{
'H24:0,H4:3,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Wait,LIMIT:66,STOP-LIMIT:71,MIN:15,MAX:120, 
'H24:0,H4:0,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:29,STOP-LIMIT:23,MIN:15,MAX:120, 
'H24:-3,H4:3,LOW:-7,HIGH:-22,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:86,STOP-LIMIT:35,MIN:15,MAX:120, 
'H24:3,H4:3,LOW:-4,HIGH:-19,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:98,STOP-LIMIT:76,MIN:15,MAX:120, 
'H24:-3,H4:0,LOW:12,HIGH:-2,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:78,STOP-LIMIT:64,MIN:15,MAX:120, 
'H24:0,H4:0,LOW:9,HIGH:-5,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:92,STOP-LIMIT:62,MIN:15,MAX:120, 
'H24:-3,H4:0,LOW:5,HIGH:-9,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:82,STOP-LIMIT:115,MIN:15,MAX:120, 
'H24:0,H4:-3,LOW:0,HIGH:-15,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:108,STOP-LIMIT:109,MIN:15,MAX:120, 
'H24:3,H4:-3,LOW:-4,HIGH:-19,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:100,STOP-LIMIT:42,MIN:15,MAX:120, 
'H24:-3,H4:0,LOW:-7,HIGH:-22,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:63,STOP-LIMIT:72,MIN:15,MAX:120, 
'H24:3,H4:0,LOW:9,HIGH:-5,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Wait,LIMIT:64,STOP-LIMIT:89,MIN:15,MAX:120, 
'H24:0,H4:0,LOW:5,HIGH:-9,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:94,STOP-LIMIT:16,MIN:15,MAX:120, 
'H24:3,H4:-3,LOW:5,HIGH:-9,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Wait,LIMIT:50,STOP-LIMIT:117,MIN:15,MAX:120, 
'H24:0,H4:3,LOW:9,HIGH:-5,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:112,STOP-LIMIT:24,MIN:15,MAX:120, 
'H24:3,H4:0,LOW:-10,HIGH:-25,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:74,STOP-LIMIT:50,MIN:15,MAX:120, 
'H24:3,H4:3,LOW:-10,HIGH:-25,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:20,STOP-LIMIT:111,MIN:15,MAX:120, 
...
}

The contents of AI are composed of meta data that is difficult for humans to handle. We will evolve this AI with a genetic algorithm.

Generate next-generation AI with genetic algorithms

■ What is a genetic algorithm? The genetic algorithm roughly transitions in the following flow. In this section, we will generate the next generation by crossing 3.

  1. Initial population generation
  2. Evaluation
  3. Generation of the next generation by crossing
  4. Loop through 2-3 to repeat generations.

■ Generation of the next generation by crossing Various methods have been proposed for crossover, but I chose the method that is relatively famous and has good calculation efficiency.

■ Specifications for crossover and next-generation generation

  1. Do not use elitism (a selection method that always leaves the best individuals of that generation for the next generation)
  2. Parents select by roulette selection method
  3. Cross two parents to produce two children
  4. Apply a two-point crossover algorithm for crossover
  5. Mutation occurs with a 1% probability when each gene crosses
  6. When each gene crosses, there is an 85% chance that two-point crossing will occur.
  7. There is a 14% chance that nothing will happen when each gene crosses
  8. Be sure to have 20 next generation

■ About roulette selection method Example) AI-1 makes a profit of 1 million yen AI-2 makes a profit of 500,000 yen AI-3 makes a profit of 100,000 yen When

The probability that AI-1 will be selected as a parent is 100 / (100 + 50 + 10) = 62.5% The probability that AI-2 will be selected as a parent is 50 / (100 + 50 + 10) = 31.25% The probability that AI-3 will be selected as a parent is 10 / (100 + 50 + 10) = 6.55%

■ About the two-point crossover algorithm I implemented it by referring to Introduction to Genetic Algorithms.

スクリーンショット 2015-10-02 14.47.51.png

■ Please be careful! Parent selection, crossover, and mutation methods have a significant impact on the performance of genetic algorithms. Please choose the method with great care.

genetic_mixin.py


# -*- coding: utf-8 -*-
import random
import datetime
from enum import Enum


def mutation(_min, _max):
    """
mutation
    :param _min: int
    :param _max: int
    """
    return random.randint(_min, _max)


def cross_2point(a, b, _min, _max):
    """
Two-point crossing
    :param a: int
    :param b: int
    """
    a = format(a, 'b')
    b = format(b, 'b')
    max_length = max([len(a), len(b)])
    if len(a) < max_length:
        a = '0' * (max_length - len(a)) + a
    if len(b) < max_length:
        b = '0' * (max_length - len(b)) + b
    point1 = random.randint(1, max_length)
    point2 = random.randint(1, max_length)
    point_max = max(point1, point2)
    point_min = min(point1, point2)
    _a = a[:point_min] + b[point_min:point_max] + a[point_max:]
    _b = b[:point_min] + a[point_min:point_max] + b[point_max:]
    _a_point = int(_a, 2)
    _b_point = int(_b, 2)

    #Round to each value when it is below the minimum value or above the maximum value
    def adjust(value, _min, _max):
        if value > _max:
            return _max
        if value < _min:
            return _min
        return value

    _a_point = adjust(_a_point, _min, _max)
    _b_point = adjust(_b_point, _min, _max)

    return _a_point, _b_point


def roulette_selection(ai_group):
    """
Genetic algorithm
Roulette selection method Select score as weight
    :param ai_group: list of AI
    :rtype : AI
    """
    #Use the correction value when the score is negative
    correct_value = min([ai.score(0) for ai in ai_group])
    if correct_value > 0:
        correct_value = 0

    #Calculate with the roulette selection method
    total = sum([ai.score(correct_value) for ai in ai_group])
    r = random.randint(0, total)
    _total = 0
    for ai in ai_group:
        _total += ai.score(correct_value)
        if r <= _total:
            return ai
    raise ValueError


class OrderType(Enum):
    Buy = 1
    Wait = 0
    Sell = -1

    @classmethod
    def cross_2point(cls, a, b):
        """
Cross
        :param a: OrderType
        :param b: OrderType
        """
        value_a, value_b = cross_2point(a.value + 1, b.value + 1, 0, 2)
        a_value = cls(value_a - 1)
        b_value = cls(value_b - 1)
        return a_value, b_value


class AIParamValue(object):
    """
Class that defines AI operation data
    """
    def __init__(self, value, _min, _max):
        self.value = value
        self._min = _min
        self._max = _max

    def __repr__(self):
        return "VALUE:{},MIN:{},MAX:{}".format(self.value,
                                               self._min,
                                               self._max)

    def cross_2point(self, b):
        """
Two-point crossing
        """
        a = self
        value_a, value_b = cross_2point(a.value, b.value, a._min, a._max)
        a.value = value_a
        b.value = value_b
        return a, b

    def mutation(self):
        """
mutation
        """
        self.value = random.randint(self._min, self._max)
        return self


class AIParamOrder(object):
    """
Class that defines the operation at the time of ordering in the AI operation data
    """
    def __init__(self, order_type, limit, stop_limit, _min, _max):
        self.order_type = order_type
        self.limit = limit
        self.stop_limit = stop_limit
        self._min = _min
        self._max = _max

    def __repr__(self):
        _base = "ORDER-TYPE:{},LIMIT:{},STOP-LIMIT:{},MIN:{},MAX:{}"
        return _base.format(self.order_type,
                            self.limit,
                            self.stop_limit,
                            self._min,
                            self._max)

    def cross_2point(self, b):
        """
Two-point crossing
        """
        a = self
        # order_Cross type
        order_type_a, order_type_b = OrderType.cross_2point(a.order_type, b.order_type)
        a.order_type = order_type_a
        b.order_type = order_type_b

        #Cross limit
        limit_a, limit_b = cross_2point(a.limit, b.limit, a._min, a._max)
        a.limit = limit_a
        b.limit = limit_b

        # stop_Cross limit
        stop_limit_a, stop_limit_b = cross_2point(a.stop_limit, b.stop_limit, a._min, a._max)
        a.stop_limit = stop_limit_a
        b.stop_limit = stop_limit_b

        return a, b

    def mutation(self):
        """
mutation
        """
        self.order_type = random.choice(list(OrderType))
        self.limit = random.randint(self._min, self._max)
        self.stop_limit = random.randint(self._min, self._max)
        return self


class GeneticMixin(object):
    @classmethod
    def cross_over(cls, size, ai_group):
        """
Genetic algorithm
Cross-blend
        """
        #size must be even
        if size % 2 != 0:
            raise AssertionError

        #Elitism(Leave the top 3)
        # elite_group = sorted(ai_group, key=lambda x: x.score(0), reverse=True)[:3]
        # elite_group = copy.deepcopy(elite_group)
        # elite_group = [ai.incr_generation() for ai in elite_group]

        #Select parents by roulette selection method and cross
        next_ai_group = []
        while len(next_ai_group) != size:
            next_ai_group += cls._cross(roulette_selection(ai_group),
                                        roulette_selection(ai_group))
        return next_ai_group

    @classmethod
    def _cross(cls, ai_a, ai_b):
        """
Crossing two parents to produce two children
        :param ai_a: AI
        :param ai_b: AI
        :return: list of AI
        """
        #Incr generation
        generation = ai_a.generation + 1
        child_a_param = {}
        child_b_param = {}
        for key in ai_a.param:
            _value_a = ai_a.param.get(key)
            _value_b = ai_b.param.get(key)
            #Cross for each gene
            _a, _b = cls._cross_value(_value_a, _value_b)
            child_a_param[key] = _a
            child_b_param[key] = _b

        #Generate child
        child_a = cls.create_child(child_a_param, generation)
        child_b = cls.create_child(child_b_param, generation)
        return [child_a, child_b]

    @classmethod
    def create_child(cls, param, generation):
        """
Generate the next generation
        :param param: dict
        :param generation: int
        :rtype: cls
        """
        ai = cls()
        ai.param = param
        ai.generation = generation
        return ai

    @classmethod
    def _cross_value(cls, value_a, value_b):
        """
Cross genes
        :param value_a: AIParamValue or AIParamOrder
        :param value_b: AIParamValue or AIParamOrder
        :return: int or list
        """
        if random.randint(1, 100) == 1:
            #mutation
            return value_a.mutation(), value_a.mutation()
        elif random.randint(1, 100) <= 85:
            #Two-point crossing
            return value_a.cross_2point(value_b)
        else:
            #do nothing
            return value_a, value_b


class AI(GeneticMixin):
    DEFAULT_STANDARD_TICK = 30
    DEFAULT_MIN = 15
    DEFAULT_MAX = 120
    param = {}
    generation = 0  #generation

    def __repr__(self):
        return "No.{}Generation AI PARAM:{}".format(self.generation, str(self.param))

    def score(self, correct_value):
        """
Return the score of the back test result
Profit throughout the period

        :param correct_value: float
        :rtype : int
        """
        return self.profit - correct_value

    def get_random_order(self):
        """
Randomly generate initial data when AI order data does not exist
        """
        return AIParamOrder(random.choice(list(OrderType)),
                            0,
                            0,
                            self.DEFAULT_MIN,
                            self.DEFAULT_MAX).mutation()


def gen_random_ai_parame():
    param = {
        'DEFAULT_STANDARD_TICK': AIParamValue(AI.DEFAULT_STANDARD_TICK, AI.DEFAULT_MIN, AI.DEFAULT_MAX),
        'H24:0,H4:3,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': AI().get_random_order(),
        'H24:0,H4:0,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': AI().get_random_order(),
        'H24:-3,H4:3,LOW:-7,HIGH:-22,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': AI().get_random_order(),
        'H24:3,H4:3,LOW:-4,HIGH:-19,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': AI().get_random_order(),
    }
    return param

#Test initial data
print '~~~~~~~~~~~~~TEST DATA~~~~~~~~~~~~~'
ai1 = AI.create_child(gen_random_ai_parame(), 1)
ai1.profit = 100 * 10000
print ai1

ai2 = AI.create_child(gen_random_ai_parame(), 1)
ai2.profit = 50 * 10000
print ai2

ai3 = AI.create_child(gen_random_ai_parame(), 1)
ai3.profit = -100 * 10000
print ai3

ai4 = AI.create_child(gen_random_ai_parame(), 1)
ai4.profit = -500 * 10000
print ai4

ai_group = [ai1, ai2, ai3, ai4]

#Generation of next-generation AI
print '~~~~~~~~~~~~~RESULT~~~~~~~~~~~~~'
ai_group_next_generation = AI.cross_over(20, ai_group)

for ai in ai_group_next_generation:
    print ai


>>python genetic_mixin.py
~~~~~~~~~~~~~TEST DATA~~~~~~~~~~~~~
1st generation AI PARAM:{'H24:-3,H4:3,LOW:-7,HIGH:-22,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:28,STOP-LIMIT:83,MIN:15,MAX:120, 'H24:3,H4:3,LOW:-4,HIGH:-19,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:32,STOP-LIMIT:120,MIN:15,MAX:120, 'DEFAULT_STANDARD_TICK': VALUE:30,MIN:15,MAX:120, 'H24:0,H4:3,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:99,STOP-LIMIT:25,MIN:15,MAX:120, 'H24:0,H4:0,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Wait,LIMIT:30,STOP-LIMIT:20,MIN:15,MAX:120}
1st generation AI PARAM:{'H24:-3,H4:3,LOW:-7,HIGH:-22,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:94,STOP-LIMIT:112,MIN:15,MAX:120, 'H24:3,H4:3,LOW:-4,HIGH:-19,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Wait,LIMIT:24,STOP-LIMIT:101,MIN:15,MAX:120, 'DEFAULT_STANDARD_TICK': VALUE:30,MIN:15,MAX:120, 'H24:0,H4:3,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:66,STOP-LIMIT:79,MIN:15,MAX:120, 'H24:0,H4:0,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:78,STOP-LIMIT:81,MIN:15,MAX:120}
1st generation AI PARAM:{'H24:-3,H4:3,LOW:-7,HIGH:-22,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Wait,LIMIT:94,STOP-LIMIT:35,MIN:15,MAX:120, 'H24:3,H4:3,LOW:-4,HIGH:-19,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:103,STOP-LIMIT:112,MIN:15,MAX:120, 'DEFAULT_STANDARD_TICK': VALUE:30,MIN:15,MAX:120, 'H24:0,H4:3,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:18,STOP-LIMIT:38,MIN:15,MAX:120, 'H24:0,H4:0,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:20,STOP-LIMIT:89,MIN:15,MAX:120}
1st generation AI PARAM:{'H24:-3,H4:3,LOW:-7,HIGH:-22,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Wait,LIMIT:42,STOP-LIMIT:20,MIN:15,MAX:120, 'H24:3,H4:3,LOW:-4,HIGH:-19,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:46,STOP-LIMIT:76,MIN:15,MAX:120, 'DEFAULT_STANDARD_TICK': VALUE:30,MIN:15,MAX:120, 'H24:0,H4:3,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:104,STOP-LIMIT:43,MIN:15,MAX:120, 'H24:0,H4:0,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:40,STOP-LIMIT:109,MIN:15,MAX:120}
~~~~~~~~~~~~~RESULT~~~~~~~~~~~~~
2nd generation AI PARAM:{'H24:-3,H4:3,LOW:-7,HIGH:-22,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:30,STOP-LIMIT:83,MIN:15,MAX:120, 'H24:3,H4:3,LOW:-4,HIGH:-19,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:55,STOP-LIMIT:96,MIN:15,MAX:120, 'DEFAULT_STANDARD_TICK': VALUE:30,MIN:15,MAX:120, 'H24:0,H4:3,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:83,STOP-LIMIT:31,MIN:15,MAX:120, 'H24:0,H4:0,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:28,STOP-LIMIT:20,MIN:15,MAX:120}
2nd generation AI PARAM:{'H24:-3,H4:3,LOW:-7,HIGH:-22,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:30,STOP-LIMIT:83,MIN:15,MAX:120, 'H24:3,H4:3,LOW:-4,HIGH:-19,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:55,STOP-LIMIT:96,MIN:15,MAX:120, 'DEFAULT_STANDARD_TICK': VALUE:30,MIN:15,MAX:120, 'H24:0,H4:3,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:83,STOP-LIMIT:31,MIN:15,MAX:120, 'H24:0,H4:0,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:28,STOP-LIMIT:20,MIN:15,MAX:120}
2nd generation AI PARAM:{'H24:-3,H4:3,LOW:-7,HIGH:-22,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Wait,LIMIT:92,STOP-LIMIT:48,MIN:15,MAX:120, 'H24:3,H4:3,LOW:-4,HIGH:-19,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:111,STOP-LIMIT:113,MIN:15,MAX:120, 'DEFAULT_STANDARD_TICK': VALUE:30,MIN:15,MAX:120, 'H24:0,H4:3,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:15,STOP-LIMIT:38,MIN:15,MAX:120, 'H24:0,H4:0,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:15,STOP-LIMIT:89,MIN:15,MAX:120}
2nd generation AI PARAM:{'H24:-3,H4:3,LOW:-7,HIGH:-22,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:94,STOP-LIMIT:99,MIN:15,MAX:120, 'H24:3,H4:3,LOW:-4,HIGH:-19,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:15,STOP-LIMIT:120,MIN:15,MAX:120, 'DEFAULT_STANDARD_TICK': VALUE:30,MIN:15,MAX:120, 'H24:0,H4:3,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:98,STOP-LIMIT:79,MIN:15,MAX:120, 'H24:0,H4:0,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:86,STOP-LIMIT:81,MIN:15,MAX:120}
2nd generation AI PARAM:{'H24:-3,H4:3,LOW:-7,HIGH:-22,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:30,STOP-LIMIT:83,MIN:15,MAX:120, 'H24:3,H4:3,LOW:-4,HIGH:-19,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:55,STOP-LIMIT:96,MIN:15,MAX:120, 'DEFAULT_STANDARD_TICK': VALUE:30,MIN:15,MAX:120, 'H24:0,H4:3,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:83,STOP-LIMIT:31,MIN:15,MAX:120, 'H24:0,H4:0,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:28,STOP-LIMIT:20,MIN:15,MAX:120}
2nd generation AI PARAM:{'H24:-3,H4:3,LOW:-7,HIGH:-22,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:94,STOP-LIMIT:99,MIN:15,MAX:120, 'H24:3,H4:3,LOW:-4,HIGH:-19,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:15,STOP-LIMIT:120,MIN:15,MAX:120, 'DEFAULT_STANDARD_TICK': VALUE:30,MIN:15,MAX:120, 'H24:0,H4:3,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:98,STOP-LIMIT:79,MIN:15,MAX:120, 'H24:0,H4:0,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:86,STOP-LIMIT:81,MIN:15,MAX:120}
2nd generation AI PARAM:{'H24:-3,H4:3,LOW:-7,HIGH:-22,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:94,STOP-LIMIT:99,MIN:15,MAX:120, 'H24:3,H4:3,LOW:-4,HIGH:-19,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:15,STOP-LIMIT:120,MIN:15,MAX:120, 'DEFAULT_STANDARD_TICK': VALUE:30,MIN:15,MAX:120, 'H24:0,H4:3,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:98,STOP-LIMIT:79,MIN:15,MAX:120, 'H24:0,H4:0,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:86,STOP-LIMIT:81,MIN:15,MAX:120}
2nd generation AI PARAM:{'H24:-3,H4:3,LOW:-7,HIGH:-22,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:30,STOP-LIMIT:83,MIN:15,MAX:120, 'H24:3,H4:3,LOW:-4,HIGH:-19,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:55,STOP-LIMIT:96,MIN:15,MAX:120, 'DEFAULT_STANDARD_TICK': VALUE:30,MIN:15,MAX:120, 'H24:0,H4:3,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:83,STOP-LIMIT:31,MIN:15,MAX:120, 'H24:0,H4:0,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:28,STOP-LIMIT:20,MIN:15,MAX:120}
2nd generation AI PARAM:{'H24:-3,H4:3,LOW:-7,HIGH:-22,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:30,STOP-LIMIT:83,MIN:15,MAX:120, 'H24:3,H4:3,LOW:-4,HIGH:-19,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:55,STOP-LIMIT:96,MIN:15,MAX:120, 'DEFAULT_STANDARD_TICK': VALUE:30,MIN:15,MAX:120, 'H24:0,H4:3,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:83,STOP-LIMIT:31,MIN:15,MAX:120, 'H24:0,H4:0,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:28,STOP-LIMIT:20,MIN:15,MAX:120}
2nd generation AI PARAM:{'H24:-3,H4:3,LOW:-7,HIGH:-22,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:94,STOP-LIMIT:99,MIN:15,MAX:120, 'H24:3,H4:3,LOW:-4,HIGH:-19,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:15,STOP-LIMIT:120,MIN:15,MAX:120, 'DEFAULT_STANDARD_TICK': VALUE:30,MIN:15,MAX:120, 'H24:0,H4:3,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:98,STOP-LIMIT:79,MIN:15,MAX:120, 'H24:0,H4:0,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:86,STOP-LIMIT:81,MIN:15,MAX:120}
2nd generation AI PARAM:{'H24:-3,H4:3,LOW:-7,HIGH:-22,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:94,STOP-LIMIT:99,MIN:15,MAX:120, 'H24:3,H4:3,LOW:-4,HIGH:-19,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:15,STOP-LIMIT:120,MIN:15,MAX:120, 'DEFAULT_STANDARD_TICK': VALUE:30,MIN:15,MAX:120, 'H24:0,H4:3,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:98,STOP-LIMIT:79,MIN:15,MAX:120, 'H24:0,H4:0,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:86,STOP-LIMIT:81,MIN:15,MAX:120}
2nd generation AI PARAM:{'H24:-3,H4:3,LOW:-7,HIGH:-22,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:30,STOP-LIMIT:83,MIN:15,MAX:120, 'H24:3,H4:3,LOW:-4,HIGH:-19,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:55,STOP-LIMIT:96,MIN:15,MAX:120, 'DEFAULT_STANDARD_TICK': VALUE:30,MIN:15,MAX:120, 'H24:0,H4:3,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:83,STOP-LIMIT:31,MIN:15,MAX:120, 'H24:0,H4:0,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:28,STOP-LIMIT:20,MIN:15,MAX:120}
2nd generation AI PARAM:{'H24:-3,H4:3,LOW:-7,HIGH:-22,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:30,STOP-LIMIT:83,MIN:15,MAX:120, 'H24:3,H4:3,LOW:-4,HIGH:-19,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:55,STOP-LIMIT:96,MIN:15,MAX:120, 'DEFAULT_STANDARD_TICK': VALUE:30,MIN:15,MAX:120, 'H24:0,H4:3,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:83,STOP-LIMIT:31,MIN:15,MAX:120, 'H24:0,H4:0,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:28,STOP-LIMIT:20,MIN:15,MAX:120}
2nd generation AI PARAM:{'H24:-3,H4:3,LOW:-7,HIGH:-22,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:30,STOP-LIMIT:83,MIN:15,MAX:120, 'H24:3,H4:3,LOW:-4,HIGH:-19,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:55,STOP-LIMIT:96,MIN:15,MAX:120, 'DEFAULT_STANDARD_TICK': VALUE:30,MIN:15,MAX:120, 'H24:0,H4:3,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:83,STOP-LIMIT:31,MIN:15,MAX:120, 'H24:0,H4:0,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:28,STOP-LIMIT:20,MIN:15,MAX:120}
2nd generation AI PARAM:{'H24:-3,H4:3,LOW:-7,HIGH:-22,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:94,STOP-LIMIT:99,MIN:15,MAX:120, 'H24:3,H4:3,LOW:-4,HIGH:-19,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:15,STOP-LIMIT:120,MIN:15,MAX:120, 'DEFAULT_STANDARD_TICK': VALUE:30,MIN:15,MAX:120, 'H24:0,H4:3,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:98,STOP-LIMIT:79,MIN:15,MAX:120, 'H24:0,H4:0,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:86,STOP-LIMIT:81,MIN:15,MAX:120}
2nd generation AI PARAM:{'H24:-3,H4:3,LOW:-7,HIGH:-22,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:30,STOP-LIMIT:83,MIN:15,MAX:120, 'H24:3,H4:3,LOW:-4,HIGH:-19,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:55,STOP-LIMIT:96,MIN:15,MAX:120, 'DEFAULT_STANDARD_TICK': VALUE:30,MIN:15,MAX:120, 'H24:0,H4:3,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:83,STOP-LIMIT:31,MIN:15,MAX:120, 'H24:0,H4:0,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:28,STOP-LIMIT:20,MIN:15,MAX:120}
2nd generation AI PARAM:{'H24:-3,H4:3,LOW:-7,HIGH:-22,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:30,STOP-LIMIT:83,MIN:15,MAX:120, 'H24:3,H4:3,LOW:-4,HIGH:-19,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:55,STOP-LIMIT:96,MIN:15,MAX:120, 'DEFAULT_STANDARD_TICK': VALUE:30,MIN:15,MAX:120, 'H24:0,H4:3,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:83,STOP-LIMIT:31,MIN:15,MAX:120, 'H24:0,H4:0,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:28,STOP-LIMIT:20,MIN:15,MAX:120}
2nd generation AI PARAM:{'H24:-3,H4:3,LOW:-7,HIGH:-22,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Wait,LIMIT:92,STOP-LIMIT:48,MIN:15,MAX:120, 'H24:3,H4:3,LOW:-4,HIGH:-19,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:111,STOP-LIMIT:113,MIN:15,MAX:120, 'DEFAULT_STANDARD_TICK': VALUE:30,MIN:15,MAX:120, 'H24:0,H4:3,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:15,STOP-LIMIT:38,MIN:15,MAX:120, 'H24:0,H4:0,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:15,STOP-LIMIT:89,MIN:15,MAX:120}
2nd generation AI PARAM:{'H24:-3,H4:3,LOW:-7,HIGH:-22,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:94,STOP-LIMIT:99,MIN:15,MAX:120, 'H24:3,H4:3,LOW:-4,HIGH:-19,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:15,STOP-LIMIT:120,MIN:15,MAX:120, 'DEFAULT_STANDARD_TICK': VALUE:30,MIN:15,MAX:120, 'H24:0,H4:3,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:98,STOP-LIMIT:79,MIN:15,MAX:120, 'H24:0,H4:0,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:86,STOP-LIMIT:81,MIN:15,MAX:120}
2nd generation AI PARAM:{'H24:-3,H4:3,LOW:-7,HIGH:-22,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:30,STOP-LIMIT:83,MIN:15,MAX:120, 'H24:3,H4:3,LOW:-4,HIGH:-19,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:55,STOP-LIMIT:96,MIN:15,MAX:120, 'DEFAULT_STANDARD_TICK': VALUE:30,MIN:15,MAX:120, 'H24:0,H4:3,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Buy,LIMIT:83,STOP-LIMIT:31,MIN:15,MAX:120, 'H24:0,H4:0,LOW:2,HIGH:-12,LOW_PASSED_DAY:8,HIGH_PASSED_DAY:2': ORDER-TYPE:OrderType.Sell,LIMIT:28,STOP-LIMIT:20,MIN:15,MAX:120}

The results are getting more complicated. The test will be tougher with your eyes, so let's write the test code properly.

Column: AI that makes a profit even if it is buggy

What if the trading part implementation has a bug? If you set the score of the genetic algorithm to trading revenue, the parameters will be optimized so that you can buy and sell with bugs and earn profits with bugs. In fact, AI that makes a profit even if there is a bug. At first, I wasn't quite convinced. And when I fixed the bug, the trading result changed, so I couldn't stop the production system and I was in trouble.

in conclusion

In this post, we have implemented the definition of complex trading AI and the evolution of genetic algorithms. Implementation of automatic trading, implementation of Oanda API call, saving of AI, recording of calculation results for each generation, etc. I haven't written it yet, so I'd like to introduce it in Part 3.

Part 3 I wrote

Forex automatic trading with genetic algorithm Part 3 Actual trading with Oanda API

Related article

FX automatic trading system made with python and genetic algorithm part 1 Forex automatic trading with genetic algorithm Part 2 Evolving trading AI implementation Forex automatic trading with genetic algorithm Part 3 Actual trading with Oanda API

Recommended Posts

Forex automatic trading with genetic algorithm Part 2 Evolving trading AI implementation
Forex automatic trading with genetic algorithm Part 3 Actual trading with Oanda API
FX automatic trading system made with python and genetic algorithm Part 1
Find the optimal value of a function with a genetic algorithm (Part 2)
Implementation of Dijkstra's algorithm with python
[Easy] AI automatic recognition with a webcam!