rename to buy_tag

This commit is contained in:
kevinjulian 2021-07-21 20:05:35 +07:00
parent db1e676639
commit 49886874aa
15 changed files with 47 additions and 47 deletions

View File

@ -114,7 +114,7 @@ class AwesomeStrategy(IStrategy):
See [Dataframe access](#dataframe-access) for more information about dataframe use in strategy callbacks. See [Dataframe access](#dataframe-access) for more information about dataframe use in strategy callbacks.
## Buy Signal Name ## Buy Tag
When your strategy has multiple buy signal, you can name it. When your strategy has multiple buy signal, you can name it.
Then you can access you buy signal on `custom_sell` Then you can access you buy signal on `custom_sell`
@ -126,7 +126,7 @@ def populate_buy_trend(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
(dataframe['rsi'] < 35) & (dataframe['rsi'] < 35) &
(dataframe['volume'] > 0) (dataframe['volume'] > 0)
), ),
['buy', 'buy_signal_name']] = 1, 'buy_signal_rsi' ['buy', 'buy_tag']] = 1, 'buy_signal_rsi'
return dataframe return dataframe
@ -134,7 +134,7 @@ def custom_sell(self, pair: str, trade: Trade, current_time: datetime, current_r
current_profit: float, **kwargs): current_profit: float, **kwargs):
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe) dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
last_candle = dataframe.iloc[-1].squeeze() last_candle = dataframe.iloc[-1].squeeze()
if trade.buy_signal_name == 'buy_signal_rsi' and last_candle['rsi'] > 80: if trade.buy_tag == 'buy_signal_rsi' and last_candle['rsi'] > 80:
return 'sell_signal_rsi' return 'sell_signal_rsi'
return None return None

View File

@ -30,7 +30,7 @@ BT_DATA_COLUMNS = ['pair', 'stake_amount', 'amount', 'open_date', 'close_date',
'fee_open', 'fee_close', 'trade_duration', 'fee_open', 'fee_close', 'trade_duration',
'profit_ratio', 'profit_abs', 'sell_reason', 'profit_ratio', 'profit_abs', 'sell_reason',
'initial_stop_loss_abs', 'initial_stop_loss_ratio', 'stop_loss_abs', 'initial_stop_loss_abs', 'initial_stop_loss_ratio', 'stop_loss_abs',
'stop_loss_ratio', 'min_rate', 'max_rate', 'is_open', 'buy_signal_name'] 'stop_loss_ratio', 'min_rate', 'max_rate', 'is_open', 'buy_tag']
def get_latest_optimize_filename(directory: Union[Path, str], variant: str) -> str: def get_latest_optimize_filename(directory: Union[Path, str], variant: str) -> str:

View File

@ -3,5 +3,5 @@ from freqtrade.enums.backteststate import BacktestState
from freqtrade.enums.rpcmessagetype import RPCMessageType from freqtrade.enums.rpcmessagetype import RPCMessageType
from freqtrade.enums.runmode import NON_UTIL_MODES, OPTIMIZE_MODES, TRADING_MODES, RunMode from freqtrade.enums.runmode import NON_UTIL_MODES, OPTIMIZE_MODES, TRADING_MODES, RunMode
from freqtrade.enums.selltype import SellType from freqtrade.enums.selltype import SellType
from freqtrade.enums.signaltype import SignalNameType, SignalType from freqtrade.enums.signaltype import SignalTagType, SignalType
from freqtrade.enums.state import State from freqtrade.enums.state import State

View File

@ -9,8 +9,8 @@ class SignalType(Enum):
SELL = "sell" SELL = "sell"
class SignalNameType(Enum): class SignalTagType(Enum):
""" """
Enum for signal columns Enum for signal columns
""" """
BUY_SIGNAL_NAME = "buy_signal_name" BUY_TAG = "buy_tag"

View File

@ -420,7 +420,7 @@ class FreqtradeBot(LoggingMixin):
return False return False
# running get_signal on historical data fetched # running get_signal on historical data fetched
(buy, sell, buy_signal_name) = self.strategy.get_signal( (buy, sell, buy_tag) = self.strategy.get_signal(
pair, pair,
self.strategy.timeframe, self.strategy.timeframe,
analyzed_df analyzed_df
@ -433,11 +433,11 @@ class FreqtradeBot(LoggingMixin):
if ((bid_check_dom.get('enabled', False)) and if ((bid_check_dom.get('enabled', False)) and
(bid_check_dom.get('bids_to_ask_delta', 0) > 0)): (bid_check_dom.get('bids_to_ask_delta', 0) > 0)):
if self._check_depth_of_market_buy(pair, bid_check_dom): if self._check_depth_of_market_buy(pair, bid_check_dom):
return self.execute_buy(pair, stake_amount, buy_signal_name=buy_signal_name) return self.execute_buy(pair, stake_amount, buy_tag=buy_tag)
else: else:
return False return False
return self.execute_buy(pair, stake_amount, buy_signal_name=buy_signal_name) return self.execute_buy(pair, stake_amount, buy_tag=buy_tag)
else: else:
return False return False
@ -466,7 +466,7 @@ class FreqtradeBot(LoggingMixin):
return False return False
def execute_buy(self, pair: str, stake_amount: float, price: Optional[float] = None, def execute_buy(self, pair: str, stake_amount: float, price: Optional[float] = None,
forcebuy: bool = False, buy_signal_name: str = '') -> bool: forcebuy: bool = False, buy_tag: str = '') -> bool:
""" """
Executes a limit buy for the given pair Executes a limit buy for the given pair
:param pair: pair for which we want to create a LIMIT_BUY :param pair: pair for which we want to create a LIMIT_BUY
@ -569,7 +569,7 @@ class FreqtradeBot(LoggingMixin):
exchange=self.exchange.id, exchange=self.exchange.id,
open_order_id=order_id, open_order_id=order_id,
strategy=self.strategy.get_strategy_name(), strategy=self.strategy.get_strategy_name(),
buy_signal_name=buy_signal_name, buy_tag=buy_tag,
timeframe=timeframe_to_minutes(self.config['timeframe']) timeframe=timeframe_to_minutes(self.config['timeframe'])
) )
trade.orders.append(order_obj) trade.orders.append(order_obj)

View File

@ -43,7 +43,7 @@ CLOSE_IDX = 3
SELL_IDX = 4 SELL_IDX = 4
LOW_IDX = 5 LOW_IDX = 5
HIGH_IDX = 6 HIGH_IDX = 6
BUY_SIGNAL_NAME_IDX = 7 buy_tag_IDX = 7
class Backtesting: class Backtesting:
@ -210,7 +210,7 @@ class Backtesting:
""" """
# Every change to this headers list must evaluate further usages of the resulting tuple # Every change to this headers list must evaluate further usages of the resulting tuple
# and eventually change the constants for indexes at the top # and eventually change the constants for indexes at the top
headers = ['date', 'buy', 'open', 'close', 'sell', 'low', 'high', 'buy_signal_name'] headers = ['date', 'buy', 'open', 'close', 'sell', 'low', 'high', 'buy_tag']
data: Dict = {} data: Dict = {}
self.progress.init_step(BacktestState.CONVERT, len(processed)) self.progress.init_step(BacktestState.CONVERT, len(processed))
@ -221,7 +221,7 @@ class Backtesting:
if not pair_data.empty: if not pair_data.empty:
pair_data.loc[:, 'buy'] = 0 # cleanup if buy_signal is exist pair_data.loc[:, 'buy'] = 0 # cleanup if buy_signal is exist
pair_data.loc[:, 'sell'] = 0 # cleanup if sell_signal is exist pair_data.loc[:, 'sell'] = 0 # cleanup if sell_signal is exist
pair_data.loc[:, 'buy_signal_name'] = '' # cleanup if buy_signal_name is exist pair_data.loc[:, 'buy_tag'] = '' # cleanup if buy_tag is exist
df_analyzed = self.strategy.advise_sell( df_analyzed = self.strategy.advise_sell(
self.strategy.advise_buy(pair_data, {'pair': pair}), {'pair': pair})[headers].copy() self.strategy.advise_buy(pair_data, {'pair': pair}), {'pair': pair})[headers].copy()
@ -230,7 +230,7 @@ class Backtesting:
# from the previous candle # from the previous candle
df_analyzed.loc[:, 'buy'] = df_analyzed.loc[:, 'buy'].shift(1) df_analyzed.loc[:, 'buy'] = df_analyzed.loc[:, 'buy'].shift(1)
df_analyzed.loc[:, 'sell'] = df_analyzed.loc[:, 'sell'].shift(1) df_analyzed.loc[:, 'sell'] = df_analyzed.loc[:, 'sell'].shift(1)
df_analyzed.loc[:, 'buy_signal_name'] = df_analyzed.loc[:, 'buy_signal_name'].shift(1) df_analyzed.loc[:, 'buy_tag'] = df_analyzed.loc[:, 'buy_tag'].shift(1)
df_analyzed.drop(df_analyzed.head(1).index, inplace=True) df_analyzed.drop(df_analyzed.head(1).index, inplace=True)
@ -370,7 +370,7 @@ class Backtesting:
fee_open=self.fee, fee_open=self.fee,
fee_close=self.fee, fee_close=self.fee,
is_open=True, is_open=True,
buy_signal_name=row[BUY_SIGNAL_NAME_IDX], buy_tag=row[buy_tag_IDX],
exchange='backtesting', exchange='backtesting',
) )
return trade return trade

View File

@ -47,7 +47,7 @@ def migrate_trades_table(decl_base, inspector, engine, table_back_name: str, col
min_rate = get_column_def(cols, 'min_rate', 'null') min_rate = get_column_def(cols, 'min_rate', 'null')
sell_reason = get_column_def(cols, 'sell_reason', 'null') sell_reason = get_column_def(cols, 'sell_reason', 'null')
strategy = get_column_def(cols, 'strategy', 'null') strategy = get_column_def(cols, 'strategy', 'null')
buy_signal_name = get_column_def(cols, 'buy_signal_name', 'null') buy_tag = get_column_def(cols, 'buy_tag', 'null')
# If ticker-interval existed use that, else null. # If ticker-interval existed use that, else null.
if has_column(cols, 'ticker_interval'): if has_column(cols, 'ticker_interval'):
timeframe = get_column_def(cols, 'timeframe', 'ticker_interval') timeframe = get_column_def(cols, 'timeframe', 'ticker_interval')
@ -81,7 +81,7 @@ def migrate_trades_table(decl_base, inspector, engine, table_back_name: str, col
stake_amount, amount, amount_requested, open_date, close_date, open_order_id, stake_amount, amount, amount_requested, open_date, close_date, open_order_id,
stop_loss, stop_loss_pct, initial_stop_loss, initial_stop_loss_pct, stop_loss, stop_loss_pct, initial_stop_loss, initial_stop_loss_pct,
stoploss_order_id, stoploss_last_update, stoploss_order_id, stoploss_last_update,
max_rate, min_rate, sell_reason, sell_order_status, strategy, buy_signal_name, max_rate, min_rate, sell_reason, sell_order_status, strategy, buy_tag,
timeframe, open_trade_value, close_profit_abs timeframe, open_trade_value, close_profit_abs
) )
select id, lower(exchange), select id, lower(exchange),
@ -104,7 +104,7 @@ def migrate_trades_table(decl_base, inspector, engine, table_back_name: str, col
{stoploss_order_id} stoploss_order_id, {stoploss_last_update} stoploss_last_update, {stoploss_order_id} stoploss_order_id, {stoploss_last_update} stoploss_last_update,
{max_rate} max_rate, {min_rate} min_rate, {sell_reason} sell_reason, {max_rate} max_rate, {min_rate} min_rate, {sell_reason} sell_reason,
{sell_order_status} sell_order_status, {sell_order_status} sell_order_status,
{strategy} strategy, {buy_signal_name} buy_signal_name, {timeframe} timeframe, {strategy} strategy, {buy_tag} buy_tag, {timeframe} timeframe,
{open_trade_value} open_trade_value, {close_profit_abs} close_profit_abs {open_trade_value} open_trade_value, {close_profit_abs} close_profit_abs
from {table_back_name} from {table_back_name}
""")) """))
@ -168,7 +168,7 @@ def check_migrate(engine, decl_base, previous_tables) -> None:
inspector = inspect(engine) inspector = inspect(engine)
cols = inspector.get_columns('trades') cols = inspector.get_columns('trades')
if not has_column(cols, 'buy_signal_name'): if not has_column(cols, 'buy_tag'):
logger.info(f'Running database migration for trades - backup: {table_back_name}') logger.info(f'Running database migration for trades - backup: {table_back_name}')
migrate_trades_table(decl_base, inspector, engine, table_back_name, cols) migrate_trades_table(decl_base, inspector, engine, table_back_name, cols)
# Reread columns - the above recreated the table! # Reread columns - the above recreated the table!

View File

@ -257,7 +257,7 @@ class LocalTrade():
sell_reason: str = '' sell_reason: str = ''
sell_order_status: str = '' sell_order_status: str = ''
strategy: str = '' strategy: str = ''
buy_signal_name: str = '' buy_tag: str = ''
timeframe: Optional[int] = None timeframe: Optional[int] = None
def __init__(self, **kwargs): def __init__(self, **kwargs):
@ -289,7 +289,7 @@ class LocalTrade():
'amount_requested': round(self.amount_requested, 8) if self.amount_requested else None, 'amount_requested': round(self.amount_requested, 8) if self.amount_requested else None,
'stake_amount': round(self.stake_amount, 8), 'stake_amount': round(self.stake_amount, 8),
'strategy': self.strategy, 'strategy': self.strategy,
'buy_signal_name': self.buy_signal_name, 'buy_tag': self.buy_tag,
'timeframe': self.timeframe, 'timeframe': self.timeframe,
'fee_open': self.fee_open, 'fee_open': self.fee_open,
@ -705,7 +705,7 @@ class Trade(_DECL_BASE, LocalTrade):
sell_reason = Column(String(100), nullable=True) sell_reason = Column(String(100), nullable=True)
sell_order_status = Column(String(100), nullable=True) sell_order_status = Column(String(100), nullable=True)
strategy = Column(String(100), nullable=True) strategy = Column(String(100), nullable=True)
buy_signal_name = Column(String(100), nullable=True) buy_tag = Column(String(100), nullable=True)
timeframe = Column(Integer, nullable=True) timeframe = Column(Integer, nullable=True)
def __init__(self, **kwargs): def __init__(self, **kwargs):

View File

@ -13,7 +13,7 @@ from pandas import DataFrame
from freqtrade.constants import ListPairsWithTimeframes from freqtrade.constants import ListPairsWithTimeframes
from freqtrade.data.dataprovider import DataProvider from freqtrade.data.dataprovider import DataProvider
from freqtrade.enums import SellType, SignalNameType, SignalType from freqtrade.enums import SellType, SignalTagType, SignalType
from freqtrade.exceptions import OperationalException, StrategyError from freqtrade.exceptions import OperationalException, StrategyError
from freqtrade.exchange import timeframe_to_minutes, timeframe_to_seconds from freqtrade.exchange import timeframe_to_minutes, timeframe_to_seconds
from freqtrade.exchange.exchange import timeframe_to_next_date from freqtrade.exchange.exchange import timeframe_to_next_date
@ -422,7 +422,7 @@ class IStrategy(ABC, HyperStrategyMixin):
logger.debug("Skipping TA Analysis for already analyzed candle") logger.debug("Skipping TA Analysis for already analyzed candle")
dataframe['buy'] = 0 dataframe['buy'] = 0
dataframe['sell'] = 0 dataframe['sell'] = 0
dataframe['buy_signal_name'] = '' dataframe['buy_tag'] = ''
# Other Defs in strategy that want to be called every loop here # Other Defs in strategy that want to be called every loop here
# twitter_sell = self.watch_twitter_feed(dataframe, metadata) # twitter_sell = self.watch_twitter_feed(dataframe, metadata)
@ -525,9 +525,9 @@ class IStrategy(ABC, HyperStrategyMixin):
) )
return False, False, '' return False, False, ''
(buy, sell, buy_signal_name) = latest[SignalType.BUY.value] == 1,\ (buy, sell, buy_tag) = latest[SignalType.BUY.value] == 1,\
latest[SignalType.SELL.value] == 1,\ latest[SignalType.SELL.value] == 1,\
latest.get(SignalNameType.BUY_SIGNAL_NAME.value, '') latest.get(SignalTagType.BUY_TAG.value, '')
logger.debug('trigger: %s (pair=%s) buy=%s sell=%s', logger.debug('trigger: %s (pair=%s) buy=%s sell=%s',
latest['date'], pair, str(buy), str(sell)) latest['date'], pair, str(buy), str(sell))
timeframe_seconds = timeframe_to_seconds(timeframe) timeframe_seconds = timeframe_to_seconds(timeframe)
@ -535,8 +535,8 @@ class IStrategy(ABC, HyperStrategyMixin):
current_time=datetime.now(timezone.utc), current_time=datetime.now(timezone.utc),
timeframe_seconds=timeframe_seconds, timeframe_seconds=timeframe_seconds,
buy=buy): buy=buy):
return False, sell, buy_signal_name return False, sell, buy_tag
return buy, sell, buy_signal_name return buy, sell, buy_tag
def ignore_expired_candle(self, latest_date: datetime, current_time: datetime, def ignore_expired_candle(self, latest_date: datetime, current_time: datetime,
timeframe_seconds: int, buy: bool): timeframe_seconds: int, buy: bool):

View File

@ -18,7 +18,7 @@ class BTrade(NamedTuple):
sell_reason: SellType sell_reason: SellType
open_tick: int open_tick: int
close_tick: int close_tick: int
buy_signal_name: Optional[str] = '' buy_tag: Optional[str] = ''
class BTContainer(NamedTuple): class BTContainer(NamedTuple):
@ -44,7 +44,7 @@ def _get_frame_time_from_offset(offset):
def _build_backtest_dataframe(data): def _build_backtest_dataframe(data):
columns = ['date', 'open', 'high', 'low', 'close', 'volume', 'buy', 'sell', 'buy_signal_name'] columns = ['date', 'open', 'high', 'low', 'close', 'volume', 'buy', 'sell', 'buy_tag']
frame = DataFrame.from_records(data, columns=columns) frame = DataFrame.from_records(data, columns=columns)
frame['date'] = frame['date'].apply(_get_frame_time_from_offset) frame['date'] = frame['date'].apply(_get_frame_time_from_offset)

View File

@ -532,7 +532,7 @@ tc33 = BTContainer(data=[
sell_reason=SellType.TRAILING_STOP_LOSS, sell_reason=SellType.TRAILING_STOP_LOSS,
open_tick=1, open_tick=1,
close_tick=1, close_tick=1,
buy_signal_name='buy_signal_01' buy_tag='buy_signal_01'
)] )]
) )
@ -619,6 +619,6 @@ def test_backtest_results(default_conf, fee, mocker, caplog, data) -> None:
for c, trade in enumerate(data.trades): for c, trade in enumerate(data.trades):
res = results.iloc[c] res = results.iloc[c]
assert res.sell_reason == trade.sell_reason.value assert res.sell_reason == trade.sell_reason.value
assert res.buy_signal_name == trade.buy_signal_name assert res.buy_tag == trade.buy_tag
assert res.open_date == _get_frame_time_from_offset(trade.open_tick) assert res.open_date == _get_frame_time_from_offset(trade.open_tick)
assert res.close_date == _get_frame_time_from_offset(trade.close_tick) assert res.close_date == _get_frame_time_from_offset(trade.close_tick)

View File

@ -584,7 +584,7 @@ def test_backtest_one(default_conf, fee, mocker, testdatadir) -> None:
'min_rate': [0.1038, 0.10302485], 'min_rate': [0.1038, 0.10302485],
'max_rate': [0.10501, 0.1038888], 'max_rate': [0.10501, 0.1038888],
'is_open': [False, False], 'is_open': [False, False],
'buy_signal_name': ['', ''], 'buy_tag': ['', ''],
}) })
pd.testing.assert_frame_equal(results, expected) pd.testing.assert_frame_equal(results, expected)
data_pair = processed[pair] data_pair = processed[pair]

View File

@ -69,7 +69,7 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None:
'min_rate': ANY, 'min_rate': ANY,
'max_rate': ANY, 'max_rate': ANY,
'strategy': ANY, 'strategy': ANY,
'buy_signal_name': ANY, 'buy_tag': ANY,
'timeframe': 5, 'timeframe': 5,
'open_order_id': ANY, 'open_order_id': ANY,
'close_date': None, 'close_date': None,
@ -136,7 +136,7 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None:
'min_rate': ANY, 'min_rate': ANY,
'max_rate': ANY, 'max_rate': ANY,
'strategy': ANY, 'strategy': ANY,
'buy_signal_name': ANY, 'buy_tag': ANY,
'timeframe': ANY, 'timeframe': ANY,
'open_order_id': ANY, 'open_order_id': ANY,
'close_date': None, 'close_date': None,

View File

@ -49,7 +49,7 @@ def test_returns_latest_signal(mocker, default_conf, ohlcv_history):
assert _STRATEGY.get_signal('ETH/BTC', '5m', mocked_history) == (False, False, '') assert _STRATEGY.get_signal('ETH/BTC', '5m', mocked_history) == (False, False, '')
mocked_history.loc[1, 'sell'] = 0 mocked_history.loc[1, 'sell'] = 0
mocked_history.loc[1, 'buy'] = 1 mocked_history.loc[1, 'buy'] = 1
mocked_history.loc[1, 'buy_signal_name'] = 'buy_signal_01' mocked_history.loc[1, 'buy_tag'] = 'buy_signal_01'
assert _STRATEGY.get_signal('ETH/BTC', '5m', mocked_history) == (True, False, 'buy_signal_01') assert _STRATEGY.get_signal('ETH/BTC', '5m', mocked_history) == (True, False, 'buy_signal_01')

View File

@ -861,7 +861,7 @@ def test_to_json(default_conf, fee):
open_date=arrow.utcnow().shift(hours=-2).datetime, open_date=arrow.utcnow().shift(hours=-2).datetime,
open_rate=0.123, open_rate=0.123,
exchange='binance', exchange='binance',
buy_signal_name='', buy_tag='',
open_order_id='dry_run_buy_12345' open_order_id='dry_run_buy_12345'
) )
result = trade.to_json() result = trade.to_json()
@ -911,7 +911,7 @@ def test_to_json(default_conf, fee):
'min_rate': None, 'min_rate': None,
'max_rate': None, 'max_rate': None,
'strategy': None, 'strategy': None,
'buy_signal_name': '', 'buy_tag': '',
'timeframe': None, 'timeframe': None,
'exchange': 'binance', 'exchange': 'binance',
} }
@ -928,7 +928,7 @@ def test_to_json(default_conf, fee):
close_date=arrow.utcnow().shift(hours=-1).datetime, close_date=arrow.utcnow().shift(hours=-1).datetime,
open_rate=0.123, open_rate=0.123,
close_rate=0.125, close_rate=0.125,
buy_signal_name='buys_signal_001', buy_tag='buys_signal_001',
exchange='binance', exchange='binance',
) )
result = trade.to_json() result = trade.to_json()
@ -978,7 +978,7 @@ def test_to_json(default_conf, fee):
'sell_reason': None, 'sell_reason': None,
'sell_order_status': None, 'sell_order_status': None,
'strategy': None, 'strategy': None,
'buy_signal_name': 'buys_signal_001', 'buy_tag': 'buys_signal_001',
'timeframe': None, 'timeframe': None,
'exchange': 'binance', 'exchange': 'binance',
} }