Merge branch 'wohlgemuth' of https://github.com/berlinguyinca/freqtrade into wohlgemuth
This commit is contained in:
commit
39368baffd
@ -40,7 +40,7 @@ due to demand, it is possible to have a default stop loss, when you are in the r
|
|||||||
the system will utilize a new stop loss, which can be a different value. For example your default stop loss is 5%, but once you are in the
|
the system will utilize a new stop loss, which can be a different value. For example your default stop loss is 5%, but once you are in the
|
||||||
black, it will be changed to be only a 1% stop loss
|
black, it will be changed to be only a 1% stop loss
|
||||||
|
|
||||||
this can be configured in the main confiuration file, the following way:
|
this can be configured in the main configuration file, the following way:
|
||||||
|
|
||||||
```
|
```
|
||||||
"trailing_stop": {
|
"trailing_stop": {
|
||||||
|
@ -65,7 +65,7 @@ class Analyze(object):
|
|||||||
frame.drop(frame.tail(1).index, inplace=True) # eliminate partial candle
|
frame.drop(frame.tail(1).index, inplace=True) # eliminate partial candle
|
||||||
return frame
|
return frame
|
||||||
|
|
||||||
def populate_indicators(self, dataframe: DataFrame) -> DataFrame:
|
def populate_indicators(self, dataframe: DataFrame, pair: str = None) -> DataFrame:
|
||||||
"""
|
"""
|
||||||
Adds several different TA indicators to the given DataFrame
|
Adds several different TA indicators to the given DataFrame
|
||||||
|
|
||||||
@ -73,23 +73,23 @@ class Analyze(object):
|
|||||||
you are using. Let uncomment only the indicator you are using in your strategies
|
you are using. Let uncomment only the indicator you are using in your strategies
|
||||||
or your hyperopt configuration, otherwise you will waste your memory and CPU usage.
|
or your hyperopt configuration, otherwise you will waste your memory and CPU usage.
|
||||||
"""
|
"""
|
||||||
return self.strategy.populate_indicators(dataframe=dataframe)
|
return self.strategy.advise_indicators(dataframe=dataframe, pair=pair)
|
||||||
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame) -> DataFrame:
|
def populate_buy_trend(self, dataframe: DataFrame, pair: str = None) -> DataFrame:
|
||||||
"""
|
"""
|
||||||
Based on TA indicators, populates the buy signal for the given dataframe
|
Based on TA indicators, populates the buy signal for the given dataframe
|
||||||
:param dataframe: DataFrame
|
:param dataframe: DataFrame
|
||||||
:return: DataFrame with buy column
|
:return: DataFrame with buy column
|
||||||
"""
|
"""
|
||||||
return self.strategy.populate_buy_trend(dataframe=dataframe)
|
return self.strategy.advise_buy(dataframe=dataframe, pair=pair)
|
||||||
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame) -> DataFrame:
|
def populate_sell_trend(self, dataframe: DataFrame, pair: str = None) -> DataFrame:
|
||||||
"""
|
"""
|
||||||
Based on TA indicators, populates the sell signal for the given dataframe
|
Based on TA indicators, populates the sell signal for the given dataframe
|
||||||
:param dataframe: DataFrame
|
:param dataframe: DataFrame
|
||||||
:return: DataFrame with buy column
|
:return: DataFrame with buy column
|
||||||
"""
|
"""
|
||||||
return self.strategy.populate_sell_trend(dataframe=dataframe)
|
return self.strategy.advise_sell(dataframe=dataframe, pair=pair)
|
||||||
|
|
||||||
def get_ticker_interval(self) -> str:
|
def get_ticker_interval(self) -> str:
|
||||||
"""
|
"""
|
||||||
@ -98,16 +98,17 @@ class Analyze(object):
|
|||||||
"""
|
"""
|
||||||
return self.strategy.ticker_interval
|
return self.strategy.ticker_interval
|
||||||
|
|
||||||
def analyze_ticker(self, ticker_history: List[Dict]) -> DataFrame:
|
def analyze_ticker(self, ticker_history: List[Dict], pair: str) -> DataFrame:
|
||||||
"""
|
"""
|
||||||
Parses the given ticker history and returns a populated DataFrame
|
Parses the given ticker history and returns a populated DataFrame
|
||||||
add several TA indicators and buy signal to it
|
add several TA indicators and buy signal to it
|
||||||
:return DataFrame with ticker data and indicator data
|
:return DataFrame with ticker data and indicator data
|
||||||
"""
|
"""
|
||||||
|
|
||||||
dataframe = self.parse_ticker_dataframe(ticker_history)
|
dataframe = self.parse_ticker_dataframe(ticker_history)
|
||||||
dataframe = self.populate_indicators(dataframe)
|
dataframe = self.populate_indicators(dataframe, pair)
|
||||||
dataframe = self.populate_buy_trend(dataframe)
|
dataframe = self.populate_buy_trend(dataframe, pair)
|
||||||
dataframe = self.populate_sell_trend(dataframe)
|
dataframe = self.populate_sell_trend(dataframe, pair)
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
def get_signal(self, pair: str, interval: str) -> Tuple[bool, bool]:
|
def get_signal(self, pair: str, interval: str) -> Tuple[bool, bool]:
|
||||||
@ -123,7 +124,7 @@ class Analyze(object):
|
|||||||
return False, False
|
return False, False
|
||||||
|
|
||||||
try:
|
try:
|
||||||
dataframe = self.analyze_ticker(ticker_hist)
|
dataframe = self.analyze_ticker(ticker_hist, pair)
|
||||||
except ValueError as error:
|
except ValueError as error:
|
||||||
logger.warning(
|
logger.warning(
|
||||||
'Unable to analyze ticker for pair %s: %s',
|
'Unable to analyze ticker for pair %s: %s',
|
||||||
|
@ -156,7 +156,7 @@ class FreqtradeBot(object):
|
|||||||
state_changed |= self.process_maybe_execute_sell(trade)
|
state_changed |= self.process_maybe_execute_sell(trade)
|
||||||
|
|
||||||
# Then looking for buy opportunities
|
# Then looking for buy opportunities
|
||||||
if (self.config['disable_buy']):
|
if (self.config.get('disable_buy', False)):
|
||||||
logger.info('Buy disabled...')
|
logger.info('Buy disabled...')
|
||||||
else:
|
else:
|
||||||
if len(trades) < self.config['max_open_trades']:
|
if len(trades) < self.config['max_open_trades']:
|
||||||
@ -250,7 +250,7 @@ class FreqtradeBot(object):
|
|||||||
balance = self.config['bid_strategy']['ask_last_balance']
|
balance = self.config['bid_strategy']['ask_last_balance']
|
||||||
ticker_rate = ticker['ask'] + balance * (ticker['last'] - ticker['ask'])
|
ticker_rate = ticker['ask'] + balance * (ticker['last'] - ticker['ask'])
|
||||||
|
|
||||||
if self.config['bid_strategy']['use_book_order']:
|
if self.config['bid_strategy'].get('use_book_order', False):
|
||||||
logger.info('Getting price from Order Book')
|
logger.info('Getting price from Order Book')
|
||||||
orderBook = exchange.get_order_book(pair)
|
orderBook = exchange.get_order_book(pair)
|
||||||
orderBook_rate = orderBook['bids'][self.config['bid_strategy']['book_order_top']][0]
|
orderBook_rate = orderBook['bids'][self.config['bid_strategy']['book_order_top']][0]
|
||||||
@ -444,7 +444,7 @@ with limit `{buy_limit:.8f} ({stake_amount:.6f} \
|
|||||||
if self.config.get('experimental', {}).get('use_sell_signal'):
|
if self.config.get('experimental', {}).get('use_sell_signal'):
|
||||||
(buy, sell) = self.analyze.get_signal(trade.pair, self.analyze.get_ticker_interval())
|
(buy, sell) = self.analyze.get_signal(trade.pair, self.analyze.get_ticker_interval())
|
||||||
|
|
||||||
if self.config['ask_strategy']['use_book_order']:
|
if 'ask_strategy' in self.config and self.config['ask_strategy'].get('use_book_order', False):
|
||||||
logger.info('Using order book for selling...')
|
logger.info('Using order book for selling...')
|
||||||
orderBook = exchange.get_order_book(trade.pair)
|
orderBook = exchange.get_order_book(trade.pair)
|
||||||
# logger.debug('Order book %s',orderBook)
|
# logger.debug('Order book %s',orderBook)
|
||||||
@ -502,7 +502,7 @@ with limit `{buy_limit:.8f} ({stake_amount:.6f} \
|
|||||||
ordertime = arrow.get(order['datetime']).datetime
|
ordertime = arrow.get(order['datetime']).datetime
|
||||||
|
|
||||||
# Check if trade is still actually open
|
# Check if trade is still actually open
|
||||||
if (int(order['filled']) == 0) and (order['status'] == 'open'):
|
if order['status'] == 'open':
|
||||||
if order['side'] == 'buy' and ordertime < buy_timeoutthreashold:
|
if order['side'] == 'buy' and ordertime < buy_timeoutthreashold:
|
||||||
self.handle_timedout_limit_buy(trade, order)
|
self.handle_timedout_limit_buy(trade, order)
|
||||||
elif order['side'] == 'sell' and ordertime < sell_timeoutthreashold:
|
elif order['side'] == 'sell' and ordertime < sell_timeoutthreashold:
|
||||||
|
@ -2,12 +2,12 @@
|
|||||||
IStrategy interface
|
IStrategy interface
|
||||||
This module defines the interface to apply for strategies
|
This module defines the interface to apply for strategies
|
||||||
"""
|
"""
|
||||||
|
import warnings
|
||||||
from typing import Dict
|
from typing import Dict
|
||||||
from abc import ABC, abstractmethod
|
|
||||||
|
|
||||||
|
from abc import ABC
|
||||||
from pandas import DataFrame
|
from pandas import DataFrame
|
||||||
|
|
||||||
|
|
||||||
class IStrategy(ABC):
|
class IStrategy(ABC):
|
||||||
"""
|
"""
|
||||||
Interface for freqtrade strategies
|
Interface for freqtrade strategies
|
||||||
@ -19,30 +19,71 @@ class IStrategy(ABC):
|
|||||||
ticker_interval -> str: value of the ticker interval to use for the strategy
|
ticker_interval -> str: value of the ticker interval to use for the strategy
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
# associated minimal roi
|
||||||
minimal_roi: Dict
|
minimal_roi: Dict
|
||||||
|
|
||||||
|
# associated stoploss
|
||||||
stoploss: float
|
stoploss: float
|
||||||
|
|
||||||
|
# associated ticker interval
|
||||||
ticker_interval: str
|
ticker_interval: str
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def populate_indicators(self, dataframe: DataFrame) -> DataFrame:
|
def populate_indicators(self, dataframe: DataFrame) -> DataFrame:
|
||||||
"""
|
"""
|
||||||
Populate indicators that will be used in the Buy and Sell strategy
|
Populate indicators that will be used in the Buy and Sell strategy
|
||||||
:param dataframe: Raw data from the exchange and parsed by parse_ticker_dataframe()
|
:param dataframe: Raw data from the exchange and parsed by parse_ticker_dataframe()
|
||||||
:return: a Dataframe with all mandatory indicators for the strategies
|
:return: a Dataframe with all mandatory indicators for the strategies
|
||||||
"""
|
"""
|
||||||
|
warnings.warn("deprecated - please replace this method with advise_indicators!", DeprecationWarning)
|
||||||
|
return dataframe
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def populate_buy_trend(self, dataframe: DataFrame) -> DataFrame:
|
def populate_buy_trend(self, dataframe: DataFrame) -> DataFrame:
|
||||||
"""
|
"""
|
||||||
Based on TA indicators, populates the buy signal for the given dataframe
|
Based on TA indicators, populates the buy signal for the given dataframe
|
||||||
:param dataframe: DataFrame
|
:param dataframe: DataFrame
|
||||||
:return: DataFrame with buy column
|
:return: DataFrame with buy column
|
||||||
"""
|
"""
|
||||||
|
warnings.warn("deprecated - please replace this method with advise_buy!", DeprecationWarning)
|
||||||
|
dataframe.loc[(), 'buy'] = 0
|
||||||
|
return dataframe
|
||||||
|
|
||||||
@abstractmethod
|
|
||||||
def populate_sell_trend(self, dataframe: DataFrame) -> DataFrame:
|
def populate_sell_trend(self, dataframe: DataFrame) -> DataFrame:
|
||||||
"""
|
"""
|
||||||
Based on TA indicators, populates the sell signal for the given dataframe
|
Based on TA indicators, populates the sell signal for the given dataframe
|
||||||
:param dataframe: DataFrame
|
:param dataframe: DataFrame
|
||||||
:return: DataFrame with sell column
|
:return: DataFrame with sell column
|
||||||
"""
|
"""
|
||||||
|
warnings.warn("deprecated - please replace this method with advise_sell!", DeprecationWarning)
|
||||||
|
dataframe.loc[(), 'sell'] = 0
|
||||||
|
return dataframe
|
||||||
|
|
||||||
|
def advise_indicators(self, dataframe: DataFrame, pair: str) -> DataFrame:
|
||||||
|
"""
|
||||||
|
|
||||||
|
This wraps around the internal method
|
||||||
|
|
||||||
|
Populate indicators that will be used in the Buy and Sell strategy
|
||||||
|
:param dataframe: Raw data from the exchange and parsed by parse_ticker_dataframe()
|
||||||
|
:param pair: The currently traded pair
|
||||||
|
:return: a Dataframe with all mandatory indicators for the strategies
|
||||||
|
"""
|
||||||
|
return self.populate_indicators(dataframe)
|
||||||
|
|
||||||
|
def advise_buy(self, dataframe: DataFrame, pair: str) -> DataFrame:
|
||||||
|
"""
|
||||||
|
Based on TA indicators, populates the buy signal for the given dataframe
|
||||||
|
:param dataframe: DataFrame
|
||||||
|
:param pair: The currently traded pair
|
||||||
|
:return: DataFrame with buy column
|
||||||
|
"""
|
||||||
|
|
||||||
|
return self.populate_buy_trend(dataframe)
|
||||||
|
|
||||||
|
def advise_sell(self, dataframe: DataFrame, pair: str) -> DataFrame:
|
||||||
|
"""
|
||||||
|
Based on TA indicators, populates the sell signal for the given dataframe
|
||||||
|
:param dataframe: DataFrame
|
||||||
|
:param pair: The currently traded pair
|
||||||
|
:return: DataFrame with sell column
|
||||||
|
"""
|
||||||
|
return self.populate_sell_trend(dataframe)
|
||||||
|
@ -40,6 +40,7 @@ class StrategyResolver(object):
|
|||||||
self.strategy: IStrategy = self._load_strategy(strategy_name,
|
self.strategy: IStrategy = self._load_strategy(strategy_name,
|
||||||
extra_dir=config.get('strategy_path'))
|
extra_dir=config.get('strategy_path'))
|
||||||
|
|
||||||
|
|
||||||
# Set attributes
|
# Set attributes
|
||||||
# Check if we need to override configuration
|
# Check if we need to override configuration
|
||||||
if 'minimal_roi' in config:
|
if 'minimal_roi' in config:
|
||||||
@ -125,7 +126,7 @@ class StrategyResolver(object):
|
|||||||
|
|
||||||
strategy_name = os.path.splitext(name)[0]
|
strategy_name = os.path.splitext(name)[0]
|
||||||
|
|
||||||
print("stored downloaded stat at: {}".format(temp))
|
# print("stored downloaded stat at: {}".format(temp))
|
||||||
# register temp path with the bot
|
# register temp path with the bot
|
||||||
abs_paths.insert(0, temp.absolute())
|
abs_paths.insert(0, temp.absolute())
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ def load_dataframe_pair(pairs):
|
|||||||
dataframe = ld[pairs[0]]
|
dataframe = ld[pairs[0]]
|
||||||
|
|
||||||
analyze = Analyze({'strategy': 'DefaultStrategy'})
|
analyze = Analyze({'strategy': 'DefaultStrategy'})
|
||||||
dataframe = analyze.analyze_ticker(dataframe)
|
dataframe = analyze.analyze_ticker(dataframe, pairs[0])
|
||||||
return dataframe
|
return dataframe
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user