pass around dataframe instead of list
This commit is contained in:
parent
a377088421
commit
627ab9f583
@ -7,12 +7,14 @@ from typing import List, Dict, Tuple, Any, Optional
|
||||
from datetime import datetime
|
||||
from math import floor, ceil
|
||||
|
||||
import arrow
|
||||
import asyncio
|
||||
import ccxt
|
||||
import ccxt.async_support as ccxt_async
|
||||
import arrow
|
||||
from pandas import DataFrame
|
||||
|
||||
from freqtrade import constants, OperationalException, DependencyException, TemporaryError
|
||||
from freqtrade.exchange.exchange_helpers import parse_ticker_dataframe
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
@ -81,7 +83,7 @@ class Exchange(object):
|
||||
self._pairs_last_refresh_time: Dict[str, int] = {}
|
||||
|
||||
# Holds candles
|
||||
self.klines: Dict[str, Any] = {}
|
||||
self._klines: Dict[str, DataFrame] = {}
|
||||
|
||||
# Holds all open sell orders for dry_run
|
||||
self._dry_run_open_orders: Dict[str, Any] = {}
|
||||
@ -155,6 +157,12 @@ class Exchange(object):
|
||||
"""exchange ccxt id"""
|
||||
return self._api.id
|
||||
|
||||
def klines(self, pair: str) -> DataFrame:
|
||||
if pair in self._klines:
|
||||
return self._klines.get(pair).copy()
|
||||
else:
|
||||
return None
|
||||
|
||||
def set_sandbox(self, api, exchange_config: dict, name: str):
|
||||
if exchange_config.get('sandbox'):
|
||||
if api.urls.get('test'):
|
||||
@ -499,7 +507,7 @@ class Exchange(object):
|
||||
|
||||
def refresh_tickers(self, pair_list: List[str], ticker_interval: str) -> None:
|
||||
"""
|
||||
Refresh tickers asyncronously and set `klines` of this object with the result
|
||||
Refresh tickers asyncronously and set `_klines` of this object with the result
|
||||
"""
|
||||
logger.debug("Refreshing klines for %d pairs", len(pair_list))
|
||||
asyncio.get_event_loop().run_until_complete(
|
||||
@ -515,7 +523,7 @@ class Exchange(object):
|
||||
# Gather corotines to run
|
||||
for pair in pairs:
|
||||
if not (self._pairs_last_refresh_time.get(pair, 0) + interval_in_sec >=
|
||||
arrow.utcnow().timestamp and pair in self.klines):
|
||||
arrow.utcnow().timestamp and pair in self._klines):
|
||||
input_coroutines.append(self._async_get_candle_history(pair, tick_interval))
|
||||
else:
|
||||
logger.debug("Using cached klines data for %s ...", pair)
|
||||
@ -528,7 +536,7 @@ class Exchange(object):
|
||||
if ticks:
|
||||
self._pairs_last_refresh_time[pair] = ticks[-1][0] // 1000
|
||||
# keeping parsed dataframe in cache
|
||||
self.klines[pair] = ticks
|
||||
self._klines[pair] = parse_ticker_dataframe(ticks)
|
||||
return tickers
|
||||
|
||||
@retrier_async
|
||||
|
@ -14,6 +14,7 @@ def parse_ticker_dataframe(ticker: list) -> DataFrame:
|
||||
:param ticker: ticker list, as returned by exchange.async_get_candle_history
|
||||
:return: DataFrame
|
||||
"""
|
||||
logger.debug("Parsing tickerlist to dataframe")
|
||||
cols = ['date', 'open', 'high', 'low', 'close', 'volume']
|
||||
frame = DataFrame(ticker, columns=cols)
|
||||
|
||||
|
@ -317,7 +317,7 @@ class FreqtradeBot(object):
|
||||
|
||||
# running get_signal on historical data fetched
|
||||
for _pair in whitelist:
|
||||
(buy, sell) = self.strategy.get_signal(_pair, interval, self.exchange.klines.get(_pair))
|
||||
(buy, sell) = self.strategy.get_signal(_pair, interval, self.exchange.klines(_pair))
|
||||
if buy and not sell:
|
||||
stake_amount = self._get_trade_stake_amount(_pair)
|
||||
if not stake_amount:
|
||||
@ -540,9 +540,8 @@ class FreqtradeBot(object):
|
||||
(buy, sell) = (False, False)
|
||||
experimental = self.config.get('experimental', {})
|
||||
if experimental.get('use_sell_signal') or experimental.get('ignore_roi_if_buy_signal'):
|
||||
ticker = self.exchange.klines.get(trade.pair)
|
||||
(buy, sell) = self.strategy.get_signal(trade.pair, self.strategy.ticker_interval,
|
||||
ticker)
|
||||
self.exchange.klines(trade.pair))
|
||||
|
||||
config_ask_strategy = self.config.get('ask_strategy', {})
|
||||
if config_ask_strategy.get('use_order_book', False):
|
||||
|
@ -6,7 +6,7 @@ import logging
|
||||
from abc import ABC, abstractmethod
|
||||
from datetime import datetime
|
||||
from enum import Enum
|
||||
from typing import Dict, List, NamedTuple, Optional, Tuple
|
||||
from typing import Dict, List, NamedTuple, Tuple
|
||||
import warnings
|
||||
|
||||
import arrow
|
||||
@ -122,15 +122,13 @@ class IStrategy(ABC):
|
||||
"""
|
||||
return self.__class__.__name__
|
||||
|
||||
def analyze_ticker(self, ticker_history: List[Dict], metadata: dict) -> DataFrame:
|
||||
def analyze_ticker(self, dataframe: DataFrame, metadata: dict) -> DataFrame:
|
||||
"""
|
||||
Parses the given ticker history and returns a populated DataFrame
|
||||
add several TA indicators and buy signal to it
|
||||
:return DataFrame with ticker data and indicator data
|
||||
"""
|
||||
|
||||
dataframe = parse_ticker_dataframe(ticker_history)
|
||||
|
||||
pair = str(metadata.get('pair'))
|
||||
|
||||
# Test if seen this pair and last candle before.
|
||||
@ -155,19 +153,20 @@ class IStrategy(ABC):
|
||||
return dataframe
|
||||
|
||||
def get_signal(self, pair: str, interval: str,
|
||||
ticker_hist: Optional[List[Dict]]) -> Tuple[bool, bool]:
|
||||
dataframe: DataFrame) -> Tuple[bool, bool]:
|
||||
"""
|
||||
Calculates current signal based several technical analysis indicators
|
||||
:param pair: pair in format ANT/BTC
|
||||
:param interval: Interval to use (in min)
|
||||
:param dataframe: Dataframe to analyze
|
||||
:return: (Buy, Sell) A bool-tuple indicating buy/sell signal
|
||||
"""
|
||||
if not ticker_hist:
|
||||
if isinstance(dataframe, DataFrame) and dataframe.empty:
|
||||
logger.warning('Empty ticker history for pair %s', pair)
|
||||
return False, False
|
||||
|
||||
try:
|
||||
dataframe = self.analyze_ticker(ticker_hist, {'pair': pair})
|
||||
dataframe = self.analyze_ticker(dataframe, {'pair': pair})
|
||||
except ValueError as error:
|
||||
logger.warning(
|
||||
'Unable to analyze ticker for pair %s: %s',
|
||||
|
Loading…
Reference in New Issue
Block a user