mirror of
https://github.com/freqtrade/freqtrade.git
synced 2024-11-10 10:21:59 +00:00
rename to buy_tag
This commit is contained in:
parent
db1e676639
commit
49886874aa
|
@ -114,7 +114,7 @@ class AwesomeStrategy(IStrategy):
|
|||
|
||||
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.
|
||||
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['volume'] > 0)
|
||||
),
|
||||
['buy', 'buy_signal_name']] = 1, 'buy_signal_rsi'
|
||||
['buy', 'buy_tag']] = 1, 'buy_signal_rsi'
|
||||
|
||||
return dataframe
|
||||
|
||||
|
@ -134,7 +134,7 @@ def custom_sell(self, pair: str, trade: Trade, current_time: datetime, current_r
|
|||
current_profit: float, **kwargs):
|
||||
dataframe, _ = self.dp.get_analyzed_dataframe(pair, self.timeframe)
|
||||
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 None
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ BT_DATA_COLUMNS = ['pair', 'stake_amount', 'amount', 'open_date', 'close_date',
|
|||
'fee_open', 'fee_close', 'trade_duration',
|
||||
'profit_ratio', 'profit_abs', 'sell_reason',
|
||||
'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:
|
||||
|
|
|
@ -3,5 +3,5 @@ from freqtrade.enums.backteststate import BacktestState
|
|||
from freqtrade.enums.rpcmessagetype import RPCMessageType
|
||||
from freqtrade.enums.runmode import NON_UTIL_MODES, OPTIMIZE_MODES, TRADING_MODES, RunMode
|
||||
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
|
||||
|
|
|
@ -9,8 +9,8 @@ class SignalType(Enum):
|
|||
SELL = "sell"
|
||||
|
||||
|
||||
class SignalNameType(Enum):
|
||||
class SignalTagType(Enum):
|
||||
"""
|
||||
Enum for signal columns
|
||||
"""
|
||||
BUY_SIGNAL_NAME = "buy_signal_name"
|
||||
BUY_TAG = "buy_tag"
|
||||
|
|
|
@ -420,7 +420,7 @@ class FreqtradeBot(LoggingMixin):
|
|||
return False
|
||||
|
||||
# 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,
|
||||
self.strategy.timeframe,
|
||||
analyzed_df
|
||||
|
@ -431,13 +431,13 @@ class FreqtradeBot(LoggingMixin):
|
|||
|
||||
bid_check_dom = self.config.get('bid_strategy', {}).get('check_depth_of_market', {})
|
||||
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):
|
||||
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:
|
||||
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:
|
||||
return False
|
||||
|
||||
|
@ -466,7 +466,7 @@ class FreqtradeBot(LoggingMixin):
|
|||
return False
|
||||
|
||||
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
|
||||
:param pair: pair for which we want to create a LIMIT_BUY
|
||||
|
@ -569,7 +569,7 @@ class FreqtradeBot(LoggingMixin):
|
|||
exchange=self.exchange.id,
|
||||
open_order_id=order_id,
|
||||
strategy=self.strategy.get_strategy_name(),
|
||||
buy_signal_name=buy_signal_name,
|
||||
buy_tag=buy_tag,
|
||||
timeframe=timeframe_to_minutes(self.config['timeframe'])
|
||||
)
|
||||
trade.orders.append(order_obj)
|
||||
|
|
|
@ -43,7 +43,7 @@ CLOSE_IDX = 3
|
|||
SELL_IDX = 4
|
||||
LOW_IDX = 5
|
||||
HIGH_IDX = 6
|
||||
BUY_SIGNAL_NAME_IDX = 7
|
||||
buy_tag_IDX = 7
|
||||
|
||||
|
||||
class Backtesting:
|
||||
|
@ -210,7 +210,7 @@ class Backtesting:
|
|||
"""
|
||||
# Every change to this headers list must evaluate further usages of the resulting tuple
|
||||
# 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 = {}
|
||||
self.progress.init_step(BacktestState.CONVERT, len(processed))
|
||||
|
||||
|
@ -221,7 +221,7 @@ class Backtesting:
|
|||
if not pair_data.empty:
|
||||
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[:, '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(
|
||||
self.strategy.advise_buy(pair_data, {'pair': pair}), {'pair': pair})[headers].copy()
|
||||
|
@ -230,7 +230,7 @@ class Backtesting:
|
|||
# from the previous candle
|
||||
df_analyzed.loc[:, 'buy'] = df_analyzed.loc[:, 'buy'].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)
|
||||
|
||||
|
@ -265,7 +265,7 @@ class Backtesting:
|
|||
# Worst case: price reaches stop_positive_offset and dives down.
|
||||
stop_rate = (sell_row[OPEN_IDX] *
|
||||
(1 + abs(self.strategy.trailing_stop_positive_offset) -
|
||||
abs(self.strategy.trailing_stop_positive)))
|
||||
abs(self.strategy.trailing_stop_positive)))
|
||||
else:
|
||||
# Worst case: price ticks tiny bit above open and dives down.
|
||||
stop_rate = sell_row[OPEN_IDX] * (1 - abs(trade.stop_loss_pct))
|
||||
|
@ -370,7 +370,7 @@ class Backtesting:
|
|||
fee_open=self.fee,
|
||||
fee_close=self.fee,
|
||||
is_open=True,
|
||||
buy_signal_name=row[BUY_SIGNAL_NAME_IDX],
|
||||
buy_tag=row[buy_tag_IDX],
|
||||
exchange='backtesting',
|
||||
)
|
||||
return trade
|
||||
|
|
|
@ -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')
|
||||
sell_reason = get_column_def(cols, 'sell_reason', '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 has_column(cols, '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,
|
||||
stop_loss, stop_loss_pct, initial_stop_loss, initial_stop_loss_pct,
|
||||
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
|
||||
)
|
||||
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,
|
||||
{max_rate} max_rate, {min_rate} min_rate, {sell_reason} sell_reason,
|
||||
{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
|
||||
from {table_back_name}
|
||||
"""))
|
||||
|
@ -168,7 +168,7 @@ def check_migrate(engine, decl_base, previous_tables) -> None:
|
|||
inspector = inspect(engine)
|
||||
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}')
|
||||
migrate_trades_table(decl_base, inspector, engine, table_back_name, cols)
|
||||
# Reread columns - the above recreated the table!
|
||||
|
|
|
@ -257,7 +257,7 @@ class LocalTrade():
|
|||
sell_reason: str = ''
|
||||
sell_order_status: str = ''
|
||||
strategy: str = ''
|
||||
buy_signal_name: str = ''
|
||||
buy_tag: str = ''
|
||||
timeframe: Optional[int] = None
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
|
@ -289,7 +289,7 @@ class LocalTrade():
|
|||
'amount_requested': round(self.amount_requested, 8) if self.amount_requested else None,
|
||||
'stake_amount': round(self.stake_amount, 8),
|
||||
'strategy': self.strategy,
|
||||
'buy_signal_name': self.buy_signal_name,
|
||||
'buy_tag': self.buy_tag,
|
||||
'timeframe': self.timeframe,
|
||||
|
||||
'fee_open': self.fee_open,
|
||||
|
@ -638,7 +638,7 @@ class LocalTrade():
|
|||
|
||||
# skip case if trailing-stop changed the stoploss already.
|
||||
if (trade.stop_loss == trade.initial_stop_loss
|
||||
and trade.initial_stop_loss_pct != desired_stoploss):
|
||||
and trade.initial_stop_loss_pct != desired_stoploss):
|
||||
# Stoploss value got changed
|
||||
|
||||
logger.info(f"Stoploss for {trade} needs adjustment...")
|
||||
|
@ -705,7 +705,7 @@ class Trade(_DECL_BASE, LocalTrade):
|
|||
sell_reason = Column(String(100), nullable=True)
|
||||
sell_order_status = 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)
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
|
|
|
@ -13,7 +13,7 @@ from pandas import DataFrame
|
|||
|
||||
from freqtrade.constants import ListPairsWithTimeframes
|
||||
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.exchange import timeframe_to_minutes, timeframe_to_seconds
|
||||
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")
|
||||
dataframe['buy'] = 0
|
||||
dataframe['sell'] = 0
|
||||
dataframe['buy_signal_name'] = ''
|
||||
dataframe['buy_tag'] = ''
|
||||
|
||||
# Other Defs in strategy that want to be called every loop here
|
||||
# twitter_sell = self.watch_twitter_feed(dataframe, metadata)
|
||||
|
@ -525,9 +525,9 @@ class IStrategy(ABC, HyperStrategyMixin):
|
|||
)
|
||||
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.get(SignalNameType.BUY_SIGNAL_NAME.value, '')
|
||||
latest.get(SignalTagType.BUY_TAG.value, '')
|
||||
logger.debug('trigger: %s (pair=%s) buy=%s sell=%s',
|
||||
latest['date'], pair, str(buy), str(sell))
|
||||
timeframe_seconds = timeframe_to_seconds(timeframe)
|
||||
|
@ -535,8 +535,8 @@ class IStrategy(ABC, HyperStrategyMixin):
|
|||
current_time=datetime.now(timezone.utc),
|
||||
timeframe_seconds=timeframe_seconds,
|
||||
buy=buy):
|
||||
return False, sell, buy_signal_name
|
||||
return buy, sell, buy_signal_name
|
||||
return False, sell, buy_tag
|
||||
return buy, sell, buy_tag
|
||||
|
||||
def ignore_expired_candle(self, latest_date: datetime, current_time: datetime,
|
||||
timeframe_seconds: int, buy: bool):
|
||||
|
|
|
@ -18,7 +18,7 @@ class BTrade(NamedTuple):
|
|||
sell_reason: SellType
|
||||
open_tick: int
|
||||
close_tick: int
|
||||
buy_signal_name: Optional[str] = ''
|
||||
buy_tag: Optional[str] = ''
|
||||
|
||||
|
||||
class BTContainer(NamedTuple):
|
||||
|
@ -44,7 +44,7 @@ def _get_frame_time_from_offset(offset):
|
|||
|
||||
|
||||
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['date'] = frame['date'].apply(_get_frame_time_from_offset)
|
||||
|
|
|
@ -532,7 +532,7 @@ tc33 = BTContainer(data=[
|
|||
sell_reason=SellType.TRAILING_STOP_LOSS,
|
||||
open_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):
|
||||
res = results.iloc[c]
|
||||
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.close_date == _get_frame_time_from_offset(trade.close_tick)
|
||||
|
|
|
@ -584,7 +584,7 @@ def test_backtest_one(default_conf, fee, mocker, testdatadir) -> None:
|
|||
'min_rate': [0.1038, 0.10302485],
|
||||
'max_rate': [0.10501, 0.1038888],
|
||||
'is_open': [False, False],
|
||||
'buy_signal_name': ['', ''],
|
||||
'buy_tag': ['', ''],
|
||||
})
|
||||
pd.testing.assert_frame_equal(results, expected)
|
||||
data_pair = processed[pair]
|
||||
|
@ -859,7 +859,7 @@ def test_backtest_start_multi_strat(default_conf, mocker, caplog, testdatadir):
|
|||
'locks': [],
|
||||
'rejected_signals': 20,
|
||||
'final_balance': 1000,
|
||||
})
|
||||
})
|
||||
mocker.patch('freqtrade.plugins.pairlistmanager.PairListManager.whitelist',
|
||||
PropertyMock(return_value=['UNITTEST/BTC']))
|
||||
mocker.patch('freqtrade.optimize.backtesting.Backtesting.backtest', backtestmock)
|
||||
|
|
|
@ -69,7 +69,7 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None:
|
|||
'min_rate': ANY,
|
||||
'max_rate': ANY,
|
||||
'strategy': ANY,
|
||||
'buy_signal_name': ANY,
|
||||
'buy_tag': ANY,
|
||||
'timeframe': 5,
|
||||
'open_order_id': ANY,
|
||||
'close_date': None,
|
||||
|
@ -136,7 +136,7 @@ def test_rpc_trade_status(default_conf, ticker, fee, mocker) -> None:
|
|||
'min_rate': ANY,
|
||||
'max_rate': ANY,
|
||||
'strategy': ANY,
|
||||
'buy_signal_name': ANY,
|
||||
'buy_tag': ANY,
|
||||
'timeframe': ANY,
|
||||
'open_order_id': ANY,
|
||||
'close_date': None,
|
||||
|
|
|
@ -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, '')
|
||||
mocked_history.loc[1, 'sell'] = 0
|
||||
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')
|
||||
|
||||
|
|
|
@ -861,7 +861,7 @@ def test_to_json(default_conf, fee):
|
|||
open_date=arrow.utcnow().shift(hours=-2).datetime,
|
||||
open_rate=0.123,
|
||||
exchange='binance',
|
||||
buy_signal_name='',
|
||||
buy_tag='',
|
||||
open_order_id='dry_run_buy_12345'
|
||||
)
|
||||
result = trade.to_json()
|
||||
|
@ -911,7 +911,7 @@ def test_to_json(default_conf, fee):
|
|||
'min_rate': None,
|
||||
'max_rate': None,
|
||||
'strategy': None,
|
||||
'buy_signal_name': '',
|
||||
'buy_tag': '',
|
||||
'timeframe': None,
|
||||
'exchange': 'binance',
|
||||
}
|
||||
|
@ -928,7 +928,7 @@ def test_to_json(default_conf, fee):
|
|||
close_date=arrow.utcnow().shift(hours=-1).datetime,
|
||||
open_rate=0.123,
|
||||
close_rate=0.125,
|
||||
buy_signal_name='buys_signal_001',
|
||||
buy_tag='buys_signal_001',
|
||||
exchange='binance',
|
||||
)
|
||||
result = trade.to_json()
|
||||
|
@ -978,7 +978,7 @@ def test_to_json(default_conf, fee):
|
|||
'sell_reason': None,
|
||||
'sell_order_status': None,
|
||||
'strategy': None,
|
||||
'buy_signal_name': 'buys_signal_001',
|
||||
'buy_tag': 'buys_signal_001',
|
||||
'timeframe': None,
|
||||
'exchange': 'binance',
|
||||
}
|
||||
|
@ -1323,7 +1323,7 @@ def test_Trade_object_idem():
|
|||
'get_open_trades_without_assigned_fees',
|
||||
'get_open_order_trades',
|
||||
'get_trades',
|
||||
)
|
||||
)
|
||||
|
||||
# Parent (LocalTrade) should have the same attributes
|
||||
for item in trade:
|
||||
|
|
Loading…
Reference in New Issue
Block a user