Skip to content

Commit

Permalink
Use ticker_interval defined in Strategy() instead of a mix between st…
Browse files Browse the repository at this point in the history
…rategy and config file
  • Loading branch information
glonlas committed Mar 6, 2018
1 parent c94f558 commit 451aef8
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 92 deletions.
7 changes: 7 additions & 0 deletions freqtrade/analyze.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,13 @@ def populate_sell_trend(self, dataframe: DataFrame) -> DataFrame:
"""
return self.strategy.populate_sell_trend(dataframe=dataframe)

def get_ticker_interval(self) -> int:
"""
Return ticker interval to use
:return: Ticker interval value to use
"""
return self.strategy.ticker_interval

def analyze_ticker(self, ticker_history: List[Dict]) -> DataFrame:
"""
Parses the given ticker history and returns a populated DataFrame
Expand Down
35 changes: 14 additions & 21 deletions freqtrade/freqtradebot.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,17 +125,9 @@ def worker(self, old_state: None) -> State:
Constants.DYNAMIC_WHITELIST
)

interval = int(
self.config.get(
'ticker_interval',
Constants.TICKER_INTERVAL
)
)

self._throttle(func=self._process,
min_secs=min_secs,
nb_assets=nb_assets,
interval=interval)
nb_assets=nb_assets)
return new_state

def _throttle(self, func: Callable[..., Any], min_secs: float, *args, **kwargs) -> Any:
Expand All @@ -154,7 +146,7 @@ def _throttle(self, func: Callable[..., Any], min_secs: float, *args, **kwargs)
time.sleep(duration)
return result

def _process(self, interval: int, nb_assets: Optional[int] = 0) -> bool:
def _process(self, nb_assets: Optional[int] = 0) -> bool:
"""
Queries the persistence layer for open trades and handles them,
otherwise a new trade is created.
Expand All @@ -179,11 +171,11 @@ def _process(self, interval: int, nb_assets: Optional[int] = 0) -> bool:

# First process current opened trades
for trade in trades:
state_changed |= self.process_maybe_execute_sell(trade, interval)
state_changed |= self.process_maybe_execute_sell(trade)

# Then looking for buy opportunities
if len(trades) < self.config['max_open_trades']:
state_changed = self.process_maybe_execute_buy(interval)
state_changed = self.process_maybe_execute_buy()

if 'unfilledtimeout' in self.config:
# Check and handle any timed out open orders
Expand Down Expand Up @@ -263,16 +255,17 @@ def get_target_bid(self, ticker: Dict[str, float]) -> float:
balance = self.config['bid_strategy']['ask_last_balance']
return ticker['ask'] + balance * (ticker['last'] - ticker['ask'])

# TODO: Remove the two parameters and use the value already in conf['stake_amount'] and
# int(conf['ticker_interval'])
def create_trade(self, stake_amount: float, interval: int) -> bool:
def create_trade(self) -> bool:
"""
Checks the implemented trading indicator(s) for a randomly picked pair,
if one pair triggers the buy_signal a new trade record gets created
:param stake_amount: amount of btc to spend
:param interval: Ticker interval used for Analyze
:return: True if a trade object has been created and persisted, False otherwise
"""
stake_amount = self.config['stake_amount']
interval = self.analyze.get_ticker_interval()

self.logger.info(
'Checking buy signals to create a new trade with stake_amount: %f ...',
stake_amount
Expand Down Expand Up @@ -343,14 +336,14 @@ def create_trade(self, stake_amount: float, interval: int) -> bool:
Trade.session.flush()
return True

def process_maybe_execute_buy(self, interval: int) -> bool:
def process_maybe_execute_buy(self) -> bool:
"""
Tries to execute a buy trade in a safe way
:return: True if executed
"""
try:
# Create entity and execute trade
if self.create_trade(float(self.config['stake_amount']), interval):
if self.create_trade():
return True

self.logger.info('Found no buy signals for whitelisted currencies. Trying again..')
Expand All @@ -359,7 +352,7 @@ def process_maybe_execute_buy(self, interval: int) -> bool:
self.logger.warning('Unable to create trade: %s', exception)
return False

def process_maybe_execute_sell(self, trade: Trade, interval: int) -> bool:
def process_maybe_execute_sell(self, trade: Trade) -> bool:
"""
Tries to execute a sell trade
:return: True if executed
Expand All @@ -372,10 +365,10 @@ def process_maybe_execute_sell(self, trade: Trade, interval: int) -> bool:

if trade.is_open and trade.open_order_id is None:
# Check if we can sell our current pair
return self.handle_trade(trade, interval)
return self.handle_trade(trade)
return False

def handle_trade(self, trade: Trade, interval: int) -> bool:
def handle_trade(self, trade: Trade) -> bool:
"""
Sells the current pair if the threshold is reached and updates the trade record.
:return: True if trade has been sold, False otherwise
Expand All @@ -389,7 +382,7 @@ def handle_trade(self, trade: Trade, interval: int) -> bool:
(buy, sell) = (False, False)

if self.config.get('experimental', {}).get('use_sell_signal'):
(buy, sell) = self.analyze.get_signal(trade.pair, interval)
(buy, sell) = self.analyze.get_signal(trade.pair, self.analyze.get_ticker_interval())

if self.analyze.should_sell(trade, current_rate, datetime.utcnow(), buy, sell):
self.execute_sell(trade, current_rate)
Expand Down
2 changes: 1 addition & 1 deletion freqtrade/strategy/strategy.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def __init__(self, config: dict = {}) -> None:
# Optimal stoploss designed for the strategy
self.stoploss = float(self.custom_strategy.stoploss)

self.ticker_interval = self.custom_strategy.ticker_interval
self.ticker_interval = int(self.custom_strategy.ticker_interval)

def _load_strategy(self, strategy_name: str) -> None:
"""
Expand Down
18 changes: 9 additions & 9 deletions freqtrade/tests/rpc/test_rpc.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ def test_rpc_trade_status(default_conf, ticker, mocker) -> None:
assert error
assert 'no active trade' in result

freqtradebot.create_trade(0.001, 5)
freqtradebot.create_trade()
(error, result) = rpc.rpc_trade_status()
assert not error
trade = result[0]
Expand Down Expand Up @@ -99,7 +99,7 @@ def test_rpc_status_table(default_conf, ticker, mocker) -> None:
assert error
assert '*Status:* `no active order`' in result

freqtradebot.create_trade(0.001, 5)
freqtradebot.create_trade()
(error, result) = rpc.rpc_status_table()
assert 'just now' in result['Since'].all()
assert 'BTC_ETH' in result['Pair'].all()
Expand Down Expand Up @@ -127,7 +127,7 @@ def test_rpc_daily_profit(default_conf, update, ticker, limit_buy_order, limit_s
rpc = RPC(freqtradebot)

# Create some test data
freqtradebot.create_trade(0.001, 5)
freqtradebot.create_trade()
trade = Trade.query.first()
assert trade

Expand Down Expand Up @@ -188,7 +188,7 @@ def test_rpc_trade_statistics(
assert stats.find('no closed trade') >= 0

# Create some test data
freqtradebot.create_trade(0.001, 5)
freqtradebot.create_trade()
trade = Trade.query.first()
# Simulate fulfilled LIMIT_BUY order for trade
trade.update(limit_buy_order)
Expand Down Expand Up @@ -247,7 +247,7 @@ def test_rpc_trade_statistics_closed(mocker, default_conf, ticker, ticker_sell_u
rpc = RPC(freqtradebot)

# Create some test data
freqtradebot.create_trade(0.001, 5)
freqtradebot.create_trade()
trade = Trade.query.first()
# Simulate fulfilled LIMIT_BUY order for trade
trade.update(limit_buy_order)
Expand Down Expand Up @@ -427,7 +427,7 @@ def test_rpc_forcesell(default_conf, ticker, mocker) -> None:
assert not error
assert res == ''

freqtradebot.create_trade(0.001, 5)
freqtradebot.create_trade()
(error, res) = rpc.rpc_forcesell('all')
assert not error
assert res == ''
Expand Down Expand Up @@ -462,7 +462,7 @@ def test_rpc_forcesell(default_conf, ticker, mocker) -> None:
assert res == ''
assert cancel_order_mock.call_count == 1

freqtradebot.create_trade(0.001, 5)
freqtradebot.create_trade()
# make an limit-sell open trade
mocker.patch(
'freqtrade.freqtradebot.exchange.get_order',
Expand Down Expand Up @@ -497,7 +497,7 @@ def test_performance_handle(default_conf, ticker, limit_buy_order,
rpc = RPC(freqtradebot)

# Create some test data
freqtradebot.create_trade(0.001, int(default_conf['ticker_interval']))
freqtradebot.create_trade()
trade = Trade.query.first()
assert trade

Expand Down Expand Up @@ -540,7 +540,7 @@ def test_rpc_count(mocker, default_conf, ticker) -> None:
assert nb_trades == 0

# Create some test data
freqtradebot.create_trade(0.001, int(default_conf['ticker_interval']))
freqtradebot.create_trade()
(error, trades) = rpc.rpc_count()
nb_trades = len(trades)
assert not error
Expand Down
28 changes: 15 additions & 13 deletions freqtrade/tests/rpc/test_rpc_telegram.py
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ def test_status(default_conf, update, mocker, ticker) -> None:

# Create some test data
for _ in range(3):
freqtradebot.create_trade(0.001, 5)
freqtradebot.create_trade()

telegram._status(bot=MagicMock(), update=update)
assert msg_mock.call_count == 3
Expand Down Expand Up @@ -314,7 +314,7 @@ def test_status_handle(default_conf, update, ticker, mocker) -> None:
msg_mock.reset_mock()

# Create some test data
freqtradebot.create_trade(0.001, int(default_conf['ticker_interval']))
freqtradebot.create_trade()
# Trigger status while we have a fulfilled order for the open trade
telegram._status(bot=MagicMock(), update=update)

Expand Down Expand Up @@ -342,7 +342,9 @@ def test_status_table_handle(default_conf, update, ticker, mocker) -> None:
)
mocker.patch('freqtrade.freqtradebot.RPCManager', MagicMock())

freqtradebot = FreqtradeBot(default_conf, create_engine('sqlite://'))
conf = deepcopy(default_conf)
conf['stake_amount'] = 15.0
freqtradebot = FreqtradeBot(conf, create_engine('sqlite://'))
telegram = Telegram(freqtradebot)

freqtradebot.update_state(State.STOPPED)
Expand All @@ -358,7 +360,7 @@ def test_status_table_handle(default_conf, update, ticker, mocker) -> None:
msg_mock.reset_mock()

# Create some test data
freqtradebot.create_trade(15.0, int(default_conf['ticker_interval']))
freqtradebot.create_trade()

telegram._status_table(bot=MagicMock(), update=update)

Expand Down Expand Up @@ -399,7 +401,7 @@ def test_daily_handle(default_conf, update, ticker, limit_buy_order,
telegram = Telegram(freqtradebot)

# Create some test data
freqtradebot.create_trade(0.001, int(default_conf['ticker_interval']))
freqtradebot.create_trade()
trade = Trade.query.first()
assert trade

Expand All @@ -426,8 +428,8 @@ def test_daily_handle(default_conf, update, ticker, limit_buy_order,
# Reset msg_mock
msg_mock.reset_mock()
# Add two other trades
freqtradebot.create_trade(0.001, int(default_conf['ticker_interval']))
freqtradebot.create_trade(0.001, int(default_conf['ticker_interval']))
freqtradebot.create_trade()
freqtradebot.create_trade()

trades = Trade.query.all()
for trade in trades:
Expand Down Expand Up @@ -512,7 +514,7 @@ def test_profit_handle(default_conf, update, ticker, ticker_sell_up,
msg_mock.reset_mock()

# Create some test data
freqtradebot.create_trade(0.001, int(default_conf['ticker_interval']))
freqtradebot.create_trade()
trade = Trade.query.first()

# Simulate fulfilled LIMIT_BUY order for trade
Expand Down Expand Up @@ -764,7 +766,7 @@ def test_forcesell_handle(default_conf, update, ticker, ticker_sell_up, mocker)
telegram = Telegram(freqtradebot)

# Create some test data
freqtradebot.create_trade(0.001, int(default_conf['ticker_interval']))
freqtradebot.create_trade()

trade = Trade.query.first()
assert trade
Expand Down Expand Up @@ -803,7 +805,7 @@ def test_forcesell_down_handle(default_conf, update, ticker, ticker_sell_down, m
telegram = Telegram(freqtradebot)

# Create some test data
freqtradebot.create_trade(0.001, int(default_conf['ticker_interval']))
freqtradebot.create_trade()

# Decrease the price and sell it
mocker.patch.multiple(
Expand Down Expand Up @@ -847,7 +849,7 @@ def test_forcesell_all_handle(default_conf, update, ticker, mocker) -> None:

# Create some test data
for _ in range(4):
freqtradebot.create_trade(0.001, int(default_conf['ticker_interval']))
freqtradebot.create_trade()
rpc_mock.reset_mock()

update.message.text = '/forcesell all'
Expand Down Expand Up @@ -925,7 +927,7 @@ def test_performance_handle(default_conf, update, ticker, limit_buy_order,
telegram = Telegram(freqtradebot)

# Create some test data
freqtradebot.create_trade(0.001, int(default_conf['ticker_interval']))
freqtradebot.create_trade()
trade = Trade.query.first()
assert trade

Expand Down Expand Up @@ -995,7 +997,7 @@ def test_count_handle(default_conf, update, ticker, mocker) -> None:
freqtradebot.update_state(State.RUNNING)

# Create some test data
freqtradebot.create_trade(0.001, int(default_conf['ticker_interval']))
freqtradebot.create_trade()
msg_mock.reset_mock()
telegram._count(bot=MagicMock(), update=update)

Expand Down

0 comments on commit 451aef8

Please sign in to comment.