Merge pull request #8040 from xmatthias/mypy_fixes
Enable mypy defaults for Optional typechecking
This commit is contained in:
commit
95987663f4
@ -28,7 +28,7 @@ class Configuration:
|
|||||||
Reuse this class for the bot, backtesting, hyperopt and every script that required configuration
|
Reuse this class for the bot, backtesting, hyperopt and every script that required configuration
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, args: Dict[str, Any], runmode: RunMode = None) -> None:
|
def __init__(self, args: Dict[str, Any], runmode: Optional[RunMode] = None) -> None:
|
||||||
self.args = args
|
self.args = args
|
||||||
self.config: Optional[Config] = None
|
self.config: Optional[Config] = None
|
||||||
self.runmode = runmode
|
self.runmode = runmode
|
||||||
|
@ -6,7 +6,7 @@ import re
|
|||||||
import sys
|
import sys
|
||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Dict, List
|
from typing import Any, Dict, List, Optional
|
||||||
|
|
||||||
import rapidjson
|
import rapidjson
|
||||||
|
|
||||||
@ -75,7 +75,8 @@ def load_config_file(path: str) -> Dict[str, Any]:
|
|||||||
return config
|
return config
|
||||||
|
|
||||||
|
|
||||||
def load_from_files(files: List[str], base_path: Path = None, level: int = 0) -> Dict[str, Any]:
|
def load_from_files(
|
||||||
|
files: List[str], base_path: Optional[Path] = None, level: int = 0) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
Recursively load configuration files if specified.
|
Recursively load configuration files if specified.
|
||||||
Sub-files are assumed to be relative to the initial config.
|
Sub-files are assumed to be relative to the initial config.
|
||||||
|
@ -90,7 +90,8 @@ def get_latest_hyperopt_filename(directory: Union[Path, str]) -> str:
|
|||||||
return 'hyperopt_results.pickle'
|
return 'hyperopt_results.pickle'
|
||||||
|
|
||||||
|
|
||||||
def get_latest_hyperopt_file(directory: Union[Path, str], predef_filename: str = None) -> Path:
|
def get_latest_hyperopt_file(
|
||||||
|
directory: Union[Path, str], predef_filename: Optional[str] = None) -> Path:
|
||||||
"""
|
"""
|
||||||
Get latest hyperopt export based on '.last_result.json'.
|
Get latest hyperopt export based on '.last_result.json'.
|
||||||
:param directory: Directory to search for last result
|
:param directory: Directory to search for last result
|
||||||
@ -193,7 +194,7 @@ def get_backtest_resultlist(dirname: Path):
|
|||||||
|
|
||||||
|
|
||||||
def find_existing_backtest_stats(dirname: Union[Path, str], run_ids: Dict[str, str],
|
def find_existing_backtest_stats(dirname: Union[Path, str], run_ids: Dict[str, str],
|
||||||
min_backtest_date: datetime = None) -> Dict[str, Any]:
|
min_backtest_date: Optional[datetime] = None) -> Dict[str, Any]:
|
||||||
"""
|
"""
|
||||||
Find existing backtest stats that match specified run IDs and load them.
|
Find existing backtest stats that match specified run IDs and load them.
|
||||||
:param dirname: pathlib.Path object, or string pointing to the file.
|
:param dirname: pathlib.Path object, or string pointing to the file.
|
||||||
|
@ -281,7 +281,7 @@ class DataProvider:
|
|||||||
def historic_ohlcv(
|
def historic_ohlcv(
|
||||||
self,
|
self,
|
||||||
pair: str,
|
pair: str,
|
||||||
timeframe: str = None,
|
timeframe: Optional[str] = None,
|
||||||
candle_type: str = ''
|
candle_type: str = ''
|
||||||
) -> DataFrame:
|
) -> DataFrame:
|
||||||
"""
|
"""
|
||||||
@ -333,7 +333,7 @@ class DataProvider:
|
|||||||
def get_pair_dataframe(
|
def get_pair_dataframe(
|
||||||
self,
|
self,
|
||||||
pair: str,
|
pair: str,
|
||||||
timeframe: str = None,
|
timeframe: Optional[str] = None,
|
||||||
candle_type: str = ''
|
candle_type: str = ''
|
||||||
) -> DataFrame:
|
) -> DataFrame:
|
||||||
"""
|
"""
|
||||||
@ -415,7 +415,7 @@ class DataProvider:
|
|||||||
|
|
||||||
def refresh(self,
|
def refresh(self,
|
||||||
pairlist: ListPairsWithTimeframes,
|
pairlist: ListPairsWithTimeframes,
|
||||||
helping_pairs: ListPairsWithTimeframes = None) -> None:
|
helping_pairs: Optional[ListPairsWithTimeframes] = None) -> None:
|
||||||
"""
|
"""
|
||||||
Refresh data, called with each cycle
|
Refresh data, called with each cycle
|
||||||
"""
|
"""
|
||||||
@ -439,7 +439,7 @@ class DataProvider:
|
|||||||
def ohlcv(
|
def ohlcv(
|
||||||
self,
|
self,
|
||||||
pair: str,
|
pair: str,
|
||||||
timeframe: str = None,
|
timeframe: Optional[str] = None,
|
||||||
copy: bool = True,
|
copy: bool = True,
|
||||||
candle_type: str = ''
|
candle_type: str = ''
|
||||||
) -> DataFrame:
|
) -> DataFrame:
|
||||||
|
@ -28,8 +28,8 @@ def load_pair_history(pair: str,
|
|||||||
fill_up_missing: bool = True,
|
fill_up_missing: bool = True,
|
||||||
drop_incomplete: bool = False,
|
drop_incomplete: bool = False,
|
||||||
startup_candles: int = 0,
|
startup_candles: int = 0,
|
||||||
data_format: str = None,
|
data_format: Optional[str] = None,
|
||||||
data_handler: IDataHandler = None,
|
data_handler: Optional[IDataHandler] = None,
|
||||||
candle_type: CandleType = CandleType.SPOT
|
candle_type: CandleType = CandleType.SPOT
|
||||||
) -> DataFrame:
|
) -> DataFrame:
|
||||||
"""
|
"""
|
||||||
@ -69,7 +69,7 @@ def load_data(datadir: Path,
|
|||||||
fail_without_data: bool = False,
|
fail_without_data: bool = False,
|
||||||
data_format: str = 'json',
|
data_format: str = 'json',
|
||||||
candle_type: CandleType = CandleType.SPOT,
|
candle_type: CandleType = CandleType.SPOT,
|
||||||
user_futures_funding_rate: int = None,
|
user_futures_funding_rate: Optional[int] = None,
|
||||||
) -> Dict[str, DataFrame]:
|
) -> Dict[str, DataFrame]:
|
||||||
"""
|
"""
|
||||||
Load ohlcv history data for a list of pairs.
|
Load ohlcv history data for a list of pairs.
|
||||||
@ -116,7 +116,7 @@ def refresh_data(*, datadir: Path,
|
|||||||
timeframe: str,
|
timeframe: str,
|
||||||
pairs: List[str],
|
pairs: List[str],
|
||||||
exchange: Exchange,
|
exchange: Exchange,
|
||||||
data_format: str = None,
|
data_format: Optional[str] = None,
|
||||||
timerange: Optional[TimeRange] = None,
|
timerange: Optional[TimeRange] = None,
|
||||||
candle_type: CandleType,
|
candle_type: CandleType,
|
||||||
) -> None:
|
) -> None:
|
||||||
@ -189,7 +189,7 @@ def _download_pair_history(pair: str, *,
|
|||||||
timeframe: str = '5m',
|
timeframe: str = '5m',
|
||||||
process: str = '',
|
process: str = '',
|
||||||
new_pairs_days: int = 30,
|
new_pairs_days: int = 30,
|
||||||
data_handler: IDataHandler = None,
|
data_handler: Optional[IDataHandler] = None,
|
||||||
timerange: Optional[TimeRange] = None,
|
timerange: Optional[TimeRange] = None,
|
||||||
candle_type: CandleType,
|
candle_type: CandleType,
|
||||||
erase: bool = False,
|
erase: bool = False,
|
||||||
@ -272,7 +272,7 @@ def refresh_backtest_ohlcv_data(exchange: Exchange, pairs: List[str], timeframes
|
|||||||
datadir: Path, trading_mode: str,
|
datadir: Path, trading_mode: str,
|
||||||
timerange: Optional[TimeRange] = None,
|
timerange: Optional[TimeRange] = None,
|
||||||
new_pairs_days: int = 30, erase: bool = False,
|
new_pairs_days: int = 30, erase: bool = False,
|
||||||
data_format: str = None,
|
data_format: Optional[str] = None,
|
||||||
prepend: bool = False,
|
prepend: bool = False,
|
||||||
) -> List[str]:
|
) -> List[str]:
|
||||||
"""
|
"""
|
||||||
|
@ -418,8 +418,8 @@ def get_datahandlerclass(datatype: str) -> Type[IDataHandler]:
|
|||||||
raise ValueError(f"No datahandler for datatype {datatype} available.")
|
raise ValueError(f"No datahandler for datatype {datatype} available.")
|
||||||
|
|
||||||
|
|
||||||
def get_datahandler(datadir: Path, data_format: str = None,
|
def get_datahandler(datadir: Path, data_format: Optional[str] = None,
|
||||||
data_handler: IDataHandler = None) -> IDataHandler:
|
data_handler: Optional[IDataHandler] = None) -> IDataHandler:
|
||||||
"""
|
"""
|
||||||
:param datadir: Folder to save data
|
:param datadir: Folder to save data
|
||||||
:param data_format: dataformat to use
|
:param data_format: dataformat to use
|
||||||
|
@ -675,7 +675,7 @@ class Exchange:
|
|||||||
f"Freqtrade does not support {mm_value} {trading_mode.value} on {self.name}"
|
f"Freqtrade does not support {mm_value} {trading_mode.value} on {self.name}"
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_option(self, param: str, default: Any = None) -> Any:
|
def get_option(self, param: str, default: Optional[Any] = None) -> Any:
|
||||||
"""
|
"""
|
||||||
Get parameter value from _ft_has
|
Get parameter value from _ft_has
|
||||||
"""
|
"""
|
||||||
@ -1350,7 +1350,7 @@ class Exchange:
|
|||||||
raise OperationalException(e) from e
|
raise OperationalException(e) from e
|
||||||
|
|
||||||
@retrier
|
@retrier
|
||||||
def fetch_positions(self, pair: str = None) -> List[Dict]:
|
def fetch_positions(self, pair: Optional[str] = None) -> List[Dict]:
|
||||||
"""
|
"""
|
||||||
Fetch positions from the exchange.
|
Fetch positions from the exchange.
|
||||||
If no pair is given, all positions are returned.
|
If no pair is given, all positions are returned.
|
||||||
@ -1794,7 +1794,7 @@ class Exchange:
|
|||||||
def get_historic_ohlcv(self, pair: str, timeframe: str,
|
def get_historic_ohlcv(self, pair: str, timeframe: str,
|
||||||
since_ms: int, candle_type: CandleType,
|
since_ms: int, candle_type: CandleType,
|
||||||
is_new_pair: bool = False,
|
is_new_pair: bool = False,
|
||||||
until_ms: int = None) -> List:
|
until_ms: Optional[int] = None) -> List:
|
||||||
"""
|
"""
|
||||||
Get candle history using asyncio and returns the list of candles.
|
Get candle history using asyncio and returns the list of candles.
|
||||||
Handles all async work for this.
|
Handles all async work for this.
|
||||||
|
@ -15,18 +15,19 @@ from freqtrade.util import FtPrecise
|
|||||||
CcxtModuleType = Any
|
CcxtModuleType = Any
|
||||||
|
|
||||||
|
|
||||||
def is_exchange_known_ccxt(exchange_name: str, ccxt_module: CcxtModuleType = None) -> bool:
|
def is_exchange_known_ccxt(
|
||||||
|
exchange_name: str, ccxt_module: Optional[CcxtModuleType] = None) -> bool:
|
||||||
return exchange_name in ccxt_exchanges(ccxt_module)
|
return exchange_name in ccxt_exchanges(ccxt_module)
|
||||||
|
|
||||||
|
|
||||||
def ccxt_exchanges(ccxt_module: CcxtModuleType = None) -> List[str]:
|
def ccxt_exchanges(ccxt_module: Optional[CcxtModuleType] = None) -> List[str]:
|
||||||
"""
|
"""
|
||||||
Return the list of all exchanges known to ccxt
|
Return the list of all exchanges known to ccxt
|
||||||
"""
|
"""
|
||||||
return ccxt_module.exchanges if ccxt_module is not None else ccxt.exchanges
|
return ccxt_module.exchanges if ccxt_module is not None else ccxt.exchanges
|
||||||
|
|
||||||
|
|
||||||
def available_exchanges(ccxt_module: CcxtModuleType = None) -> List[str]:
|
def available_exchanges(ccxt_module: Optional[CcxtModuleType] = None) -> List[str]:
|
||||||
"""
|
"""
|
||||||
Return exchanges available to the bot, i.e. non-bad exchanges in the ccxt list
|
Return exchanges available to the bot, i.e. non-bad exchanges in the ccxt list
|
||||||
"""
|
"""
|
||||||
@ -86,7 +87,7 @@ def timeframe_to_msecs(timeframe: str) -> int:
|
|||||||
return ccxt.Exchange.parse_timeframe(timeframe) * 1000
|
return ccxt.Exchange.parse_timeframe(timeframe) * 1000
|
||||||
|
|
||||||
|
|
||||||
def timeframe_to_prev_date(timeframe: str, date: datetime = None) -> datetime:
|
def timeframe_to_prev_date(timeframe: str, date: Optional[datetime] = None) -> datetime:
|
||||||
"""
|
"""
|
||||||
Use Timeframe and determine the candle start date for this date.
|
Use Timeframe and determine the candle start date for this date.
|
||||||
Does not round when given a candle start date.
|
Does not round when given a candle start date.
|
||||||
@ -102,7 +103,7 @@ def timeframe_to_prev_date(timeframe: str, date: datetime = None) -> datetime:
|
|||||||
return datetime.fromtimestamp(new_timestamp, tz=timezone.utc)
|
return datetime.fromtimestamp(new_timestamp, tz=timezone.utc)
|
||||||
|
|
||||||
|
|
||||||
def timeframe_to_next_date(timeframe: str, date: datetime = None) -> datetime:
|
def timeframe_to_next_date(timeframe: str, date: Optional[datetime] = None) -> datetime:
|
||||||
"""
|
"""
|
||||||
Use Timeframe and determine next candle.
|
Use Timeframe and determine next candle.
|
||||||
:param timeframe: timeframe in string format (e.g. "5m")
|
:param timeframe: timeframe in string format (e.g. "5m")
|
||||||
|
@ -5,7 +5,7 @@ import shutil
|
|||||||
from datetime import datetime, timezone
|
from datetime import datetime, timezone
|
||||||
from math import cos, sin
|
from math import cos, sin
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Dict, List, Tuple
|
from typing import Any, Dict, List, Optional, Tuple
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import numpy.typing as npt
|
import numpy.typing as npt
|
||||||
@ -112,7 +112,7 @@ class FreqaiDataKitchen:
|
|||||||
def set_paths(
|
def set_paths(
|
||||||
self,
|
self,
|
||||||
pair: str,
|
pair: str,
|
||||||
trained_timestamp: int = None,
|
trained_timestamp: Optional[int] = None,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""
|
"""
|
||||||
Set the paths to the data for the present coin/botloop
|
Set the paths to the data for the present coin/botloop
|
||||||
|
@ -1522,7 +1522,7 @@ class FreqtradeBot(LoggingMixin):
|
|||||||
*,
|
*,
|
||||||
exit_tag: Optional[str] = None,
|
exit_tag: Optional[str] = None,
|
||||||
ordertype: Optional[str] = None,
|
ordertype: Optional[str] = None,
|
||||||
sub_trade_amt: float = None,
|
sub_trade_amt: Optional[float] = None,
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""
|
"""
|
||||||
Executes a trade exit for the given trade and limit
|
Executes a trade exit for the given trade and limit
|
||||||
@ -1616,7 +1616,7 @@ class FreqtradeBot(LoggingMixin):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
def _notify_exit(self, trade: Trade, order_type: str, fill: bool = False,
|
def _notify_exit(self, trade: Trade, order_type: str, fill: bool = False,
|
||||||
sub_trade: bool = False, order: Order = None) -> None:
|
sub_trade: bool = False, order: Optional[Order] = None) -> None:
|
||||||
"""
|
"""
|
||||||
Sends rpc notification when a sell occurred.
|
Sends rpc notification when a sell occurred.
|
||||||
"""
|
"""
|
||||||
@ -1729,8 +1729,9 @@ class FreqtradeBot(LoggingMixin):
|
|||||||
# Common update trade state methods
|
# Common update trade state methods
|
||||||
#
|
#
|
||||||
|
|
||||||
def update_trade_state(self, trade: Trade, order_id: str, action_order: Dict[str, Any] = None,
|
def update_trade_state(
|
||||||
stoploss_order: bool = False, send_msg: bool = True) -> bool:
|
self, trade: Trade, order_id: str, action_order: Optional[Dict[str, Any]] = None,
|
||||||
|
stoploss_order: bool = False, send_msg: bool = True) -> bool:
|
||||||
"""
|
"""
|
||||||
Checks trades with open orders and updates the amount if necessary
|
Checks trades with open orders and updates the amount if necessary
|
||||||
Handles closing both buy and sell orders.
|
Handles closing both buy and sell orders.
|
||||||
|
@ -5,7 +5,7 @@ Read the documentation to know what cli arguments you need.
|
|||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
import sys
|
import sys
|
||||||
from typing import Any, List
|
from typing import Any, List, Optional
|
||||||
|
|
||||||
from freqtrade.util.gc_setup import gc_set_threshold
|
from freqtrade.util.gc_setup import gc_set_threshold
|
||||||
|
|
||||||
@ -23,7 +23,7 @@ from freqtrade.loggers import setup_logging_pre
|
|||||||
logger = logging.getLogger('freqtrade')
|
logger = logging.getLogger('freqtrade')
|
||||||
|
|
||||||
|
|
||||||
def main(sysargv: List[str] = None) -> None:
|
def main(sysargv: Optional[List[str]] = None) -> None:
|
||||||
"""
|
"""
|
||||||
This function will initiate the bot and start the trading loop.
|
This function will initiate the bot and start the trading loop.
|
||||||
:return: None
|
:return: None
|
||||||
|
@ -6,7 +6,7 @@ import logging
|
|||||||
import re
|
import re
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Dict, Iterator, List, Mapping, Union
|
from typing import Any, Dict, Iterator, List, Mapping, Optional, Union
|
||||||
from typing.io import IO
|
from typing.io import IO
|
||||||
from urllib.parse import urlparse
|
from urllib.parse import urlparse
|
||||||
|
|
||||||
@ -205,7 +205,7 @@ def safe_value_fallback2(dict1: dictMap, dict2: dictMap, key1: str, key2: str, d
|
|||||||
return default_value
|
return default_value
|
||||||
|
|
||||||
|
|
||||||
def plural(num: float, singular: str, plural: str = None) -> str:
|
def plural(num: float, singular: str, plural: Optional[str] = None) -> str:
|
||||||
return singular if (num == 1 or num == -1) else plural or singular + 's'
|
return singular if (num == 1 or num == -1) else plural or singular + 's'
|
||||||
|
|
||||||
|
|
||||||
|
@ -644,7 +644,7 @@ class Backtesting:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def _exit_trade(self, trade: LocalTrade, sell_row: Tuple,
|
def _exit_trade(self, trade: LocalTrade, sell_row: Tuple,
|
||||||
close_rate: float, amount: float = None) -> Optional[LocalTrade]:
|
close_rate: float, amount: Optional[float] = None) -> Optional[LocalTrade]:
|
||||||
self.order_id_counter += 1
|
self.order_id_counter += 1
|
||||||
exit_candle_time = sell_row[DATE_IDX].to_pydatetime()
|
exit_candle_time = sell_row[DATE_IDX].to_pydatetime()
|
||||||
order_type = self.strategy.order_types['exit']
|
order_type = self.strategy.order_types['exit']
|
||||||
|
@ -170,7 +170,7 @@ class HyperoptTools():
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def show_epoch_details(results, total_epochs: int, print_json: bool,
|
def show_epoch_details(results, total_epochs: int, print_json: bool,
|
||||||
no_header: bool = False, header_str: str = None) -> None:
|
no_header: bool = False, header_str: Optional[str] = None) -> None:
|
||||||
"""
|
"""
|
||||||
Display details of the hyperopt result
|
Display details of the hyperopt result
|
||||||
"""
|
"""
|
||||||
@ -264,7 +264,7 @@ class HyperoptTools():
|
|||||||
print(result)
|
print(result)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _space_params(params, space: str, r: int = None) -> Dict:
|
def _space_params(params, space: str, r: Optional[int] = None) -> Dict:
|
||||||
d = params.get(space)
|
d = params.get(space)
|
||||||
if d:
|
if d:
|
||||||
# Round floats to `r` digits after the decimal point if requested
|
# Round floats to `r` digits after the decimal point if requested
|
||||||
|
@ -30,8 +30,8 @@ class PairLocks():
|
|||||||
PairLocks.locks = []
|
PairLocks.locks = []
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def lock_pair(pair: str, until: datetime, reason: str = None, *,
|
def lock_pair(pair: str, until: datetime, reason: Optional[str] = None, *,
|
||||||
now: datetime = None, side: str = '*') -> PairLock:
|
now: Optional[datetime] = None, side: str = '*') -> PairLock:
|
||||||
"""
|
"""
|
||||||
Create PairLock from now to "until".
|
Create PairLock from now to "until".
|
||||||
Uses database by default, unless PairLocks.use_db is set to False,
|
Uses database by default, unless PairLocks.use_db is set to False,
|
||||||
|
@ -799,7 +799,7 @@ class LocalTrade():
|
|||||||
else:
|
else:
|
||||||
return close_trade - fees
|
return close_trade - fees
|
||||||
|
|
||||||
def calc_close_trade_value(self, rate: float, amount: float = None) -> float:
|
def calc_close_trade_value(self, rate: float, amount: Optional[float] = None) -> float:
|
||||||
"""
|
"""
|
||||||
Calculate the Trade's close value including fees
|
Calculate the Trade's close value including fees
|
||||||
:param rate: rate to compare with.
|
:param rate: rate to compare with.
|
||||||
@ -837,7 +837,8 @@ class LocalTrade():
|
|||||||
raise OperationalException(
|
raise OperationalException(
|
||||||
f"{self.trading_mode.value} trading is not yet available using freqtrade")
|
f"{self.trading_mode.value} trading is not yet available using freqtrade")
|
||||||
|
|
||||||
def calc_profit(self, rate: float, amount: float = None, open_rate: float = None) -> float:
|
def calc_profit(self, rate: float, amount: Optional[float] = None,
|
||||||
|
open_rate: Optional[float] = None) -> float:
|
||||||
"""
|
"""
|
||||||
Calculate the absolute profit in stake currency between Close and Open trade
|
Calculate the absolute profit in stake currency between Close and Open trade
|
||||||
:param rate: close rate to compare with.
|
:param rate: close rate to compare with.
|
||||||
@ -858,7 +859,8 @@ class LocalTrade():
|
|||||||
return float(f"{profit:.8f}")
|
return float(f"{profit:.8f}")
|
||||||
|
|
||||||
def calc_profit_ratio(
|
def calc_profit_ratio(
|
||||||
self, rate: float, amount: float = None, open_rate: float = None) -> float:
|
self, rate: float, amount: Optional[float] = None,
|
||||||
|
open_rate: Optional[float] = None) -> float:
|
||||||
"""
|
"""
|
||||||
Calculates the profit as ratio (including fee).
|
Calculates the profit as ratio (including fee).
|
||||||
:param rate: rate to compare with.
|
:param rate: rate to compare with.
|
||||||
@ -1059,8 +1061,9 @@ class LocalTrade():
|
|||||||
return self.exit_reason
|
return self.exit_reason
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_trades_proxy(*, pair: str = None, is_open: bool = None,
|
def get_trades_proxy(*, pair: Optional[str] = None, is_open: Optional[bool] = None,
|
||||||
open_date: datetime = None, close_date: datetime = None,
|
open_date: Optional[datetime] = None,
|
||||||
|
close_date: Optional[datetime] = None,
|
||||||
) -> List['LocalTrade']:
|
) -> List['LocalTrade']:
|
||||||
"""
|
"""
|
||||||
Helper function to query Trades.
|
Helper function to query Trades.
|
||||||
@ -1257,8 +1260,9 @@ class Trade(_DECL_BASE, LocalTrade):
|
|||||||
Trade.query.session.rollback()
|
Trade.query.session.rollback()
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def get_trades_proxy(*, pair: str = None, is_open: bool = None,
|
def get_trades_proxy(*, pair: Optional[str] = None, is_open: Optional[bool] = None,
|
||||||
open_date: datetime = None, close_date: datetime = None,
|
open_date: Optional[datetime] = None,
|
||||||
|
close_date: Optional[datetime] = None,
|
||||||
) -> List['LocalTrade']:
|
) -> List['LocalTrade']:
|
||||||
"""
|
"""
|
||||||
Helper function to query Trades.j
|
Helper function to query Trades.j
|
||||||
|
@ -436,11 +436,11 @@ def create_scatter(
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def generate_candlestick_graph(pair: str, data: pd.DataFrame, trades: pd.DataFrame = None, *,
|
def generate_candlestick_graph(
|
||||||
indicators1: List[str] = [],
|
pair: str, data: pd.DataFrame, trades: Optional[pd.DataFrame] = None, *,
|
||||||
indicators2: List[str] = [],
|
indicators1: List[str] = [], indicators2: List[str] = [],
|
||||||
plot_config: Dict[str, Dict] = {},
|
plot_config: Dict[str, Dict] = {},
|
||||||
) -> go.Figure:
|
) -> go.Figure:
|
||||||
"""
|
"""
|
||||||
Generate the graph from the data generated by Backtesting or from DB
|
Generate the graph from the data generated by Backtesting or from DB
|
||||||
Volume will always be ploted in row2, so Row 1 and 3 are to our disposal for custom indicators
|
Volume will always be ploted in row2, so Row 1 and 3 are to our disposal for custom indicators
|
||||||
|
@ -23,7 +23,8 @@ logger = logging.getLogger(__name__)
|
|||||||
|
|
||||||
class PairListManager(LoggingMixin):
|
class PairListManager(LoggingMixin):
|
||||||
|
|
||||||
def __init__(self, exchange, config: Config, dataprovider: DataProvider = None) -> None:
|
def __init__(
|
||||||
|
self, exchange, config: Config, dataprovider: Optional[DataProvider] = None) -> None:
|
||||||
self._exchange = exchange
|
self._exchange = exchange
|
||||||
self._config = config
|
self._config = config
|
||||||
self._whitelist = self._config['exchange'].get('pair_whitelist')
|
self._whitelist = self._config['exchange'].get('pair_whitelist')
|
||||||
@ -153,7 +154,8 @@ class PairListManager(LoggingMixin):
|
|||||||
return []
|
return []
|
||||||
return whitelist
|
return whitelist
|
||||||
|
|
||||||
def create_pair_list(self, pairs: List[str], timeframe: str = None) -> ListPairsWithTimeframes:
|
def create_pair_list(
|
||||||
|
self, pairs: List[str], timeframe: Optional[str] = None) -> ListPairsWithTimeframes:
|
||||||
"""
|
"""
|
||||||
Create list of pair tuples with (pair, timeframe)
|
Create list of pair tuples with (pair, timeframe)
|
||||||
"""
|
"""
|
||||||
|
@ -33,7 +33,7 @@ class StrategyResolver(IResolver):
|
|||||||
extra_path = "strategy_path"
|
extra_path = "strategy_path"
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def load_strategy(config: Config = None) -> IStrategy:
|
def load_strategy(config: Optional[Config] = None) -> IStrategy:
|
||||||
"""
|
"""
|
||||||
Load the custom class from config parameter
|
Load the custom class from config parameter
|
||||||
:param config: configuration dictionary or None
|
:param config: configuration dictionary or None
|
||||||
|
@ -945,7 +945,7 @@ class RPC:
|
|||||||
resp['errors'] = errors
|
resp['errors'] = errors
|
||||||
return resp
|
return resp
|
||||||
|
|
||||||
def _rpc_blacklist(self, add: List[str] = None) -> Dict:
|
def _rpc_blacklist(self, add: Optional[List[str]] = None) -> Dict:
|
||||||
""" Returns the currently active blacklist"""
|
""" Returns the currently active blacklist"""
|
||||||
errors = {}
|
errors = {}
|
||||||
if add:
|
if add:
|
||||||
|
@ -1605,7 +1605,7 @@ class Telegram(RPCHandler):
|
|||||||
|
|
||||||
def _send_msg(self, msg: str, parse_mode: str = ParseMode.MARKDOWN,
|
def _send_msg(self, msg: str, parse_mode: str = ParseMode.MARKDOWN,
|
||||||
disable_notification: bool = False,
|
disable_notification: bool = False,
|
||||||
keyboard: List[List[InlineKeyboardButton]] = None,
|
keyboard: Optional[List[List[InlineKeyboardButton]]] = None,
|
||||||
callback_path: str = "",
|
callback_path: str = "",
|
||||||
reload_able: bool = False,
|
reload_able: bool = False,
|
||||||
query: Optional[CallbackQuery] = None) -> None:
|
query: Optional[CallbackQuery] = None) -> None:
|
||||||
|
@ -4,7 +4,7 @@ This module defines a base class for auto-hyperoptable strategies.
|
|||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Dict, Iterator, List, Tuple, Type, Union
|
from typing import Any, Dict, Iterator, List, Optional, Tuple, Type, Union
|
||||||
|
|
||||||
from freqtrade.constants import Config
|
from freqtrade.constants import Config
|
||||||
from freqtrade.exceptions import OperationalException
|
from freqtrade.exceptions import OperationalException
|
||||||
@ -36,7 +36,8 @@ class HyperStrategyMixin:
|
|||||||
self._ft_params_from_file = params
|
self._ft_params_from_file = params
|
||||||
# Init/loading of parameters is done as part of ft_bot_start().
|
# Init/loading of parameters is done as part of ft_bot_start().
|
||||||
|
|
||||||
def enumerate_parameters(self, category: str = None) -> Iterator[Tuple[str, BaseParameter]]:
|
def enumerate_parameters(
|
||||||
|
self, category: Optional[str] = None) -> Iterator[Tuple[str, BaseParameter]]:
|
||||||
"""
|
"""
|
||||||
Find all optimizable parameters and return (name, attr) iterator.
|
Find all optimizable parameters and return (name, attr) iterator.
|
||||||
:param category:
|
:param category:
|
||||||
|
@ -598,7 +598,7 @@ class IStrategy(ABC, HyperStrategyMixin):
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
def populate_any_indicators(self, pair: str, df: DataFrame, tf: str,
|
def populate_any_indicators(self, pair: str, df: DataFrame, tf: str,
|
||||||
informative: DataFrame = None,
|
informative: Optional[DataFrame] = None,
|
||||||
set_generalized_indicators: bool = False) -> DataFrame:
|
set_generalized_indicators: bool = False) -> DataFrame:
|
||||||
"""
|
"""
|
||||||
DEPRECATED - USE FEATURE ENGINEERING FUNCTIONS INSTEAD
|
DEPRECATED - USE FEATURE ENGINEERING FUNCTIONS INSTEAD
|
||||||
@ -759,7 +759,8 @@ class IStrategy(ABC, HyperStrategyMixin):
|
|||||||
"""
|
"""
|
||||||
return self.__class__.__name__
|
return self.__class__.__name__
|
||||||
|
|
||||||
def lock_pair(self, pair: str, until: datetime, reason: str = None, side: str = '*') -> None:
|
def lock_pair(self, pair: str, until: datetime,
|
||||||
|
reason: Optional[str] = None, side: str = '*') -> None:
|
||||||
"""
|
"""
|
||||||
Locks pair until a given timestamp happens.
|
Locks pair until a given timestamp happens.
|
||||||
Locked pairs are not analyzed, and are prevented from opening new trades.
|
Locked pairs are not analyzed, and are prevented from opening new trades.
|
||||||
@ -791,7 +792,8 @@ class IStrategy(ABC, HyperStrategyMixin):
|
|||||||
"""
|
"""
|
||||||
PairLocks.unlock_reason(reason, datetime.now(timezone.utc))
|
PairLocks.unlock_reason(reason, datetime.now(timezone.utc))
|
||||||
|
|
||||||
def is_pair_locked(self, pair: str, *, candle_date: datetime = None, side: str = '*') -> bool:
|
def is_pair_locked(self, pair: str, *, candle_date: Optional[datetime] = None,
|
||||||
|
side: str = '*') -> bool:
|
||||||
"""
|
"""
|
||||||
Checks if a pair is currently locked
|
Checks if a pair is currently locked
|
||||||
The 2nd, optional parameter ensures that locks are applied until the new candle arrives,
|
The 2nd, optional parameter ensures that locks are applied until the new candle arrives,
|
||||||
@ -962,7 +964,7 @@ class IStrategy(ABC, HyperStrategyMixin):
|
|||||||
pair: str,
|
pair: str,
|
||||||
timeframe: str,
|
timeframe: str,
|
||||||
dataframe: DataFrame,
|
dataframe: DataFrame,
|
||||||
is_short: bool = None
|
is_short: Optional[bool] = None
|
||||||
) -> Tuple[bool, bool, Optional[str]]:
|
) -> Tuple[bool, bool, Optional[str]]:
|
||||||
"""
|
"""
|
||||||
Calculates current exit signal based based on the dataframe
|
Calculates current exit signal based based on the dataframe
|
||||||
@ -1061,7 +1063,7 @@ class IStrategy(ABC, HyperStrategyMixin):
|
|||||||
|
|
||||||
def should_exit(self, trade: Trade, rate: float, current_time: datetime, *,
|
def should_exit(self, trade: Trade, rate: float, current_time: datetime, *,
|
||||||
enter: bool, exit_: bool,
|
enter: bool, exit_: bool,
|
||||||
low: float = None, high: float = None,
|
low: Optional[float] = None, high: Optional[float] = None,
|
||||||
force_stoploss: float = 0) -> List[ExitCheckTuple]:
|
force_stoploss: float = 0) -> List[ExitCheckTuple]:
|
||||||
"""
|
"""
|
||||||
This function evaluates if one of the conditions required to trigger an exit order
|
This function evaluates if one of the conditions required to trigger an exit order
|
||||||
@ -1149,8 +1151,8 @@ class IStrategy(ABC, HyperStrategyMixin):
|
|||||||
|
|
||||||
def stop_loss_reached(self, current_rate: float, trade: Trade,
|
def stop_loss_reached(self, current_rate: float, trade: Trade,
|
||||||
current_time: datetime, current_profit: float,
|
current_time: datetime, current_profit: float,
|
||||||
force_stoploss: float, low: float = None,
|
force_stoploss: float, low: Optional[float] = None,
|
||||||
high: float = None) -> ExitCheckTuple:
|
high: Optional[float] = None) -> ExitCheckTuple:
|
||||||
"""
|
"""
|
||||||
Based on current profit of the trade and configured (trailing) stoploss,
|
Based on current profit of the trade and configured (trailing) stoploss,
|
||||||
decides to exit or not
|
decides to exit or not
|
||||||
|
@ -26,7 +26,7 @@ class Worker:
|
|||||||
Freqtradebot worker class
|
Freqtradebot worker class
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, args: Dict[str, Any], config: Config = None) -> None:
|
def __init__(self, args: Dict[str, Any], config: Optional[Config] = None) -> None:
|
||||||
"""
|
"""
|
||||||
Init all variables and objects the bot needs to work
|
Init all variables and objects the bot needs to work
|
||||||
"""
|
"""
|
||||||
|
@ -31,7 +31,6 @@ asyncio_mode = "auto"
|
|||||||
[tool.mypy]
|
[tool.mypy]
|
||||||
ignore_missing_imports = true
|
ignore_missing_imports = true
|
||||||
namespace_packages = false
|
namespace_packages = false
|
||||||
implicit_optional = true
|
|
||||||
warn_unused_ignores = true
|
warn_unused_ignores = true
|
||||||
exclude = [
|
exclude = [
|
||||||
'^build_helpers\.py$'
|
'^build_helpers\.py$'
|
||||||
@ -41,6 +40,11 @@ exclude = [
|
|||||||
module = "tests.*"
|
module = "tests.*"
|
||||||
ignore_errors = true
|
ignore_errors = true
|
||||||
|
|
||||||
|
[[tool.mypy.overrides]]
|
||||||
|
# Telegram does not use implicit_optional = false in the current version.
|
||||||
|
module = "telegram.*"
|
||||||
|
implicit_optional = true
|
||||||
|
|
||||||
[build-system]
|
[build-system]
|
||||||
requires = ["setuptools >= 46.4.0", "wheel"]
|
requires = ["setuptools >= 46.4.0", "wheel"]
|
||||||
build-backend = "setuptools.build_meta"
|
build-backend = "setuptools.build_meta"
|
||||||
@ -52,6 +56,3 @@ exclude = [
|
|||||||
"build_helpers/*.py",
|
"build_helpers/*.py",
|
||||||
]
|
]
|
||||||
ignore = ["freqtrade/vendor/**"]
|
ignore = ["freqtrade/vendor/**"]
|
||||||
|
|
||||||
# Align pyright to mypy config
|
|
||||||
strictParameterNoneValue = false
|
|
||||||
|
@ -14,6 +14,7 @@ import logging
|
|||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from typing import Optional
|
||||||
from urllib.parse import urlencode, urlparse, urlunparse
|
from urllib.parse import urlencode, urlparse, urlunparse
|
||||||
|
|
||||||
import rapidjson
|
import rapidjson
|
||||||
@ -36,7 +37,7 @@ class FtRestClient():
|
|||||||
self._session = requests.Session()
|
self._session = requests.Session()
|
||||||
self._session.auth = (username, password)
|
self._session.auth = (username, password)
|
||||||
|
|
||||||
def _call(self, method, apipath, params: dict = None, data=None, files=None):
|
def _call(self, method, apipath, params: Optional[dict] = None, data=None, files=None):
|
||||||
|
|
||||||
if str(method).upper() not in ('GET', 'POST', 'PUT', 'DELETE'):
|
if str(method).upper() not in ('GET', 'POST', 'PUT', 'DELETE'):
|
||||||
raise ValueError(f'invalid method <{method}>')
|
raise ValueError(f'invalid method <{method}>')
|
||||||
@ -60,13 +61,13 @@ class FtRestClient():
|
|||||||
except ConnectionError:
|
except ConnectionError:
|
||||||
logger.warning("Connection error")
|
logger.warning("Connection error")
|
||||||
|
|
||||||
def _get(self, apipath, params: dict = None):
|
def _get(self, apipath, params: Optional[dict] = None):
|
||||||
return self._call("GET", apipath, params=params)
|
return self._call("GET", apipath, params=params)
|
||||||
|
|
||||||
def _delete(self, apipath, params: dict = None):
|
def _delete(self, apipath, params: Optional[dict] = None):
|
||||||
return self._call("DELETE", apipath, params=params)
|
return self._call("DELETE", apipath, params=params)
|
||||||
|
|
||||||
def _post(self, apipath, params: dict = None, data: dict = None):
|
def _post(self, apipath, params: Optional[dict] = None, data: Optional[dict] = None):
|
||||||
return self._call("POST", apipath, params=params, data=data)
|
return self._call("POST", apipath, params=params, data=data)
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
|
Loading…
Reference in New Issue
Block a user