def dataset_changed(**kwargs): """Executed in response to the dataset_changed signal. Makes sure the cron tracker is up-to-date. """ self = Cron.instance set = kwargs['set'] mkt = set.market # see whether we should track this set/market if set.is_active: track_new = set.challenge_end() else: track_new = None # see how we track the market/set now if mkt in self.jobs: track_cur = self.jobs[mkt][1] else: track_cur = None # print("%s <-> %s" % (track_cur, track_new)) # proceed only if stuff changed if track_cur == track_new: return logger.info("Rescheduling market %s" % mkt) if track_cur: #print("Untracking %s. Ends at %s" % (self.jobs[mkt][:2])) self.jobs[mkt][2].cancel() del self.jobs[mkt] if track_new: Cron.advance_set(set)
def start(self): "Starts the cron scheduler on a new, separate thread. " # allow only one instance running if Cron.instance != None: raise Exception("Cron is already running!") Cron.instance = self # connect to the set changed event dataset_change.connect(Cron.dataset_changed) # start the cron self.thread = Thread(target=self.cron.run, daemon=True) self.thread.start() # get all the active datasets active_sets = set(DataSet.objects.filter(is_active=True)) if not active_sets: logger.info("[Cron] No active markets. ") return logger.info( "Tracking %d currently active market(s): %s" % (len(active_sets), ", ".join([str(s.market) for s in active_sets]))) # advance and start tracking the active sets, if needed for s in active_sets: self.advance_set(s)
def start(self): "Starts the cron scheduler on a new, separate thread. " # allow only one instance running if Cron.instance != None: raise Exception("Cron is already running!") Cron.instance = self # connect to the set changed event dataset_change.connect(Cron.dataset_changed) # start the cron self.thread = Thread(target=self.cron.run, daemon=True) self.thread.start() # get all the active datasets active_sets = set(DataSet.objects.filter(is_active=True)) if not active_sets: logger.info("[Cron] No active markets. ") return logger.info("Tracking %d currently active market(s): %s" % (len(active_sets), ", ".join([str(s.market) for s in active_sets]))) # advance and start tracking the active sets, if needed for s in active_sets: self.advance_set(s)
def on_dataset_expired(sender, **kwargs): """Handles challenge (datum) expirations in the markets and sends them to the market's maker. """ datum = kwargs['datum'] mkt_type = datum.data_set.market.type logger.info("Finalising challenge '%s' that ended at '%s' using the '%s' maker. " % (str(datum), datum.data_set.challenge_end(), mkt_type)) market_handler = MarketConfig.market_types.get(mkt_type) market_handler.end_challenge(datum)
def on_dataset_expired(sender, **kwargs): """Handles challenge (datum) expirations in the markets and sends them to the market's maker. """ datum = kwargs['datum'] mkt_type = datum.data_set.market.type logger.info( "Finalising challenge '%s' that ended at '%s' using the '%s' maker. " % (str(datum), datum.data_set.challenge_end(), mkt_type)) market_handler = MarketConfig.market_types.get(mkt_type) market_handler.end_challenge(datum)
def on_order_placed(sender, **kwargs): "Handles creation of orders by dispatching them to the appropriate market maker. " ord = kwargs['order'] acc = ord.account market = acc.market mkt_type = market.type market_handler = MarketConfig.market_types.get(mkt_type) assert (not ord.is_processed()) assert (market_handler != None) logger.info("Sending order '%s' from user '%s' placed at '%s' to the '%s' handler. " % (str(ord), str(acc.user), ord.timestamp, mkt_type)) market_handler.order_placed(ord)
def on_order_placed(sender, **kwargs): "Handles creation of orders by dispatching them to the appropriate market maker. " ord = kwargs['order'] acc = ord.account market = acc.market mkt_type = market.type market_handler = MarketConfig.market_types.get(mkt_type) assert (not ord.is_processed()) assert (market_handler != None) logger.info( "Sending order '%s' from user '%s' placed at '%s' to the '%s' handler. " % (str(ord), str(acc.user), ord.timestamp, mkt_type)) market_handler.order_placed(ord)
def next(self): """ Advances this active set to the next datum (challenge) _once_, and raises the dataset_expired signal. If there is no datum with such id, the set is made inactive. Returns whether the set is active. """ assert self.is_active # Continue only if there is data in the set # should not typically arrive here if not self.has_data(): logger.info("Abruptly ended empty dataset %s (no challenges whatsoever). " % (self.active_datum_id, str(self))) self.stop() return # get the current challenge try: old_datum = self.active_datum() except ObjectDoesNotExist: # log an error and deactive the set self.stop() logger.error("Unable to find the active data point with id: %d. Stopping the set. " % (self.active_datum_id)) return except MultipleObjectsReturned: raise Exception("Too many points with id: %d! Invalid state?.. " % (self.id)) # see if we actually need to advance to the next challenge. if not self.challenge_expired(): return # raise the dataset_expired signal dataset_expired.send(self.__class__, datum=old_datum) # grab the next challenge (datum) try: self.active_datum_id = self.next_challenge_id() except: # make it inactive if no next datum (this was the last) self.is_active = False logger.info("Ended challenge #%d for dataset %s (no next challenge). " % (self.active_datum_id, str(self))) self.save() return self.challenge_start = self.challenge_end() logger.info("Started next challenge #%d for dataset %s. Ends at %s" % (self.active_datum_id, str(self), self.challenge_end())) self.save() return self.is_active