Exemple #1
0
def load_trades_from_db(db_url: str) -> pd.DataFrame:
    """
    Load trades from a DB (using dburl)
    :param db_url: Sqlite url (default format sqlite:///tradesv3.dry-run.sqlite)
    :return: Dataframe containing Trades
    """
    trades: pd.DataFrame = pd.DataFrame([], columns=BT_DATA_COLUMNS)
    persistence.init(db_url, clean_open_orders=False)
    columns = [
        "pair", "profit", "open_time", "close_time", "open_rate", "close_rate",
        "duration", "sell_reason", "max_rate", "min_rate"
    ]

    trades = pd.DataFrame([(
        t.pair,
        t.calc_profit(),
        t.open_date.replace(tzinfo=pytz.UTC),
        t.close_date.replace(tzinfo=pytz.UTC) if t.close_date else None,
        t.open_rate,
        t.close_rate,
        t.close_date.timestamp() -
        t.open_date.timestamp() if t.close_date else None,
        t.sell_reason,
        t.max_rate,
        t.min_rate,
    ) for t in Trade.query.all()],
                          columns=columns)

    return trades
Exemple #2
0
def test_init_create_session(default_conf, mocker):
    mocker.patch.dict('freqtrade.persistence._CONF', default_conf)

    # Check if init create a session
    init(default_conf)
    assert hasattr(Trade, 'session')
    assert 'Session' in type(Trade.session).__name__
def start_show_trades(args: Dict[str, Any]) -> None:
    """
    Show trades
    """
    from freqtrade.persistence import init, Trade
    import json
    config = setup_utils_configuration(args, RunMode.UTIL_NO_EXCHANGE)

    if 'db_url' not in config:
        raise OperationalException("--db-url is required for this command.")

    logger.info(f'Using DB: "{config["db_url"]}"')
    init(config['db_url'], clean_open_orders=False)
    tfilter = []

    if config.get('trade_ids'):
        tfilter.append(Trade.id.in_(config['trade_ids']))

    trades = Trade.get_trades(tfilter).all()
    logger.info(f"Printing {len(trades)} Trades: ")
    if config.get('print_json', False):
        print(json.dumps([trade.to_json() for trade in trades], indent=4))
    else:
        for trade in trades:
            print(trade)
def test_migrate_mid_state(mocker, default_conf, fee, caplog):
    """
    Test Database migration (starting with new pairformat)
    """
    caplog.set_level(logging.DEBUG)
    amount = 103.223
    create_table_old = """CREATE TABLE IF NOT EXISTS "trades" (
                                id INTEGER NOT NULL,
                                exchange VARCHAR NOT NULL,
                                pair VARCHAR NOT NULL,
                                is_open BOOLEAN NOT NULL,
                                fee_open FLOAT NOT NULL,
                                fee_close FLOAT NOT NULL,
                                open_rate FLOAT,
                                close_rate FLOAT,
                                close_profit FLOAT,
                                stake_amount FLOAT NOT NULL,
                                amount FLOAT,
                                open_date DATETIME NOT NULL,
                                close_date DATETIME,
                                open_order_id VARCHAR,
                                PRIMARY KEY (id),
                                CHECK (is_open IN (0, 1))
                                );"""
    insert_table_old = """INSERT INTO trades (exchange, pair, is_open, fee_open, fee_close,
                          open_rate, stake_amount, amount, open_date)
                          VALUES ('binance', 'ETC/BTC', 1, {fee}, {fee},
                          0.00258580, {stake}, {amount},
                          '2019-11-28 12:44:24.000000')
                          """.format(fee=fee.return_value,
                                     stake=default_conf.get("stake_amount"),
                                     amount=amount)
    engine = create_engine('sqlite://')
    mocker.patch('freqtrade.persistence.create_engine',
                 lambda *args, **kwargs: engine)

    # Create table using the old format
    engine.execute(create_table_old)
    engine.execute(insert_table_old)

    # Run init to test migration
    init(default_conf['db_url'], default_conf['dry_run'])

    assert len(Trade.query.filter(Trade.id == 1).all()) == 1
    trade = Trade.query.filter(Trade.id == 1).first()
    assert trade.fee_open == fee.return_value
    assert trade.fee_close == fee.return_value
    assert trade.open_rate_requested is None
    assert trade.close_rate_requested is None
    assert trade.is_open == 1
    assert trade.amount == amount
    assert trade.stake_amount == default_conf.get("stake_amount")
    assert trade.pair == "ETC/BTC"
    assert trade.exchange == "binance"
    assert trade.max_rate == 0.0
    assert trade.stop_loss == 0.0
    assert trade.initial_stop_loss == 0.0
    assert log_has("trying trades_bak0", caplog)
    assert log_has(
        "Running database migration - backup available as trades_bak0", caplog)
Exemple #5
0
def load_trades_from_db(db_url: str) -> pd.DataFrame:
    """
    Load trades from a DB (using dburl)
    :param db_url: Sqlite url (default format sqlite:///tradesv3.dry-run.sqlite)
    :return: Dataframe containing Trades
    """
    trades: pd.DataFrame = pd.DataFrame([], columns=BT_DATA_COLUMNS)
    persistence.init(db_url, clean_open_orders=False)

    columns = [
        "pair", "open_time", "close_time", "profit", "profitperc", "open_rate",
        "close_rate", "amount", "duration", "sell_reason", "fee_open",
        "fee_close", "open_rate_requested", "close_rate_requested",
        "stake_amount", "max_rate", "min_rate", "id", "exchange", "stop_loss",
        "initial_stop_loss", "strategy", "ticker_interval"
    ]

    trades = pd.DataFrame(
        [(t.pair, t.open_date.replace(tzinfo=timezone.utc),
          t.close_date.replace(tzinfo=timezone.utc) if t.close_date else None,
          t.calc_profit(), t.calc_profit_percent(), t.open_rate, t.close_rate,
          t.amount, (round(
              (t.close_date.timestamp() - t.open_date.timestamp()) /
              60, 2) if t.close_date else None), t.sell_reason, t.fee_open,
          t.fee_close, t.open_rate_requested, t.close_rate_requested,
          t.stake_amount, t.max_rate, t.min_rate, t.id, t.exchange,
          t.stop_loss, t.initial_stop_loss, t.strategy, t.ticker_interval)
         for t in Trade.get_trades().all()],
        columns=columns)

    return trades
Exemple #6
0
def test_init_dry_run_db(default_conf, mocker):
    default_conf.update({'dry_run_db': True})
    mocker.patch.dict('freqtrade.persistence._CONF', default_conf)

    # First, protect the existing 'tradesv3.dry_run.sqlite' (Do not delete user data)
    dry_run_db = 'tradesv3.dry_run.sqlite'
    dry_run_db_swp = dry_run_db + '.swp'

    if os.path.isfile(dry_run_db):
        os.rename(dry_run_db, dry_run_db_swp)

    # Check if the new tradesv3.dry_run.sqlite was created
    init(default_conf)
    assert os.path.isfile(dry_run_db) is True

    # Delete the file made for this unitest and rollback to the previous
    # tradesv3.dry_run.sqlite file

    # 1. Delete file from the test
    if os.path.isfile(dry_run_db):
        os.remove(dry_run_db)

    # 2. Rollback to the initial file
    if os.path.isfile(dry_run_db_swp):
        os.rename(dry_run_db_swp, dry_run_db)
def load_trades(args: Namespace, pair: str,
                timerange: TimeRange) -> pd.DataFrame:
    trades: pd.DataFrame = pd.DataFrame()
    if args.db_url:
        persistence.init(_CONF)
        columns = [
            "pair", "profit", "open_time", "close_time", "open_rate",
            "close_rate", "duration"
        ]

        for x in Trade.query.all():
            print("date: {}".format(x.open_date))

        trades = pd.DataFrame(
            [(t.pair, t.calc_profit(), t.open_date.replace(tzinfo=timeZone),
              t.close_date.replace(tzinfo=timeZone) if t.close_date else None,
              t.open_rate, t.close_rate, t.close_date.timestamp() -
              t.open_date.timestamp() if t.close_date else None)
             for t in Trade.query.filter(Trade.pair.is_(pair)).all()],
            columns=columns)

    elif args.exportfilename:

        file = Path(args.exportfilename)
        if file.exists():
            load_backtest_data(file)

        else:
            trades = pd.DataFrame([], columns=BT_DATA_COLUMNS)

    return trades
def test_init_custom_db_url(default_conf, mocker):
    # Update path to a value other than default, but still in-memory
    default_conf.update({'db_url': 'sqlite:///tmp/freqtrade2_test.sqlite'})
    create_engine_mock = mocker.patch('freqtrade.persistence.create_engine', MagicMock())

    init(default_conf['db_url'], default_conf['dry_run'])
    assert create_engine_mock.call_count == 1
    assert create_engine_mock.mock_calls[0][1][0] == 'sqlite:///tmp/freqtrade2_test.sqlite'
Exemple #9
0
    def __init__(self, config: Dict[str, Any]) -> None:
        """
        Init all variables and objects the bot needs to work
        :param config: configuration dict, you can use Configuration.get_config()
        to get the config dict.
        """

        logger.info('Starting freqtrade %s', __version__)

        # Init bot state
        self.state = State.STOPPED

        # Init objects
        self.config = config

        self._heartbeat_msg = 0

        self.heartbeat_interval = self.config.get('internals', {}).get(
            'heartbeat_interval', 60)

        self.strategy: IStrategy = StrategyResolver(self.config).strategy

        # Check config consistency here since strategies can set certain options
        validate_config_consistency(config)

        self.exchange = ExchangeResolver(self.config['exchange']['name'],
                                         self.config).exchange

        self.wallets = Wallets(self.config, self.exchange)
        self.dataprovider = DataProvider(self.config, self.exchange)

        # Attach Dataprovider to Strategy baseclass
        IStrategy.dp = self.dataprovider
        # Attach Wallets to Strategy baseclass
        IStrategy.wallets = self.wallets

        self.pairlists = PairListManager(self.exchange, self.config)

        # Initializing Edge only if enabled
        self.edge = Edge(self.config, self.exchange, self.strategy) if \
            self.config.get('edge', {}).get('enabled', False) else None

        self.active_pair_whitelist = self._refresh_whitelist()

        persistence.init(self.config.get('db_url', None),
                         clean_open_orders=self.config.get('dry_run', False))

        # Set initial bot state from config
        initial_state = self.config.get('initial_state')
        self.state = State[
            initial_state.upper()] if initial_state else State.STOPPED

        # RPC runs in separate threads, can start handling external commands just after
        # initialization, even before Freqtradebot has a chance to start its throttling,
        # so anything in the Freqtradebot instance should be ready (initialized), including
        # the initial state of the bot.
        # Keep this at the end of this initialization method.
        self.rpc: RPCManager = RPCManager(self)
def test_stoploss_reinitialization(default_conf, fee):
    init(default_conf['db_url'])
    trade = Trade(
        pair='ETH/BTC',
        stake_amount=0.001,
        fee_open=fee.return_value,
        open_date=arrow.utcnow().shift(hours=-2).datetime,
        amount=10,
        fee_close=fee.return_value,
        exchange='bittrex',
        open_rate=1,
        max_rate=1,
    )

    trade.adjust_stop_loss(trade.open_rate, 0.05, True)
    assert trade.stop_loss == 0.95
    assert trade.stop_loss_pct == -0.05
    assert trade.initial_stop_loss == 0.95
    assert trade.initial_stop_loss_pct == -0.05
    Trade.session.add(trade)

    # Lower stoploss
    Trade.stoploss_reinitialization(0.06)

    trades = Trade.get_open_trades()
    assert len(trades) == 1
    trade_adj = trades[0]
    assert trade_adj.stop_loss == 0.94
    assert trade_adj.stop_loss_pct == -0.06
    assert trade_adj.initial_stop_loss == 0.94
    assert trade_adj.initial_stop_loss_pct == -0.06

    # Raise stoploss
    Trade.stoploss_reinitialization(0.04)

    trades = Trade.get_open_trades()
    assert len(trades) == 1
    trade_adj = trades[0]
    assert trade_adj.stop_loss == 0.96
    assert trade_adj.stop_loss_pct == -0.04
    assert trade_adj.initial_stop_loss == 0.96
    assert trade_adj.initial_stop_loss_pct == -0.04

    # Trailing stoploss (move stoplos up a bit)
    trade.adjust_stop_loss(1.02, 0.04)
    assert trade_adj.stop_loss == 0.9792
    assert trade_adj.initial_stop_loss == 0.96

    Trade.stoploss_reinitialization(0.04)

    trades = Trade.get_open_trades()
    assert len(trades) == 1
    trade_adj = trades[0]
    # Stoploss should not change in this case.
    assert trade_adj.stop_loss == 0.9792
    assert trade_adj.stop_loss_pct == -0.04
    assert trade_adj.initial_stop_loss == 0.96
    assert trade_adj.initial_stop_loss_pct == -0.04
Exemple #11
0
def test_init_dryrun_db(default_conf, mocker):
    default_conf.update({'dry_run': True})
    default_conf.update({'db_url': constants.DEFAULT_DB_DRYRUN_URL})

    create_engine_mock = mocker.patch('freqtrade.persistence.create_engine', MagicMock())

    init(default_conf['db_url'], default_conf['dry_run'])
    assert create_engine_mock.call_count == 1
    assert create_engine_mock.mock_calls[0][1][0] == 'sqlite:///tradesv3.dryrun.sqlite'
Exemple #12
0
def test_init_prod_db(default_conf, mocker):
    default_conf.update({'dry_run': False})
    default_conf.update({'db_url': constants.DEFAULT_DB_PROD_URL})

    create_engine_mock = mocker.patch('freqtrade.persistence.create_engine',
                                      MagicMock())

    init(default_conf)
    assert create_engine_mock.call_count == 1
    assert create_engine_mock.mock_calls[0][1][
        0] == 'sqlite:///tradesv3.sqlite'
Exemple #13
0
def patch_freqtradebot(mocker, config) -> None:
    """
    This function patch _init_modules() to not call dependencies
    :param mocker: a Mocker object to apply patches
    :param config: Config to pass to the bot
    :return: None
    """
    mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock())
    persistence.init(config['db_url'])
    patch_exchange(mocker, None)
    mocker.patch('freqtrade.freqtradebot.RPCManager._init', MagicMock())
    mocker.patch('freqtrade.freqtradebot.RPCManager.send_msg', MagicMock())
Exemple #14
0
    def __init__(self, config: Dict[str, Any]) -> None:
        """
        Init all variables and objects the bot needs to work
        :param config: configuration dict, you can use Configuration.get_config()
        to get the config dict.
        """

        logger.info('Starting freqtrade %s', __version__)

        # Init bot state
        self.state = State.STOPPED

        # Init objects
        self.config = config

        self.strategy: IStrategy = StrategyResolver(self.config).strategy

        # Check config consistency here since strategies can set certain options
        validate_config_consistency(config)

        self.rpc: RPCManager = RPCManager(self)

        self.exchange = ExchangeResolver(self.config['exchange']['name'], self.config).exchange

        self.wallets = Wallets(self.config, self.exchange)
        self.dataprovider = DataProvider(self.config, self.exchange)

        # Attach Dataprovider to Strategy baseclass
        IStrategy.dp = self.dataprovider
        # Attach Wallets to Strategy baseclass
        IStrategy.wallets = self.wallets

        pairlistname = self.config.get('pairlist', {}).get('method', 'StaticPairList')
        self.pairlists = PairListResolver(pairlistname, self, self.config).pairlist

        # Initializing Edge only if enabled
        self.edge = Edge(self.config, self.exchange, self.strategy) if \
            self.config.get('edge', {}).get('enabled', False) else None

        self.active_pair_whitelist: List[str] = self.config['exchange']['pair_whitelist']

        persistence.init(self.config.get('db_url', None),
                         clean_open_orders=self.config.get('dry_run', False))

        # Stoploss on exchange does not make sense, therefore we need to disable that.
        if (self.dataprovider.runmode == RunMode.DRY_RUN and
           self.strategy.order_types.get('stoploss_on_exchange', False)):
            logger.info("Disabling stoploss_on_exchange during dry-run.")
            self.strategy.order_types['stoploss_on_exchange'] = False
            config['order_types']['stoploss_on_exchange'] = False
        # Set initial bot state from config
        initial_state = self.config.get('initial_state')
        self.state = State[initial_state.upper()] if initial_state else State.STOPPED
Exemple #15
0
def load_trades(args: Namespace, pair: str,
                timerange: TimeRange) -> pd.DataFrame:
    trades: pd.DataFrame = pd.DataFrame()
    if args.db_url:
        persistence.init(_CONF)
        columns = [
            "pair", "profit", "opents", "closets", "open_rate", "close_rate",
            "duration"
        ]

        for x in Trade.query.all():
            print("date: {}".format(x.open_date))

        trades = pd.DataFrame(
            [(t.pair, t.calc_profit(), t.open_date.replace(tzinfo=timeZone),
              t.close_date.replace(tzinfo=timeZone) if t.close_date else None,
              t.open_rate, t.close_rate, t.close_date.timestamp() -
              t.open_date.timestamp() if t.close_date else None)
             for t in Trade.query.filter(Trade.pair.is_(pair)).all()],
            columns=columns)

    elif args.exportfilename:
        file = Path(args.exportfilename)
        # must align with columns in backtest.py
        columns = [
            "pair", "profit", "opents", "closets", "index", "duration",
            "open_rate", "close_rate", "open_at_end", "sell_reason"
        ]
        if file.exists():
            with file.open() as f:
                data = json.load(f)
                trades = pd.DataFrame(data, columns=columns)
            trades = trades.loc[trades["pair"] == pair]
            if timerange:
                if timerange.starttype == 'date':
                    trades = trades.loc[trades["opents"] >= timerange.startts]
                if timerange.stoptype == 'date':
                    trades = trades.loc[trades["opents"] <= timerange.stopts]

            trades['opents'] = pd.to_datetime(trades['opents'],
                                              unit='s',
                                              utc=True,
                                              infer_datetime_format=True)
            trades['closets'] = pd.to_datetime(trades['closets'],
                                               unit='s',
                                               utc=True,
                                               infer_datetime_format=True)
        else:
            trades = pd.DataFrame([], columns=columns)

    return trades
Exemple #16
0
    def __init__(self, config: Dict[str, Any]) -> None:
        """
        Init all variables and objects the bot needs to work
        :param config: configuration dict, you can use Configuration.get_config()
        to get the config dict.
        """

        logger.info('Starting freqtrade %s', __version__)

        # Init bot state
        self.state = State.STOPPED

        # Init objects
        self.config = config

        self.strategy: IStrategy = StrategyResolver(self.config).strategy

        self.rpc: RPCManager = RPCManager(self)

        self.exchange = ExchangeResolver(self.config['exchange']['name'],
                                         self.config).exchange

        self.wallets = Wallets(self.config, self.exchange)
        self.dataprovider = DataProvider(self.config, self.exchange)

        # Attach Dataprovider to Strategy baseclass
        IStrategy.dp = self.dataprovider
        # Attach Wallets to Strategy baseclass
        IStrategy.wallets = self.wallets

        pairlistname = self.config.get('pairlist',
                                       {}).get('method', 'StaticPairList')
        self.pairlists = PairListResolver(pairlistname, self,
                                          self.config).pairlist

        # Initializing Edge only if enabled
        self.edge = Edge(self.config, self.exchange, self.strategy) if \
            self.config.get('edge', {}).get('enabled', False) else None

        self.active_pair_whitelist: List[str] = self.config['exchange'][
            'pair_whitelist']

        persistence.init(self.config.get('db_url', None),
                         clean_open_orders=self.config.get('dry_run', False))

        # Set initial bot state from config
        initial_state = self.config.get('initial_state')
        self.state = State[
            initial_state.upper()] if initial_state else State.STOPPED
Exemple #17
0
    def _init_modules(self) -> None:
        """
        Initializes all modules and updates the config
        :return: None
        """
        # Initialize all modules

        persistence.init(self.config)

        # Set initial application state
        initial_state = self.config.get('initial_state')

        if initial_state:
            self.state = State[initial_state.upper()]
        else:
            self.state = State.STOPPED
Exemple #18
0
def test_clean_dry_run_db(default_conf):
    init(default_conf, create_engine('sqlite://'))

    # Simulate dry_run entries
    trade = Trade(
        pair='BTC_ETH',
        stake_amount=0.001,
        amount=123.0,
        fee=0.0025,
        open_rate=0.123,
        exchange='BITTREX',
        open_order_id='dry_run_buy_12345'
    )
    Trade.session.add(trade)

    trade = Trade(
        pair='BTC_ETC',
        stake_amount=0.001,
        amount=123.0,
        fee=0.0025,
        open_rate=0.123,
        exchange='BITTREX',
        open_order_id='dry_run_sell_12345'
    )
    Trade.session.add(trade)

    # Simulate prod entry
    trade = Trade(
        pair='BTC_ETC',
        stake_amount=0.001,
        amount=123.0,
        fee=0.0025,
        open_rate=0.123,
        exchange='BITTREX',
        open_order_id='prod_buy_12345'
    )
    Trade.session.add(trade)

    # We have 3 entries: 2 dry_run, 1 prod
    assert len(Trade.query.filter(Trade.open_order_id.isnot(None)).all()) == 3

    clean_dry_run_db()

    # We have now only the prod
    assert len(Trade.query.filter(Trade.open_order_id.isnot(None)).all()) == 1
Exemple #19
0
def init(config: dict, db_url: Optional[str] = None) -> None:
    """
    Initializes all modules and updates the config
    :param config: config as dict
    :param db_url: database connector string for sqlalchemy (Optional)
    :return: None
    """
    # Initialize all modules
    telegram.init(config)
    persistence.init(config, db_url)
    exchange.init(config)

    # Set initial application state
    initial_state = config.get('initial_state')
    if initial_state:
        update_state(State[initial_state.upper()])
    else:
        update_state(State.STOPPED)
Exemple #20
0
def init(config: dict, db_url: Optional[str] = None) -> None:
    """
    Initializes all modules and updates the config
    :param config: config as dict
    :param db_url: database connector string for sqlalchemy (Optional)
    :return: None
    """
    # Initialize all modules
    rpc.init(config)
    persistence.init(config, db_url)
    exchange.init(config)

    # Set initial application state
    initial_state = config.get('initial_state')
    if initial_state:
        update_state(State[initial_state.upper()])
    else:
        update_state(State.STOPPED)
Exemple #21
0
def test_init_dry_run_without_db(default_conf, mocker):
    default_conf.update({'dry_run_db': False})
    mocker.patch.dict('freqtrade.persistence._CONF', default_conf)

    # First, protect the existing 'tradesv3.dry_run.sqlite' (Do not delete user data)
    dry_run_db = 'tradesv3.dry_run.sqlite'
    dry_run_db_swp = dry_run_db + '.swp'

    if os.path.isfile(dry_run_db):
        os.rename(dry_run_db, dry_run_db_swp)

    # Check if the new tradesv3.dry_run.sqlite was created
    init(default_conf)
    assert os.path.isfile(dry_run_db) is False

    # Rollback to the initial 'tradesv3.dry_run.sqlite' file
    if os.path.isfile(dry_run_db_swp):
        os.rename(dry_run_db_swp, dry_run_db)
Exemple #22
0
def test_clean_dry_run_db(default_conf, fee):
    init(default_conf)

    # Simulate dry_run entries
    trade = Trade(pair='ETH/BTC',
                  stake_amount=0.001,
                  amount=123.0,
                  fee_open=fee.return_value,
                  fee_close=fee.return_value,
                  open_rate=0.123,
                  exchange='bittrex',
                  open_order_id='dry_run_buy_12345')
    Trade.session.add(trade)

    trade = Trade(pair='ETC/BTC',
                  stake_amount=0.001,
                  amount=123.0,
                  fee_open=fee.return_value,
                  fee_close=fee.return_value,
                  open_rate=0.123,
                  exchange='bittrex',
                  open_order_id='dry_run_sell_12345')
    Trade.session.add(trade)

    # Simulate prod entry
    trade = Trade(pair='ETC/BTC',
                  stake_amount=0.001,
                  amount=123.0,
                  fee_open=fee.return_value,
                  fee_close=fee.return_value,
                  open_rate=0.123,
                  exchange='bittrex',
                  open_order_id='prod_buy_12345')
    Trade.session.add(trade)

    # We have 3 entries: 2 dry_run, 1 prod
    assert len(Trade.query.filter(Trade.open_order_id.isnot(None)).all()) == 3

    clean_dry_run_db()

    # We have now only the prod
    assert len(Trade.query.filter(Trade.open_order_id.isnot(None)).all()) == 1
Exemple #23
0
    def _init_modules(self, db_url: Optional[str] = None) -> None:
        """
        Initializes all modules and updates the config
        :param db_url: database connector string for sqlalchemy (Optional)
        :return: None
        """
        # Initialize all modules
        self.analyze = Analyze(self.config)
        self.fiat_converter = CryptoToFiatConverter()
        self.rpc = RPCManager(self)

        persistence.init(self.config, db_url)
        exchange.init(self.config)

        # Set initial application state
        initial_state = self.config.get('initial_state')

        if initial_state:
            self.state = State[initial_state.upper()]
        else:
            self.state = State.STOPPED
Exemple #24
0
def init(config: dict, db_url: Optional[str] = None) -> None:
    """
    Initializes all modules and updates the config
    :param config: config as dict
    :param db_url: database connector string for sqlalchemy (Optional)
    :return: None
    """
    # Initialize all modules
    rpc.init(config)
    persistence.init(config, db_url)
    exchange.init(config)

    # Set initial application state
    initial_state = config.get('initial_state')
    if initial_state:
        update_state(State[initial_state.upper()])
    else:
        update_state(State.STOPPED)

    # Register signal handlers
    for sig in (SIGINT, SIGTERM, SIGABRT):
        signal(sig, cleanup)
Exemple #25
0
def test_get_open(default_conf, fee):
    init(default_conf)

    # Simulate dry_run entries
    trade = Trade(pair='ETH/BTC',
                  stake_amount=0.001,
                  amount=123.0,
                  fee_open=fee.return_value,
                  fee_close=fee.return_value,
                  open_rate=0.123,
                  exchange='bittrex',
                  open_order_id='dry_run_buy_12345')
    Trade.session.add(trade)

    trade = Trade(pair='ETC/BTC',
                  stake_amount=0.001,
                  amount=123.0,
                  fee_open=fee.return_value,
                  fee_close=fee.return_value,
                  open_rate=0.123,
                  exchange='bittrex',
                  is_open=False,
                  open_order_id='dry_run_sell_12345')
    Trade.session.add(trade)

    # Simulate prod entry
    trade = Trade(pair='ETC/BTC',
                  stake_amount=0.001,
                  amount=123.0,
                  fee_open=fee.return_value,
                  fee_close=fee.return_value,
                  open_rate=0.123,
                  exchange='bittrex',
                  open_order_id='prod_buy_12345')
    Trade.session.add(trade)

    assert len(Trade.get_open_trades()) == 2
Exemple #26
0
def load_trades_from_db(db_url: str,
                        strategy: Optional[str] = None) -> pd.DataFrame:
    """
    Load trades from a DB (using dburl)
    :param db_url: Sqlite url (default format sqlite:///tradesv3.dry-run.sqlite)
    :param strategy: Strategy to load - mainly relevant for multi-strategy backtests
                     Can also serve as protection to load the correct result.
    :return: Dataframe containing Trades
    """
    persistence.init(db_url, clean_open_orders=False)

    columns = [
        "pair", "open_date", "close_date", "profit", "profit_percent",
        "open_rate", "close_rate", "amount", "trade_duration", "sell_reason",
        "fee_open", "fee_close", "open_rate_requested", "close_rate_requested",
        "stake_amount", "max_rate", "min_rate", "id", "exchange", "stop_loss",
        "initial_stop_loss", "strategy", "timeframe"
    ]

    filters = []
    if strategy:
        filters.append(Trade.strategy == strategy)

    trades = pd.DataFrame(
        [(t.pair, t.open_date.replace(tzinfo=timezone.utc),
          t.close_date.replace(tzinfo=timezone.utc) if t.close_date else None,
          t.calc_profit(), t.calc_profit_ratio(), t.open_rate, t.close_rate,
          t.amount, (round(
              (t.close_date.timestamp() - t.open_date.timestamp()) /
              60, 2) if t.close_date else None), t.sell_reason, t.fee_open,
          t.fee_close, t.open_rate_requested, t.close_rate_requested,
          t.stake_amount, t.max_rate, t.min_rate, t.id, t.exchange,
          t.stop_loss, t.initial_stop_loss, t.strategy, t.timeframe)
         for t in Trade.get_trades(filters).all()],
        columns=columns)

    return trades
Exemple #27
0
def test_migrate_new(mocker, default_conf, fee, caplog):
    """
    Test Database migration (starting with new pairformat)
    """
    amount = 103.223
    # Always create all columns apart from the last!
    create_table_old = """CREATE TABLE IF NOT EXISTS "trades" (
                                id INTEGER NOT NULL,
                                exchange VARCHAR NOT NULL,
                                pair VARCHAR NOT NULL,
                                is_open BOOLEAN NOT NULL,
                                fee FLOAT NOT NULL,
                                open_rate FLOAT,
                                close_rate FLOAT,
                                close_profit FLOAT,
                                stake_amount FLOAT NOT NULL,
                                amount FLOAT,
                                open_date DATETIME NOT NULL,
                                close_date DATETIME,
                                open_order_id VARCHAR,
                                stop_loss FLOAT,
                                initial_stop_loss FLOAT,
                                max_rate FLOAT,
                                sell_reason VARCHAR,
                                strategy VARCHAR,
                                PRIMARY KEY (id),
                                CHECK (is_open IN (0, 1))
                                );"""
    insert_table_old = """INSERT INTO trades (exchange, pair, is_open, fee,
                          open_rate, stake_amount, amount, open_date,
                          stop_loss, initial_stop_loss, max_rate)
                          VALUES ('binance', 'ETC/BTC', 1, {fee},
                          0.00258580, {stake}, {amount},
                          '2019-11-28 12:44:24.000000',
                          0.0, 0.0, 0.0)
                          """.format(fee=fee.return_value,
                                     stake=default_conf.get("stake_amount"),
                                     amount=amount)
    engine = create_engine('sqlite://')
    mocker.patch('freqtrade.persistence.create_engine',
                 lambda *args, **kwargs: engine)

    # Create table using the old format
    engine.execute(create_table_old)
    engine.execute(insert_table_old)

    # fake previous backup
    engine.execute("create table trades_bak as select * from trades")

    engine.execute("create table trades_bak1 as select * from trades")
    # Run init to test migration
    init(default_conf)

    assert len(Trade.query.filter(Trade.id == 1).all()) == 1
    trade = Trade.query.filter(Trade.id == 1).first()
    assert trade.fee_open == fee.return_value
    assert trade.fee_close == fee.return_value
    assert trade.open_rate_requested is None
    assert trade.close_rate_requested is None
    assert trade.is_open == 1
    assert trade.amount == amount
    assert trade.stake_amount == default_conf.get("stake_amount")
    assert trade.pair == "ETC/BTC"
    assert trade.exchange == "binance"
    assert trade.max_rate == 0.0
    assert trade.stop_loss == 0.0
    assert trade.initial_stop_loss == 0.0
    assert trade.sell_reason is None
    assert trade.strategy is None
    assert trade.ticker_interval is None
    assert log_has("trying trades_bak1", caplog.record_tuples)
    assert log_has("trying trades_bak2", caplog.record_tuples)
Exemple #28
0
def test_init_invalid_db_url(default_conf):
    # Update path to a value other than default, but still in-memory
    default_conf.update({'db_url': 'unknown:///some.url'})
    with pytest.raises(OperationalException,
                       match=r'.*no valid database URL*'):
        init(default_conf)
Exemple #29
0
def test_init_create_session(default_conf):
    # Check if init create a session
    init(default_conf)
    assert hasattr(Trade, 'session')
    assert 'Session' in type(Trade.session).__name__
Exemple #30
0
def init_persistence(default_conf):
    init(default_conf)
def test_init_create_session(default_conf):
    # Check if init create a session
    init(default_conf['db_url'], default_conf['dry_run'])
    assert hasattr(Trade, 'session')
    assert 'scoped_session' in type(Trade.session).__name__