Exemple #1
0
def generate(name: str) -> None:
    path = '{}'.format(name)

    # validate that doesn't create if current directory is inside a Jesse project
    ls = os.listdir('.')
    is_jesse_project = 'strategies' in ls and 'config.py' in ls and 'storage' in ls and 'routes.py' in ls
    if is_jesse_project:
        print(
            jh.color(
                'You are already inside a Jesse project. Check your working directory.'
                .format(name), 'red'))
        return

    # validation for name duplication
    exists = os.path.isdir(path)
    if exists:
        print(jh.color('Project "{}" already exists.'.format(name), 'red'))
        return

    # generate from ExampleStrategy
    dirname, filename = os.path.split(os.path.abspath(__file__))

    shutil.copytree('{}/project_template'.format(dirname), path)

    # output the location of generated strategy directory
    print(
        jh.color(
            'Your project is created successfully. \nRun "cd {}" to begin algo-trading!'
            .format(path, name), 'green'))

    # reminder for subscribe and forum
    print(
        jh.color(
            "\nDon't forget to subscribe for future updates at https://Jesse.Trade and make sure to check out the forum for support at https://forum.jesse.trade",
            "blue"))
Exemple #2
0
def generate(name: str) -> None:
    """

    :param name:
    :return:
    """
    path = f'strategies/{name}'

    # validation for name duplication
    exists = os.path.isdir(path)
    if exists:
        print(jh.color(f'Strategy "{name}" already exists.', 'red'))
        return

    # generate from ExampleStrategy
    dirname, filename = os.path.split(os.path.abspath(__file__))

    shutil.copytree(f'{dirname}/ExampleStrategy', path)

    with open(f"{path}/__init__.py") as fin:
        data = fin.read()
        data = data.replace('ExampleStrategy', name)
    with open(f"{path}/__init__.py", "wt") as fin:
        fin.write(data)
    # output the location of generated strategy directory
    print(jh.color(f'Strategy created at: {path}', 'green'))
Exemple #3
0
def generate(name):
    path = '{}'.format(name)

    # validate that doesn't create if current directory is inside a Jesse project
    ls = os.listdir('.')
    is_jesse_project = 'strategies' in ls and 'config.py' in ls and 'storage' in ls and 'routes.py' in ls
    if is_jesse_project:
        print(
            jh.color(
                'You are already inside a Jesse project. Check your working directory.'
                .format(name), 'red'))
        return

    # validation for name duplication
    exists = os.path.isdir(path)
    if exists:
        print(jh.color('Project "{}" already exists.'.format(name), 'red'))
        return

    # generate from ExampleStrategy
    dirname, filename = os.path.split(os.path.abspath(__file__))

    shutil.copytree('{}/project_template'.format(dirname), path)

    # output the location of generated strategy directory
    print(
        jh.color(
            'Your project is created successfully. \nRun "cd {}" to begin algo-trading!'
            .format(path, name), 'green'))
Exemple #4
0
def generate(name: str) -> None:
    """

    :param name:
    :return:
    """
    path = 'strategies/{}'.format(name)

    # validation for name duplication
    exists = os.path.isdir(path)
    if exists:
        print(jh.color('Strategy "{}" already exists.'.format(name), 'red'))
        return

    # generate from ExampleStrategy
    dirname, filename = os.path.split(os.path.abspath(__file__))

    shutil.copytree('{}/ExampleStrategy'.format(dirname), path)

    # replace 'ExampleStrategy' with the name of the new strategy
    fin = open("{}/__init__.py".format(path), "rt")
    data = fin.read()
    data = data.replace('ExampleStrategy', name)
    fin.close()
    fin = open("{}/__init__.py".format(path), "wt")
    fin.write(data)
    fin.close()

    # output the location of generated strategy directory
    print(jh.color('Strategy created at: {}'.format(path), 'green'))
Exemple #5
0
def init():
    from pydoc import locate
    import os
    import sys
    import jesse.helpers as jh

    # Python version validation.
    if jh.python_version() < 3.6:
        print(
            jh.color(
                'Jesse has not beed tested with your Python version ({}), hence it may not work properly. Consider upgrading to >= 3.7'.format(
                    jh.python_version()),
                'red'
            )
        )

    # fix directory issue
    sys.path.insert(0, os.getcwd())

    ls = os.listdir('.')
    is_jesse_project = 'strategies' in ls and 'config.py' in ls and 'storage' in ls and 'routes.py' in ls

    if not is_jesse_project:
        print(
            jh.color(
                'Invalid directory. To use Jesse inside notebooks, create notebooks inside the root of a Jesse project.',
                'red'
            )
        )

    if is_jesse_project:
        local_config = locate('config.config')
        from jesse.config import set_config
        set_config(local_config)
Exemple #6
0
def candles():
    """

    :return:
    """
    array = []
    candle_keys = []

    # add routes
    for e in router.routes:
        if e.strategy is None:
            return

        candle_keys.append({
            'exchange': e.exchange,
            'symbol': e.symbol,
            'timeframe': e.timeframe
        })

    # add extra_routes
    for e in router.extra_candles:
        candle_keys.append({
            'exchange': e[0],
            'symbol': e[1],
            'timeframe': e[2]
        })

    # headers
    array.append([
        'exchange-symbol-timeframe', 'timestamp', 'open', 'close', 'high',
        'low'
    ])

    for k in candle_keys:
        try:
            current_candle = store.candles.get_current_candle(
                k['exchange'], k['symbol'], k['timeframe'])
            green = is_bullish(current_candle)
            bold = k['symbol'] in config['app']['trading_symbols'] and k[
                'timeframe'] in config['app']['trading_timeframes']
            key = jh.key(k['exchange'], k['symbol'], k['timeframe'])
            array.append([
                jh.style(key, 'underline' if bold else None),
                jh.color(jh.timestamp_to_time(current_candle[0]),
                         'green' if green else 'red'),
                jh.color(str(current_candle[1]), 'green' if green else 'red'),
                jh.color(str(current_candle[2]), 'green' if green else 'red'),
                jh.color(str(current_candle[3]), 'green' if green else 'red'),
                jh.color(str(current_candle[4]), 'green' if green else 'red'),
            ])
        except IndexError:
            return
        except Exception:
            raise

    return array
Exemple #7
0
def orders(
) -> List[Union[List[str], List[Union[CharField, str, FloatField]]]]:
    array = []

    # headers
    array.append([
        'symbol', 'side', 'type', 'qty', 'price', 'flag', 'status',
        'created_at'
    ])

    route_orders = []
    for r in router.routes:
        r_orders = store.orders.get_orders(r.exchange, r.symbol)
        for o in r_orders:
            route_orders.append(o)

    if not len(route_orders):
        return None

    route_orders.sort(key=lambda x: x.created_at, reverse=False)

    for o in route_orders[::-1][0:5]:
        array.append([
            o.symbol if o.is_active else jh.color(o.symbol, 'gray'),
            jh.color(o.side, 'red') if o.side == 'sell' else jh.color(
                o.side, 'green'),
            o.type if o.is_active else jh.color(o.type, 'gray'),
            o.qty if o.is_active else jh.color(str(o.qty), 'gray'),
            o.price if o.is_active else jh.color(str(o.price), 'gray'),
            o.flag if o.is_active else jh.color(o.flag, 'gray'),
            o.status if o.is_active else jh.color(o.status, 'gray'),
            jh.timestamp_to_time(o.created_at)[:19] if o.is_active else
            jh.color(jh.timestamp_to_time(o.created_at)[:19], 'gray'),
        ])
    return array
Exemple #8
0
def run(dna=False):
    """

    :param dna:
    """
    # # # # # # # # # # # # # # # # # # # # # # # #
    # trading routes
    # # # # # # # # # # # # # # # # # # # # # # # #
    arr = []
    if not dna:
        print(
            jh.color('{}{}{}'.format('#' * 25, ' Trading Routes ', '#' * 25),
                     'blue'))
        arr.append(('exchange', 'symbol', 'timeframe', 'strategy name', 'DNA'))
    else:
        print(jh.color('Translated DNAs into hyper-parameters:', 'blue'))

    translated_DNAs_count = 0
    for i, r in enumerate(router.routes):
        if dna and r.dna:
            translated_DNAs_count += 1
            StrategyClass = jh.get_strategy_class(r.strategy_name)
            hyper_parameters = jh.dna_to_hp(StrategyClass.hyper_parameters(),
                                            r.dna)
            table.key_value(hyper_parameters.items(),
                            r.strategy_name,
                            uppercase_title=False)
            print('\n')
        else:
            arr.append(
                [r.exchange, r.symbol, r.timeframe, r.strategy_name, r.dna])
    if not dna:
        table.multi_value(arr)
        print('\n')
    else:
        if not translated_DNAs_count:
            print('No DNA string found.')

    # # # # # # # # # # # # # # # # # # # # # # # #
    # extra_candles
    # # # # # # # # # # # # # # # # # # # # # # # #
    if not dna:
        print(
            jh.color('{}{}{}'.format('#' * 25, ' Extra Candles ', '#' * 25),
                     'blue'))
        arr = [('exchange', 'symbol', 'timeframe')]

        for i, r in enumerate(router.extra_candles):
            arr.append([r[0], r[1], r[2]])

        table.multi_value(arr)
        print('\n')
Exemple #9
0
def run(start_date: str,
        finish_date: str,
        candles=None,
        chart=False,
        tradingview=False):
    # clear the screen
    if not jh.should_execute_silently():
        click.clear()

    # validate routes
    validate_routes(router)

    # initiate candle store
    store.candles.init_storage(5000)

    # load historical candles
    if candles is None:
        print('loading candles...')
        candles = _load_candles(start_date, finish_date)
        click.clear()

    if not jh.should_execute_silently():
        # print candles table
        key = '{}-{}'.format(config['app']['trading_exchanges'][0],
                             config['app']['trading_symbols'][0])
        table.key_value(stats.candles(candles[key]['candles']),
                        'candles',
                        alignments=('left', 'right'))
        print('\n')

        # print routes table
        table.multi_value(stats.routes(router.routes))
        print('\n')

        # print guidance for debugging candles
        if jh.is_debuggable('trading_candles') or jh.is_debuggable(
                'shorter_period_candles'):
            print(
                '     Symbol  |     timestamp    | open | close | high | low | volume'
            )

    # run backtest simulation
    simulator(candles)

    if not jh.should_execute_silently():
        # print trades statistics
        if store.completed_trades.count > 0:
            print('\n')
            table.key_value(report.portfolio_metrics(),
                            'Metrics',
                            alignments=('left', 'right'))
            print('\n')

            # save logs
            store_logs(tradingview)

            if chart:
                charts.portfolio_vs_asset_returns()
        else:
            print(jh.color('No trades were made.', 'yellow'))
Exemple #10
0
 def async_save():
     Candle.insert(**d).on_conflict_ignore().execute()
     print(
         jh.color(
             'candle: {}-{}-{}: {}'.format(
                 jh.timestamp_to_time(d['timestamp']), exchange, symbol,
                 candle), 'blue'))
Exemple #11
0
 def async_save():
     Trade.insert(**d).on_conflict_ignore().execute()
     print(
         jh.color(
             'trade: {}-{}-{}: {}'.format(
                 jh.timestamp_to_time(d['timestamp']), exchange, symbol,
                 trade), 'green'))
Exemple #12
0
 def async_save():
     Ticker.insert(**d).on_conflict_ignore().execute()
     print(
         jh.color('ticker: {}-{}-{}: {}'.format(
             jh.timestamp_to_time(d['timestamp']), exchange, symbol, ticker
         ), 'yellow')
     )
Exemple #13
0
 def async_save() -> None:
     Orderbook.insert(**d).on_conflict_ignore().execute()
     print(
         jh.color(
             f'orderbook: {jh.timestamp_to_time(d["timestamp"])}-{exchange}-{symbol}: [{orderbook[0][0][0]}, {orderbook[0][0][1]}], [{orderbook[1][0][0]}, {orderbook[1][0][1]}]',
             'magenta'
         )
     )
Exemple #14
0
 def async_save() -> None:
     Candle.insert(**d).on_conflict_ignore().execute()
     print(
         jh.color(
             f"candle: {jh.timestamp_to_time(d['timestamp'])}-{exchange}-{symbol}: {candle}",
             'blue'
         )
     )
Exemple #15
0
 def async_save() -> None:
     Trade.insert(**d).on_conflict_ignore().execute()
     print(
         jh.color(
             f'trade: {jh.timestamp_to_time(d["timestamp"])}-{exchange}-{symbol}: {trade}',
             'green'
         )
     )
Exemple #16
0
        def handle_thread_exception(args):
            """

            :param args:
            :return:
            """
            if args.exc_type == SystemExit:
                return

            # handle Breaking exceptions
            if args.exc_type in [
                    exceptions.ConfigException, exceptions.RouteNotFound,
                    exceptions.InvalidRoutes,
                    exceptions.CandleNotFoundInDatabase
            ]:
                click.clear()
                print('=' * 30 + ' EXCEPTION TRACEBACK:')
                traceback.print_tb(args.exc_traceback, file=sys.stdout)
                print("=" * 73)
                print(
                    '\n', jh.color('Uncaught Exception:', 'red'),
                    jh.color(
                        '{}: {}'.format(args.exc_type.__name__,
                                        args.exc_value), 'yellow'))
                return

            # send notifications if it's a live session
            if jh.is_live():
                jesse_logger.error('{}: {}'.format(args.exc_type.__name__,
                                                   args.exc_value))

            if jh.is_live() or jh.is_collecting_data():
                logging.error("Uncaught Exception:",
                              exc_info=(args.exc_type, args.exc_value,
                                        args.exc_traceback))
            else:
                print('=' * 30 + ' EXCEPTION TRACEBACK:')
                traceback.print_tb(args.exc_traceback, file=sys.stdout)
                print("=" * 73)
                print(
                    '\n', jh.color('Uncaught Exception:', 'red'),
                    jh.color(
                        '{}: {}'.format(args.exc_type.__name__,
                                        args.exc_value), 'yellow'))

            if jh.is_paper_trading():
                print(
                    jh.color(
                        'An uncaught exception was raised. Check the log file at:\n{}'
                        .format('storage/logs/paper-trade.txt'), 'red'))
            elif jh.is_livetrading():
                print(
                    jh.color(
                        'An uncaught exception was raised. Check the log file at:\n{}'
                        .format('storage/logs/live-trade.txt'), 'red'))
            elif jh.is_collecting_data():
                print(
                    jh.color(
                        'An uncaught exception was raised. Check the log file at:\n{}'
                        .format('storage/logs/collect.txt'), 'red'))
Exemple #17
0
    def handle_exception(exc_type, exc_value, exc_traceback) -> None:
        if issubclass(exc_type, KeyboardInterrupt):
            sys.excepthook(exc_type, exc_value, exc_traceback)
            return

        # handle Breaking exceptions
        if exc_type in [
            exceptions.InvalidConfig, exceptions.RouteNotFound, exceptions.InvalidRoutes,
            exceptions.CandleNotFoundInDatabase
        ]:
            click.clear()
            print(f"{'=' * 30} EXCEPTION TRACEBACK:")
            traceback.print_tb(exc_traceback, file=sys.stdout)
            print("=" * 73)
            print(
                '\n',
                jh.color('Uncaught Exception:', 'red'),
                jh.color(f'{exc_type.__name__}: {exc_value}', 'yellow')
            )
            return

        # send notifications if it's a live session
        if jh.is_live():
            jesse_logger.error(
                f'{exc_type.__name__}: {exc_value}'
            )

        if jh.is_live() or jh.is_collecting_data():
            logging.error("Uncaught Exception:", exc_info=(exc_type, exc_value, exc_traceback))
        else:
            print(f"{'=' * 30} EXCEPTION TRACEBACK:")
            traceback.print_tb(exc_traceback, file=sys.stdout)
            print("=" * 73)
            print(
                '\n',
                jh.color('Uncaught Exception:', 'red'),
                jh.color(f'{exc_type.__name__}: {exc_value}', 'yellow')
            )

        if jh.is_paper_trading():
            print(
                jh.color(
                    'An uncaught exception was raised. Check the log file at:\nstorage/logs/paper-trade.txt',
                    'red'
                )
            )
        elif jh.is_livetrading():
            print(
                jh.color(
                    'An uncaught exception was raised. Check the log file at:\nstorage/logs/live-trade.txt',
                    'red'
                )
            )
        elif jh.is_collecting_data():
            print(
                jh.color(
                    'An uncaught exception was raised. Check the log file at:\nstorage/logs/collect.txt',
                    'red'
                )
            )
Exemple #18
0
def positions():
    """

    :return:
    """
    array = []

    # headers
    array.append([
        'type', 'strategy', 'symbol', 'opened at', 'qty', 'entry',
        'current price', 'PNL (%)'
    ])

    for p in store.positions.storage:
        pos = store.positions.storage[p]

        if pos.pnl_percentage > 0:
            pnl_color = 'green'
        elif pos.pnl_percentage < 0:
            pnl_color = 'red'
        else:
            pnl_color = 'black'

        if pos.type == 'long':
            type_color = 'green'
        elif pos.type == 'short':
            type_color = 'red'
        else:
            type_color = 'black'

        array.append([
            jh.color(pos.type, type_color),
            pos.strategy.name,
            pos.symbol,
            '' if pos.is_close else '{} ago'.format(
                jh.readable_duration((jh.now() - pos.opened_at) / 1000, 3)),
            pos.qty if abs(pos.qty) > 0 else None,
            pos.entry_price,
            pos.current_price,
            '' if pos.is_close else '{} ({}%)'.format(
                jh.color(str(round(pos.pnl, 2)), pnl_color),
                jh.color(str(round(pos.pnl_percentage, 4)), pnl_color)),
        ])

    return array
Exemple #19
0
def validate_cwd() -> None:
    """
    make sure we're in a Jesse project
    """
    if not jh.is_jesse_project():
        print(
            jh.color(
                'Current directory is not a Jesse project. You must run commands from the root of a Jesse project. Read this page for more info: https://docs.jesse.trade/docs/getting-started/#create-a-new-jesse-project',
                'red'))
        os._exit(1)
Exemple #20
0
def validate_cwd() -> None:
    """
    make sure we're in a Jesse project
    """
    if not is_jesse_project:
        print(
            jh.color(
                'Current directory is not a Jesse project. You must run commands from the root of a Jesse project.',
                'red'))
        os._exit(1)
Exemple #21
0
def info(msg):
    from jesse.store import store

    store.logs.info.append({'time': jh.now(), 'message': msg})

    if (jh.is_backtesting() and jh.is_debugging()) or jh.is_collecting_data():
        print(jh.color('[{}]: {}'.format(jh.timestamp_to_time(jh.now()), msg), 'magenta'))

    if jh.is_live():
        msg = '[INFO | {}] '.format(jh.timestamp_to_time(jh.now())[:19]) + str(msg)
        import logging
        logging.info(msg)
Exemple #22
0
 def async_save():
     Orderbook.insert(**d).on_conflict_ignore().execute()
     print(
         jh.color(
             'orderbook: {}-{}-{}: [{}, {}], [{}, {}]'.format(
                 jh.timestamp_to_time(d['timestamp']), exchange, symbol,
                 # best ask
                 orderbook[0][0][0], orderbook[0][0][1],
                 # best bid
                 orderbook[1][0][0], orderbook[1][0][1]
             ),
             'magenta'
         )
     )
Exemple #23
0
def error(msg):
    from jesse.store import store

    if jh.is_live() and jh.get_config('env.notifications.events.errors', True):
        notify('ERROR:\n{}'.format(msg))
    if (jh.is_backtesting() and jh.is_debugging()) or jh.is_collecting_data():
        print(jh.color('[{}]: {}'.format(jh.timestamp_to_time(jh.now()), msg), 'red'))

    store.logs.errors.append({'time': jh.now(), 'message': msg})

    if jh.is_live():
        msg = '[ERROR | {}] '.format(jh.timestamp_to_time(jh.now())[:19]) + str(msg)
        import logging
        logging.error(msg)
Exemple #24
0
def positions(
) -> List[Union[List[str], List[Union[Union[str, int, None], Any]]]]:
    array = [[
        'type',
        'strategy',
        'symbol',
        'leverage',
        'opened at',
        'qty',
        'entry',
        'current price',
        'liq price',
        'PNL (%)',
    ]]

    for r in router.routes:
        pos = r.strategy.position

        if pos.pnl_percentage > 0:
            pnl_color = 'green'
        elif pos.pnl_percentage < 0:
            pnl_color = 'red'
        else:
            pnl_color = 'black'

        if pos.type == 'long':
            type_color = 'green'
        elif pos.type == 'short':
            type_color = 'red'
        else:
            type_color = 'black'

        array.append([
            jh.color(pos.type, type_color),
            pos.strategy.name,
            pos.symbol,
            pos.leverage,
            '' if pos.is_close else
            f'{jh.readable_duration((jh.now_to_timestamp() - pos.opened_at) / 1000, 3)} ago',
            pos.qty if abs(pos.qty) > 0 else None,
            pos.entry_price,
            pos.current_price,
            '' if
            (pos.liquidation_price is None or np.isnan(pos.liquidation_price)
             or pos.liquidation_price == 0) else pos.liquidation_price,
            '' if pos.is_close else
            f'{jh.color(str(round(pos.pnl, 2)), pnl_color)} ({jh.color(str(round(pos.pnl_percentage, 4)), pnl_color)}%)',
        ])
    return array
Exemple #25
0
def error(msg: str) -> None:
    msg = str(msg)
    from jesse.store import store

    if jh.is_live() and jh.get_config('env.notifications.events.errors', True):
        notify_urgently(f"ERROR at \"{jh.get_config('env.identifier')}\" account:\n{msg}")
        notify(f'ERROR:\n{msg}')
    if (jh.is_backtesting() and jh.is_debugging()) or jh.is_collecting_data():
        print(jh.color(f'[{jh.timestamp_to_time(jh.now_to_timestamp())}]: {msg}', 'red'))

    store.logs.errors.append({'time': jh.now_to_timestamp(), 'message': msg})

    if jh.is_live() or jh.is_optimizing():
        msg = f"[ERROR | {jh.timestamp_to_time(jh.now_to_timestamp())[:19]}] {msg}"
        logging.error(msg)
Exemple #26
0
def init() -> None:
    from pydoc import locate
    import os
    import sys

    # fix directory issue
    sys.path.insert(0, os.getcwd())

    ls = os.listdir('.')
    is_jesse_project = 'strategies' in ls and 'config.py' in ls and 'storage' in ls and 'routes.py' in ls

    if not is_jesse_project:
        print(
            jh.color(
                'Invalid directory. To use Jesse inside notebooks, create notebooks inside the root of a Jesse project.',
                'red'))

    if is_jesse_project:
        local_config = locate('config.config')
        from jesse.config import set_config
        set_config(local_config)
Exemple #27
0
def run(start_date: str,
        finish_date: str,
        candles: Dict[str, Dict[str, Union[str, np.ndarray]]] = None,
        chart: bool = False,
        tradingview: bool = False,
        full_reports: bool = False,
        csv: bool = False,
        json: bool = False) -> None:
    # clear the screen
    if not jh.should_execute_silently():
        click.clear()

    # validate routes
    validate_routes(router)

    # initiate candle store
    store.candles.init_storage(5000)

    # load historical candles
    if candles is None:
        print('loading candles...')
        candles = load_candles(start_date, finish_date)
        click.clear()

    if not jh.should_execute_silently():
        # print candles table
        key = '{}-{}'.format(config['app']['considering_candles'][0][0],
                             config['app']['considering_candles'][0][1])
        table.key_value(stats.candles(candles[key]['candles']),
                        'candles',
                        alignments=('left', 'right'))
        print('\n')

        # print routes table
        table.multi_value(stats.routes(router.routes))
        print('\n')

        # print guidance for debugging candles
        if jh.is_debuggable('trading_candles') or jh.is_debuggable(
                'shorter_period_candles'):
            print(
                '     Symbol  |     timestamp    | open | close | high | low | volume'
            )

    # run backtest simulation
    simulator(candles)

    if not jh.should_execute_silently():
        # print trades metrics
        if store.completed_trades.count > 0:

            change = []
            # calcualte market change
            for e in router.routes:
                if e.strategy is None:
                    return

                first = Candle.select(Candle.close).where(
                    Candle.timestamp == jh.date_to_timestamp(start_date),
                    Candle.exchange == e.exchange,
                    Candle.symbol == e.symbol).first()
                last = Candle.select(Candle.close).where(
                    Candle.timestamp == jh.date_to_timestamp(finish_date) -
                    60000, Candle.exchange == e.exchange,
                    Candle.symbol == e.symbol).first()

                change.append(
                    ((last.close - first.close) / first.close) * 100.0)

            data = report.portfolio_metrics()
            data.append(
                ['Market Change',
                 str(round(np.average(change), 2)) + "%"])
            print('\n')
            table.key_value(data, 'Metrics', alignments=('left', 'right'))
            print('\n')

            # save logs
            store_logs(json, tradingview, csv)

            if chart:
                charts.portfolio_vs_asset_returns()

            # QuantStats' report
            if full_reports:
                quantstats.quantstats_tearsheet()
        else:
            print(jh.color('No trades were made.', 'yellow'))
Exemple #28
0
def test_color():
    msg_text = 'msg'
    msg_color = 'black'
    assert jh.color(msg_text, msg_color) == '\x1b[30mmsg\x1b[0m'
Exemple #29
0
    def generate_initial_population(self) -> None:
        """
        generates the initial population
        """
        loop_length = int(self.population_size / self.cpu_cores)

        with click.progressbar(length=loop_length, label='Generating initial population...') as progressbar:
            for i in range(loop_length):
                people = []
                with Manager() as manager:
                    dna_bucket = manager.list([])
                    workers = []

                    def get_fitness(dna: str, dna_bucket: list) -> None:
                        try:
                            fitness_score, fitness_log_training, fitness_log_testing = self.fitness(dna)
                            dna_bucket.append((dna, fitness_score, fitness_log_training, fitness_log_testing))
                        except Exception as e:
                            proc = os.getpid()
                            logger.error(f'process failed - ID: {str(proc)}')
                            logger.error("".join(traceback.TracebackException.from_exception(e).format()))
                            raise e

                    try:
                        for _ in range(self.cpu_cores):
                            dna = ''.join(choices(self.charset, k=self.solution_len))
                            w = Process(target=get_fitness, args=(dna, dna_bucket))
                            w.start()
                            workers.append(w)

                        # join workers
                        for w in workers:
                            w.join()
                            if w.exitcode > 0:
                                logger.error(f'a process exited with exitcode: {str(w.exitcode)}')
                    except KeyboardInterrupt:
                        print(
                            jh.color('Terminating session...', 'red')
                        )

                        # terminate all workers
                        for w in workers:
                            w.terminate()

                        # shutdown the manager process manually since garbage collection cannot won't get to do it for us
                        manager.shutdown()

                        # now we can terminate the main session safely
                        jh.terminate_app()
                    except:
                        raise

                    for d in dna_bucket:
                        people.append({
                            'dna': d[0],
                            'fitness': d[1],
                            'training_log': d[2],
                            'testing_log': d[3]
                        })

                # update dashboard
                click.clear()
                progressbar.update(1)
                print('\n')

                table_items = [
                    ['Started at', jh.timestamp_to_arrow(self.start_time).humanize()],
                    ['Index', f'{len(self.population)}/{self.population_size}'],
                    ['errors/info', f'{len(store.logs.errors)}/{len(store.logs.info)}'],
                    ['Trading Route', f'{router.routes[0].exchange}, {router.routes[0].symbol}, {router.routes[0].timeframe}, {router.routes[0].strategy_name}'],
                    # TODO: add generated DNAs?
                    # ['-'*10, '-'*10],
                    # ['DNA', people[0]['dna']],
                    # ['fitness', round(people[0]['fitness'], 6)],
                    # ['training|testing logs', people[0]['log']],
                ]
                if jh.is_debugging():
                    table_items.insert(3, ['Population Size', self.population_size])
                    table_items.insert(3, ['Iterations', self.iterations])
                    table_items.insert(3, ['Solution Length', self.solution_len])
                    table_items.insert(3, ['-' * 10, '-' * 10])

                table.key_value(table_items, 'Optimize Mode', alignments=('left', 'right'))

                # errors
                if jh.is_debugging() and len(report.errors()):
                    print('\n')
                    table.key_value(report.errors(), 'Error Logs')

                for p in people:
                    self.population.append(p)

        # sort the population
        self.population = list(sorted(self.population, key=lambda x: x['fitness'], reverse=True))
Exemple #30
0
    def evolve(self) -> List[Any]:
        """
        the main method, that runs the evolutionary algorithm
        """
        # generate the population if starting
        if self.started_index == 0:
            self.generate_initial_population()
            if len(self.population) < 0.5 * self.population_size:
                raise ValueError('Too many errors: less then half of the planned population size could be generated.')

            # if even our best individual is too weak, then we better not continue
            if self.population[0]['fitness'] == 0.0001:
                print(jh.color('Cannot continue because no individual with the minimum fitness-score was found. '
                               'Your strategy seems to be flawed or maybe it requires modifications. ', 'yellow'))
                jh.terminate_app()

        loop_length = int(self.iterations / self.cpu_cores)

        i = self.started_index
        with click.progressbar(length=loop_length, label='Evolving...') as progressbar:
            while i < loop_length:
                with Manager() as manager:
                    people = manager.list([])
                    workers = []

                    def get_baby(people: List) -> None:
                        try:
                            # let's make a baby together LOL
                            baby = self.make_love()
                            # let's mutate baby's genes, who knows, maybe we create a x-man or something
                            baby = self.mutate(baby)
                            people.append(baby)
                        except Exception as e:
                            proc = os.getpid()
                            logger.error(f'process failed - ID: {str(proc)}')
                            logger.error("".join(traceback.TracebackException.from_exception(e).format()))
                            raise e

                    try:
                        for _ in range(self.cpu_cores):
                            w = Process(target=get_baby, args=[people])
                            w.start()
                            workers.append(w)

                        for w in workers:
                            w.join()
                            if w.exitcode > 0:
                                logger.error(f'a process exited with exitcode: {str(w.exitcode)}')
                    except KeyboardInterrupt:
                        print(
                            jh.color('Terminating session...', 'red')
                        )

                        # terminate all workers
                        for w in workers:
                            w.terminate()

                        # shutdown the manager process manually since garbage collection cannot won't get to do it for us
                        manager.shutdown()

                        # now we can terminate the main session safely
                        jh.terminate_app()
                    except:
                        raise

                    # update dashboard
                    click.clear()
                    progressbar.update(1)
                    print('\n')

                    table_items = [
                        ['Started At', jh.timestamp_to_arrow(self.start_time).humanize()],
                        ['Index/Total', f'{(i + 1) * self.cpu_cores}/{self.iterations}'],
                        ['errors/info', f'{len(store.logs.errors)}/{len(store.logs.info)}'],
                        ['Route', f'{router.routes[0].exchange}, {router.routes[0].symbol}, {router.routes[0].timeframe}, {router.routes[0].strategy_name}']
                    ]
                    if jh.is_debugging():
                        table_items.insert(
                            3,
                            ['Population Size, Solution Length',
                             f'{self.population_size}, {self.solution_len}']
                        )

                    table.key_value(table_items, 'info', alignments=('left', 'right'))

                    # errors
                    if jh.is_debugging() and len(report.errors()):
                        print('\n')
                        table.key_value(report.errors(), 'Error Logs')

                    print('\n')
                    print('Best DNA candidates:')
                    print('\n')

                    # print fittest individuals
                    if jh.is_debugging():
                        fittest_list = [['Rank', 'DNA', 'Fitness', 'Training log || Testing log'], ]
                    else:
                        fittest_list = [['Rank', 'DNA', 'Training log || Testing log'], ]
                    if self.population_size > 50:
                        number_of_ind_to_show = 15
                    elif self.population_size > 20:
                        number_of_ind_to_show = 10
                    elif self.population_size > 9:
                        number_of_ind_to_show = 9
                    else:
                        raise ValueError('self.population_size cannot be less than 10')

                    for j in range(number_of_ind_to_show):
                        log = f"win-rate: {self.population[j]['training_log']['win-rate']}%, total: {self.population[j]['training_log']['total']}, PNL: {self.population[j]['training_log']['PNL']}% || win-rate: {self.population[j]['testing_log']['win-rate']}%, total: {self.population[j]['testing_log']['total']}, PNL: {self.population[j]['testing_log']['PNL']}%"
                        if self.population[j]['testing_log']['PNL'] is not None and self.population[j]['training_log'][
                            'PNL'] > 0 and self.population[j]['testing_log'][
                            'PNL'] > 0:
                            log = jh.style(log, 'bold')
                        if jh.is_debugging():
                            fittest_list.append(
                                [
                                    j + 1,
                                    self.population[j]['dna'],
                                    self.population[j]['fitness'],
                                    log
                                ],
                            )
                        else:
                            fittest_list.append(
                                [
                                    j + 1,
                                    self.population[j]['dna'],
                                    log
                                ],
                            )

                    if jh.is_debugging():
                        table.multi_value(fittest_list, with_headers=True, alignments=('left', 'left', 'right', 'left'))
                    else:
                        table.multi_value(fittest_list, with_headers=True, alignments=('left', 'left', 'left'))

                    # one person has to die and be replaced with the newborn baby
                    for baby in people:
                        random_index = randint(1, len(self.population) - 1)  # never kill our best perforemr
                        try:
                            self.population[random_index] = baby
                        except IndexError:
                            print('=============')
                            print(f'self.population_size: {self.population_size}')
                            print(f'self.population length: {len(self.population)}')
                            jh.terminate_app()

                        self.population = list(sorted(self.population, key=lambda x: x['fitness'], reverse=True))

                        # reaching the fitness goal could also end the process
                        if baby['fitness'] >= self.fitness_goal:
                            progressbar.update(self.iterations - i)
                            print('\n')
                            print(f'fitness goal reached after iteration {i}')
                            return baby

                    # save progress after every n iterations
                    if i != 0 and int(i * self.cpu_cores) % 50 == 0:
                        self.save_progress(i)

                    # store a take_snapshot of the fittest individuals of the population
                    if i != 0 and i % int(100 / self.cpu_cores) == 0:
                        self.take_snapshot(i * self.cpu_cores)

                    i += 1

        print('\n\n')
        print(f'Finished {self.iterations} iterations.')
        return self.population