コード例 #1
0
    def start(self) -> None:
        """
        Schedules health checks to run automatically at night.
        These scheduled runs are in addition to runs initiated by the user manually using the webpanel.
        """

        # Stop the already-running thread, if active
        self.stop()

        # Create a time interval representing [6PM, 6AM]
        update_time_period = TimeInterval(self.logfeed_process, time(hour=18), time(hour=6))

        # Run health checks during the time interval, in a separate thread
        self.health_updates_thread = threading.Thread(target=self._updates_logic, args=[update_time_period])
        self.health_updates_thread.start()
コード例 #2
0
ファイル: SymbolDay.py プロジェクト: maxilie/TC2_public
    def get_ordered_candles(cls, candles: List[Candle],
                            interval: TimeInterval) -> List[Candle]:
        """
        :param candles: a list of candles potentially containing extraneous, unsorted candles
        :return: a list of candles containing only candles contained in this time interval, sorted ascending by date
        """

        # Filter out extraneous candles
        contained_candles = []
        for candle in candles:
            if interval.contains_time(candle.moment.time()):
                contained_candles.append(candle)

        # Sort by date
        contained_candles.sort(
            key=lambda candle_to_sort: candle_to_sort.moment)
        return contained_candles
コード例 #3
0
 def times_active(cls) -> TimeInterval:
     return TimeInterval(logfeed=None,
                         start1=time(hour=10, minute=30),
                         end1=time(hour=15, minute=0))
コード例 #4
0
ファイル: candle_util.py プロジェクト: maxilie/TC2_public
def find_mins_maxs(trendline_candles: List[Candle]) -> Tuple[List[Candle], List[Candle]]:
    """
    Returns two lists: the first containing local minima, and the second local maxima.
    """
    # Sanitize input.
    assert len(trendline_candles) > 9, 'Cannot find mins/maxs without at least 10 candles'
    # Get sliding window length.
    trend_length = ContinuousTimeInterval(start_time=trendline_candles[0].moment.time(),
                                          end_time=trendline_candles[-1].moment.time()).length()
    window_length = max(5, int(trend_length * 0.12))
    # Ensure sliding window length is an odd number of seconds.
    window_length = window_length if window_length % 2 == 0 else window_length + 1

    # Get slide interval.
    slide_interval = max(1, window_length * 0.02)

    # Slide the window along the trendline period.
    mins, maxs = [], []
    window = ContinuousTimeInterval(trendline_candles[0].moment.time(),
                                    (trendline_candles[0].moment + timedelta(seconds=window_length)).time())
    while datetime.combine(trendline_candles[0].moment.date(), window.end_time) <= trendline_candles[-1].moment:
        # Get candles in the window.
        window_candles = SymbolDay.get_ordered_candles(candles=trendline_candles,
                                                       interval=TimeInterval(None, window.start_time, window.end_time))
        # Get midpoint candle.
        midpoint_candle = midpoint_candle_in_period(period=window,
                                                    candles=trendline_candles,
                                                    day_date=trendline_candles[0].moment.date())
        # Get candles before and after the midpoint.
        first_half_candles = [candle for candle in window_candles if candle.moment < midpoint_candle.moment]
        second_half_candles = [candle for candle in window_candles if candle.moment > midpoint_candle.moment]

        # Ensure there are candles before/after the midpoint.
        if midpoint_candle is None or len(window_candles) == 0 or len(first_half_candles) == 0 \
                or len(second_half_candles) == 0:
            # Slide the window forward if not enough candles.
            window_start = datetime.combine(datetime.today(), window.start_time) + timedelta(seconds=slide_interval)
            window_end = datetime.combine(datetime.today(), window.end_time) + timedelta(seconds=slide_interval)
            window = ContinuousTimeInterval(window_start.time(), window_end.time())
            continue

        # Find out what percentage of prices before/after midpoint are less than the midpoint price.
        pct_prices_below = (len([candle for candle in first_half_candles if candle.low < midpoint_candle.low])
                            + len([candle for candle in second_half_candles if candle.low < midpoint_candle.low])) \
                           / len(window_candles)
        # Find out what percentage of prices before/after midpoint are greater than the midpoint price.
        pct_prices_above = (len([candle for candle in first_half_candles if candle.high > midpoint_candle.high])
                            + len([candle for candle in second_half_candles if candle.high > midpoint_candle.high])) \
                           / len(window_candles)

        # Record a local minimum if 97% of the window's prices are higher than the midpoint price.
        if pct_prices_above >= 0.97:
            mins.append(midpoint_candle)

        # Record a local maximum if 97% of the window's prices are lower than the midpoint price.
        if pct_prices_below >= 0.97:
            maxs.append(midpoint_candle)

        # Slide the window forward.
        window_start = datetime.combine(datetime.today(), window.start_time) + timedelta(seconds=slide_interval)
        window_end = datetime.combine(datetime.today(), window.end_time) + timedelta(seconds=slide_interval)
        window = ContinuousTimeInterval(window_start.time(), window_end.time())

    # Get candles at the beginning and end of the trendline period.
    start_candles = SymbolDay.get_ordered_candles(
        candles=trendline_candles,
        interval=TimeInterval(None, trendline_candles[0].moment.time(),
                              (trendline_candles[0].moment + timedelta(seconds=window_length)).time()))
    end_candles = SymbolDay.get_ordered_candles(
        candles=trendline_candles,
        interval=TimeInterval(None, (trendline_candles[-1].moment - timedelta(seconds=window_length)).time(),
                              trendline_candles[-1].moment.time()))

    # Check for a global minimum in prices at the start and end of the trendline period.
    start_min = sorted(start_candles, key=lambda candle: candle.low)[0]
    end_min = sorted(end_candles, key=lambda candle: candle.low)[0]
    if len(mins) < 2 or start_min.low < min([local_min_candle.low for local_min_candle in mins]):
        mins.insert(0, start_min)
    if len(mins) < 2 or end_min.low < min([local_min_candle.low for local_min_candle in mins]):
        mins.append(end_min)

    # Check for a global maximum in prices at the start and end of the trendline period.
    start_max = sorted(start_candles, key=lambda candle: candle.high)[-1]
    end_max = sorted(end_candles, key=lambda candle: candle.high)[-1]
    if len(maxs) < 2 or start_max.high > max([local_max_candle.high for local_max_candle in maxs]):
        maxs.insert(0, start_max)
    if len(maxs) < 2 or end_max.high > max([local_max_candle.high for local_max_candle in maxs]):
        maxs.append(end_max)

    # Ensure minima are spread apart by at least 3% of the trendline's period.
    reqd_dist = max(3, trend_length * 0.03)
    i = 0
    while i < len(mins) - 1 and len(mins) >= 3:
        if (mins[i + 1].moment - mins[i].moment).total_seconds() < reqd_dist:
            # Remove the higher of the two local minima
            mins.pop(i if mins[i].low > mins[i + 1].low else i + 1)
        else:
            i += 1

    # Ensure maxima are spread apart by at least 3% of the trendline's period.
    i = 0
    while i < len(maxs) - 1 and len(maxs) >= 3:
        if (maxs[i + 1].moment - maxs[i].moment).total_seconds() < reqd_dist:
            # Remove the lower of the two local maxima.
            maxs.pop(i if maxs[i].high < maxs[i + 1].high else i + 1)
        else:
            i += 1

    return mins, maxs
コード例 #5
0
    def _updates_logic(self, time_to_run: TimeInterval) -> None:
        """
        Starts an infinite loop that runs health checks during time_to_run.
        """
        self.info_process('Starting health checks thread')
        checks_completed = []
        while getattr(threading.current_thread(), "do_run", True):

            # Wait for 6PM to run health checks
            if not time_to_run.contains_time(self.live_time_env.now()):
                checks_completed = []
                pytime.sleep(5)
                continue

            # TODO Ensure we have a valid auth token for the API

            expected_update_time = self.live_time_env.now()

            # Check MongoDB health
            if 'mongo' not in checks_completed:
                self.info_process('Running scheduled mongo model_type')
                # TODO Call API '/api/health_checks/perform?check_type=MONGO'
                # TODO Wait 1 second between /get calls, until last_updated > expected_update_time
                checks_completed.append('mongo')
                continue

            # Check output of dip45 analysis model
            if 'dip45' not in checks_completed:
                self.info_process('Running scheduled dip45 model_type')
                # TODO Call API '/api/health_checks/perform?check_type=DIP45'
                # TODO Wait 1 second between /get calls, until last_updated > expected_update_time
                checks_completed.append('dip45')
                continue

            # Check speed of simulations
            if 'sim-timings' not in checks_completed:
                self.info_process('Running scheduled simulations model_type')
                # TODO Call API '/api/health_checks/perform?check_type=SIMULATION_TIMINGS'
                # TODO Wait 1 second between /get calls, until last_updated > expected_update_time
                checks_completed.append('sim-timings')
                continue

            # Check health of daily data collection and model feeding
            if 'model-feeding' not in checks_completed:
                self.info_process('Running scheduled model feeding check')
                # TODO Call API '/api/health_checks/perform?check_type=MODEL_FEEDING'
                # TODO Wait 1 second between /get calls, until last_updated > expected_update_time
                checks_completed.append('model-feeding')
                continue

            # Check depth and accuracy of symbol data
            for symbol in self.symbols:
                if f'data-{symbol}' not in checks_completed:
                    self.info_process('Running scheduled symbol ({0}) model_type'.format(symbol))
                    # TODO Call API '/api/health_checks/perform?check_type=DATA?symbol={}'
                    # TODO Wait 1 second between /get calls, until last_updated > expected_update_time
                    checks_completed.append('data-' + symbol)
                    break

            # Allow health checks to run again once all have been run
            checks_completed = []
コード例 #6
0
ファイル: market_util.py プロジェクト: maxilie/TC2_public
"""Times"""
OPEN_TIME = time(hour=9, minute=30)
CLOSE_TIME = time(hour=16, minute=0)
"""Time durations in seconds"""
FOR_1_MIN = 60
FOR_15_MINS = FOR_1_MIN * 15
FOR_1_HR = FOR_1_MIN * 60
FOR_24_HRS = FOR_1_HR * 24
# How long the markets are open for on a regular market day, in seconds
OPEN_DURATION = FOR_1_HR * 6.5
# How long the markets are closed for on a regular market day, in seconds
CLOSED_DURATION = FOR_24_HRS - OPEN_DURATION
# How many minutes to wait after markets close before the program trains its analysis models
MODEL_FEED_DELAY = FOR_15_MINS
"""Time intervals"""
ENTIRE_DAY = TimeInterval(None, OPEN_TIME, CLOSE_TIME)
FIRST_45_MINS = TimeInterval(None, OPEN_TIME,
                             (datetime.combine(datetime.today(), OPEN_TIME) +
                              timedelta(minutes=45)).time())


def calculate_holidays() -> List[date]:
    """Calculates market holidays from 2015 - 2030"""
    holidays = []
    for year in range(2015, 2030):
        holidays.extend(_get_holidays_in_year(year))
    return holidays


def _get_holidays_in_year(year: int) -> List[date]:
    """Calculates all the market holidays for the given year."""