Exemplo n.º 1
0
def doctor(doctorId):
	_userId = 1
        u = UserDispatcher()
        _doctor = u.get(doctorId,False)
	_d = Data(_userId)
	_hm_hr,_hm_eda,_hm_temp  = _d.getHeatMapSessions(True)
	return render_template("doctor.html",_hm_hr = _hm_hr,_hm_eda=_hm_eda,_hm_temp= _hm_temp, _patientID = _userId, _doctor = _doctor)
Exemplo n.º 2
0
    def __init__(self,
                 logger,
                 data,
                 capital_allowed,
                 live_mode,
                 default_ticker=None,
                 default_period=None):
        """
		- logger: a Logger instance linked to a bot
		- data: a Data instance linked to a bot
		- capital_allowed: float, percentage (0-100) of the capital this instance is able to trade with
		- live_mode: bool, should we make real orders on the markets or simulate them
		- default_ticker: string, the ticker formatted like that: ASSET1/ASSET2, optional 
		- default_period: string, the period resolution you want to get data in (1m, 5m, 1h...), optional
		"""
        self.logger = logger
        self.data = data
        self.capital_allowed = capital_allowed
        self.default_ticker = default_ticker
        self.default_period = default_period
        self.live_mode = live_mode
        self.fake_balance = []
        self.fake_pnl = []
        self.fake_current_price = None
        self.fake_current_date = None
        self.fake_orders = []
        if (self.default_period and self.default_ticker):
            self.cache = Data(
                f"{self.default_period}-{''.join(self.default_ticker.split('/'))}-cache"
            )
        else:
            self.cache = None
        self.client = ccxt.binance(config.get_creds()['binance'])
Exemplo n.º 3
0
def doctor_patient(doctorId,patientId):
        u = UserDispatcher()
        _doctor = u.get(doctorId,False)
        _cpatient = u.get(patientId,False)
	_d = Data(patientId)
	_hm_hr,_hm_eda,_hm_temp  = _d.getHeatMapSessions(True)
	return render_template("doctor_patient.html",_hm_hr = _hm_hr,_hm_eda=_hm_eda,_hm_temp= _hm_temp, _patientID = patientId, _doctor = _doctor,_cpatient = _cpatient)
Exemplo n.º 4
0
 def _count_macd(self, date):
     """
     Moving Average Convergence/Divergence
     :link https://en.wikipedia.org/wiki/MACD
     """
     period1, period2, period3 = self.params
     if period1 > period2:
         # period1 should always be less than period2
         period1, period2 = period2, period2
     # Obtaining the needed data
     Count.count_once(
         ['EMA(' + str(period1) + ')', 'EMA(' + str(period2) + ')'],
         self.ticker,
         date=date)
     data = Data.get(
         ['EMA(' + str(period1) + ')', 'EMA(' + str(period2) + ')'],
         self.ticker,
         date=date)
     alpha = 2 / (period3 + 1)
     initial_sum = 0
     prev_signal = 0
     for index, (dtime, ema1, ema2) in enumerate(data):
         ema_diff = ema1 - ema2
         if index < period3 - 1:
             initial_sum += ema_diff
             continue
         elif index == period3 - 1:
             signal = round((initial_sum + ema_diff) / period3)
         else:
             signal = round(ema_diff * alpha + prev_signal * (1 - alpha))
         self.update(dtime, signal)
         prev_signal = signal
     self.commit()
Exemplo n.º 5
0
	def __init__(self, name, ticker, period, live_mode, periods_needed=200):
		"""
		- name: string, the name of the bot
		- ticker: string, the ticker formatted like that: ASSET1/ASSET2
		- period: string, the period on which the loop will be set, and the resolution of the candles
		- live_mode: bool, should we launch the live loop and start trading live
		- periods_needed: int, the number of candles you will get every loop, optional
		"""
		self.live_mode = live_mode
		self.name = name
		self.ticker = ticker
		self.period_text = period
		self.periods_needed = periods_needed
		self.offset_seconds = 10
		if (not self.name in config.get_config()):
			print("❌ Cannot instantiate bot: no config entry")
			exit(1)
		self.config = config.get_config()[self.name]
		if (not "capitalAllowed" in self.config):
			print("❌ Cannot instantiate bot: no 'capitalAllowed' property")
			exit(1)
		try:
			self.logger = Logger(self.name, live_mode)
		except:
			print("❌ Cannot connect to the log DB, are you sure it's running?")
			raise
		if (self.live_mode):
			self.data = Data(self.name)
		else:
			self.data = Data(self.name + "-test")
		self.exchange = Exchange(self.logger, self.data, self.config['capitalAllowed'], live_mode, self.ticker, self.period_text)
		try:
			self.period = period_matching[period]
		except:
			print("Available periods: 1m, 3m, 5m, 15m, 30m, 1h, 2h, 3h, 4h, 1d, 1w")
			raise
		self.logger.log("ℹ️", f"Bot {self.name} started with a period of {period}")
		self.logger.log("ℹ️", f"Capital allowed: {self.config['capitalAllowed']}%")
		self.setup()
		if (self.live_mode):
			self.preloop()
Exemplo n.º 6
0
 def reset(self):
     data_instance = Data.init_from_config_dic(config_dict)
     self.model = Model(data_instance)
     self.T = WARMUP_TIME_SECONDS
     # run the warm up period
     for t in range(self.T, self.T + 3600, INT_ASSIGN):
         self.model.dispatch_at_time(t)
     self.T = ANALYSIS_TIME_SECONDS
     print("##########################")
     print("##########################")
     print("End of the warm up time ")
     print("##########################")
     print("##########################")
Exemplo n.º 7
0
 def count(indicators, ticker, date=None):
     """ Count the requested set of indicators """
     indicators = Count.__fix_indicators_list(indicators)
     if date is not None and isinstance(date, str):
         date = datetime.datetime.strptime(date, '%Y-%m-%d')
     for indicator in indicators:
         counter = Count.__get_indicator_counter(ticker, indicator)
         if date is not None:
             # Counting for one particular date
             counter.count(date)
         else:
             # Counting indicator for all trade days
             for date in Data.trade_dates(ticker):
                 counter.count(date)
     return None
Exemplo n.º 8
0
Arquivo: SMA.py Projeto: rsukhar/ft
 def _count_sma(self, date):
     """
     Simple Moving Average
     :link https://en.wikipedia.org/wiki/Moving_average#Simple_moving_average
     """
     data = Data.get(['vwap'], self.ticker, date=date, market_hours=True)
     period = self.params[0]
     prices = []
     for dtime, price in data:
         prices.append(price)
         if len(prices) > period:
             del prices[0]
         if len(prices) == period:
             value = round(sum(prices) / period)
             self.update(dtime, value)
     self.commit()
Exemplo n.º 9
0
Arquivo: EMA.py Projeto: rsukhar/ft
 def _count_ema(self, date):
     """
     Exponential Moving Average
     :link https://en.wikipedia.org/wiki/Moving_average#Exponential_moving_average
     """
     data = Data.get(['vwap'], self.ticker, date=date, market_hours=True)
     period = self.params[0]
     alpha = 2 / (period + 1)
     initial_sum = 0
     prev_value = 0
     for index, (dtime, price) in enumerate(data):
         if index < period - 1:
             initial_sum += price
             continue
         elif index == period - 1:
             value = round((initial_sum + price) / period)
         else:
             value = round(price * alpha + prev_value * (1 - alpha))
         self.update(dtime, value)
         prev_value = value
     self.commit()
Exemplo n.º 10
0
 def count_once(indicators, ticker, date=None):
     """ Count the requested set of indicators if they were not counted previously """
     indicators = Count.__fix_indicators_list(indicators)
     # Getting data 1-minute slice from the very middle of the day to check which data presents and which is missing
     if date is not None and isinstance(date, str):
         date = datetime.datetime.strptime(date, '%Y-%m-%d')
     date_mid = tradetime.daymid(date)
     missing_indicators = []
     data = list(
         Data.get(indicators,
                  ticker,
                  dtime_from=date_mid,
                  dtime_to=date_mid,
                  market_hours=False))
     if len(data) == 0:
         missing_indicators = list(indicators)
     else:
         for index, value in enumerate(data[0]):
             if index > 0 and value is None:
                 missing_indicators.append(indicators[index - 1])
     if len(missing_indicators) > 0:
         Count.count(missing_indicators, ticker, date)
Exemplo n.º 11
0
Arquivo: Chance.py Projeto: rsukhar/ft
 def _count_chance(self, date):
     """
     Relative price difference in the next N minutes
     """
     data = Data.get(['open', 'vwap'],
                     self.ticker,
                     date=date,
                     market_hours=True,
                     order='desc')
     period = self.params[0]
     history = []
     index = 0
     for dtime, open, vwap in data:
         index += 1
         if index > period:
             index = 1
         if len(history) < index:
             history.append(vwap)
         else:
             value = round((history[index - 1] - open) / open * 100, 2)
             history[index - 1] = vwap
             self.update(dtime, value)
     self.commit()
Exemplo n.º 12
0
def sessions(_userId):
	_d = Data(_userId)
	return _d.getSessions()
Exemplo n.º 13
0
class Bot:
	"""This class is an instance of a bot.
	Every bot has a name, a ticker, and period.
	The period can be 1m, 3m, 5m, 15m, 30m, 1h, 2h, 3h, 4h, 1d, 1w.
	A bot can have a period_needed property that will specify how much past data you want at least
	at every loop.
	
	Example: a bot with a time period of 5m and a period_needed of 200 will receive at every loop the 200
	last ticker, 1000 minutes.

	To implement a bot, you just have to override the compute and setup function. Those two functions will be
	called automatically by the timing system.
	Compute will receive the last period_needed candles for the selected asset.

	The data property is a Data object that allows you to store important and persistant information.
	Every important variables or objects should be stored in data, in case the bot is restarted or if the server is down.

	The logger property is an instance of Logger. It allows you to log information in the console and in the
	database and the Dashboard. If you want to log custom metrics, use logger.custom. You will be able to create
	visualizations in Grafana with this logs.

	The config property is the dictionnary with the same name as the bot in the config.

	The exchange property is an instance of Exchange. It allows you to interact with the actual markets.

	The live_mode property indicates if the bot should loop and receive live data. Use it only to test your bot
	live. If you want to backtrack or test your algorithm, leave live_mode = False.
	When live_mode is False, the logger won't log to the DB, and the exchange actions will be simulated.
	"""

	def __init__(self, name, ticker, period, live_mode, periods_needed=200):
		"""
		- name: string, the name of the bot
		- ticker: string, the ticker formatted like that: ASSET1/ASSET2
		- period: string, the period on which the loop will be set, and the resolution of the candles
		- live_mode: bool, should we launch the live loop and start trading live
		- periods_needed: int, the number of candles you will get every loop, optional
		"""
		self.live_mode = live_mode
		self.name = name
		self.ticker = ticker
		self.period_text = period
		self.periods_needed = periods_needed
		self.offset_seconds = 10
		if (not self.name in config.get_config()):
			print("❌ Cannot instantiate bot: no config entry")
			exit(1)
		self.config = config.get_config()[self.name]
		if (not "capitalAllowed" in self.config):
			print("❌ Cannot instantiate bot: no 'capitalAllowed' property")
			exit(1)
		try:
			self.logger = Logger(self.name, live_mode)
		except:
			print("❌ Cannot connect to the log DB, are you sure it's running?")
			raise
		if (self.live_mode):
			self.data = Data(self.name)
		else:
			self.data = Data(self.name + "-test")
		self.exchange = Exchange(self.logger, self.data, self.config['capitalAllowed'], live_mode, self.ticker, self.period_text)
		try:
			self.period = period_matching[period]
		except:
			print("Available periods: 1m, 3m, 5m, 15m, 30m, 1h, 2h, 3h, 4h, 1d, 1w")
			raise
		self.logger.log("ℹ️", f"Bot {self.name} started with a period of {period}")
		self.logger.log("ℹ️", f"Capital allowed: {self.config['capitalAllowed']}%")
		self.setup()
		if (self.live_mode):
			self.preloop()

	def preloop(self):
		"""Waits for the selected period to begin. We use UTC time.
		"""
		while (1):
			current_time = datetime.datetime.utcnow()
			if (self.period < 60):
				if (current_time.minute % self.period == 0 and current_time.second == self.offset_seconds):
					self.loop()
			elif (self.period <= 4 * 60):
				hour_offset = int(self.period / 60)
				if (current_time.hour % hour_offset == 0 and current_time.minute == 0 and current_time.second == self.offset_seconds):
					self.loop()
			elif (self.period <= 1 * 60 * 24):
				if (current_time.hour == 0
					and current_time.minute == 0
					and current_time.second == self.offset_seconds):
					self.loop()
			else:
				if (current_time.weekday() == 0
					and current_time.hour == 0
					and current_time.minute == 0
					and current_time.second == self.offset_seconds):
					self.loop()

	def loop(self):
		"""Once we waited for the period to start, we can loop over the periods. At every period we
		call compute with the latest data.
		"""
		while (1):
			current_time = datetime.datetime.utcnow()
			self.logger.log("ℹ️", f"Downloading latest data at {current_time}")
			data = self.exchange.get_latest_data(self.ticker, self.period_text, self.periods_needed)
			self.logger.price(data.iloc[-1]['close'])
			self.compute(data)
			time.sleep(self.offset_seconds + self.period * 60 - datetime.datetime.now().second)

	def backtest(self, start_date, end_date):
		self.exchange.init_fake_balance()
		self.data.reset()
		price = []
		date = []
		data = self.exchange.get_data(start_date, end_date, self.ticker, self.period_text)
		if (data.shape[0] == 0):
			self.logger.log("❌", "No data for the given time frame")
		for i in range(self.periods_needed, data.shape[0]):
			batch = data.iloc[i - self.periods_needed:i]
			self.exchange.fake_current_price = batch.iloc[-1]['close']
			self.exchange.fake_current_date = batch.iloc[-1]['date']
			price.append(batch.iloc[-1]['close'])
			date.append(batch.iloc[-1]['date'])
			self.compute(batch.copy())
		hist = pd.DataFrame()
		hist['date'] = date
		hist['price'] = price
		for order in self.exchange.fake_orders:
			hist.loc[hist['date'] == order['date'], 'action'] = order['action']
		return (self.exchange.fake_balance, self.exchange.fake_pnl, hist)

	def setup(self):
		"""To implement. Set the bot variable, instantiate classes... This will be done once before the bot
		starts.
		"""
		pass

	def compute(self, data):
		"""To implement. Called every period, you have the latest data available. You can here take decisions.
		"""
		pass
def main():
    parser = argparse.ArgumentParser(
        description="Simulation of drivers' behavior")
    parser.add_argument(
        '-f',
        '--fleet',
        help=
        'Fleet sizes to simulate, formatted as comma-separated list (i.e. "-f 250,275,300")'
    )
    parser.add_argument(
        '-m',
        '--multiplier',
        help=
        'Surge multiplier, formatted as comma-separated list (i.e. "-m 1,1.5,2")'
    )
    parser.add_argument('-b', '--bonus', type=int, help='Bonus')
    parser.add_argument('-d', '--demand', help='Percent false demand ')
    parser.add_argument(
        '-k',
        '--know',
        help=
        'Percent knowing fare, formatted as comma-separated list (i.e. "-m 1,1.5,2") '
    )
    parser.add_argument(
        '-p',
        '--pro',
        help=
        'Percent pro drivers, formatted as comma-separated list (i.e. "-m 1,1.5,2") '
    )
    parser.add_argument('-r',
                        '--replications',
                        help='number of times to run the simulation')
    parser.add_argument('-bb', '--beta', help='BETA')
    parser.add_argument('-b_policy', '--bonus_policy', help='bonus per zone ')
    parser.add_argument('-budget', '--budget', help='budget ')
    args = parser.parse_args()
    # TODO: argpars should get the bonus policy as input
    data_instance = Data()
    if args.fleet:
        fleet_sizes = [int(args.fleet)]
    else:
        fleet_sizes = data_instance.FLEET_SIZE

    if args.multiplier:
        # surge = args.multiplier
        surges = [float(x) for x in args.multiplier.split(',')]
    else:
        surges = [data_instance.SURGE_MULTIPLIER]

    if args.know:
        perc_know = [float(args.know)]
    else:
        perc_know = [data_instance.PERCE_KNOW]

    if args.bonus:
        bonus = args.bonus
    else:
        bonus = data_instance.BONUS
    if args.beta:
        beta = float(args.beta)
    else:
        beta = configs_dict["BETA"]

    if args.pro:
        pro_share = [float(x) for x in args.pro.split(',')]
    else:
        pro_share = [data_instance.PRO_SHARE]

    if args.demand:
        percent_false_demand = float(args.demand)
    else:
        percent_false_demand = data_instance.PERCENT_FALSE_DEMAND
    if args.replications:
        n_rep = int(args.replications)
    else:
        n_rep = 1
    if args.bonus_policy:
        bonus_policy = args.bonus_policy
    else:
        bonus_policy = data_instance.BONUS_POLICY
    if args.budget:
        budget = args.budget
    else:
        budget = data_instance.BUDGET
    # output_path = "./Outputs/avg_fare_info/" + str(beta) + "/"

    for fleet_size in fleet_sizes:
        for surge in surges:
            for perc_k in perc_know:
                for pro_s in pro_share:
                    for repl in range(n_rep):
                        output_path = "./Outputs/avg_fare_info/" + str(budget) + "_" + str(bonus_policy) + "_" + \
                                      str(datetime.datetime.now()).split('.')[0] + "/"
                        if not os.path.exists(output_path):
                            os.makedirs(output_path)
                        print("iteration number ", repl)
                        print('Fleet size is {f}'.format(f=fleet_size))
                        print('Surge is {}'.format(surge))
                        print('Percentage knowing fares is {}'.format(perc_k))
                        print('Percentage of professional drivers {}'.format(
                            pro_s))

                        data_instance.FLEET_SIZE = fleet_size
                        data_instance.PRO_SHARE = pro_s
                        data_instance.SURGE_MULTIPLIER = surge
                        data_instance.BONUS = bonus
                        data_instance.PERCENT_FALSE_DEMAND = percent_false_demand
                        data_instance.PERCE_KNOW = perc_k

                        m = Model(data_instance, configs_dict, beta)

                        # start time
                        stime = time.time()

                        # # dispatch the system for T_TOTAL seconds, at the interval of INT_ASSIGN
                        for T in range(data_instance.WARMUP_TIME_SECONDS,
                                       data_instance.T_TOTAL_SECONDS,
                                       data_instance.INT_ASSIGN):
                            m.dispatch_at_time(T)
                        print('Total drivers: ', len(m.vehicles))
                        print(
                            '# of Pro drivers: ',
                            len([
                                v for v in m.vehicles
                                if v.driver_type == DriverType.PROFESSIONAL
                            ]))
                        print(
                            '# of naive drivers: ',
                            len([
                                v for v in m.vehicles
                                if v.driver_type == DriverType.NAIVE
                            ]))
                        print(
                            '# of inexperienced drivers: ',
                            len([
                                v for v in m.vehicles
                                if v.driver_type == DriverType.INEXPERIENCED
                            ]))
                        # end time
                        etime = time.time()
                        # run time of this simulation
                        runtime = etime - stime
                        print("The run time was {runtime} minutes ".format(
                            runtime=runtime / 60))

                        report = m.get_service_rate_per_zone()

                        # So that it doesn't save a file with 1.5.py, rather 15.py
                        ss = str(surge).split('.')
                        ss = ''.join(ss)

                        report.to_csv(output_path + "report for fleet size " +
                                      str(fleet_size) + " surge " + str(ss) +
                                      "fdemand= " + str(percent_false_demand) +
                                      "perc_k " + str(perc_k) + "pro_s " +
                                      str(pro_s) + " repl" + str(repl) +
                                      ".csv")
Exemplo n.º 15
0
def userSessions(_userId):
	_d = Data(_userId)
	_sessions = _d.getSessions(False)
	u = UserDispatcher()
	_user = u.get(_userId,False)
	return render_template("userFeed.html",user = _user,sessions = _sessions)
Exemplo n.º 16
0
def getData(_userId,_sessionId,_type,_json=True):
	_d = Data(_userId)
	_sid = _sessionId
	return _d.getDataFromSession(_sid,_type,_json)
Exemplo n.º 17
0
def main():
    print("Start of main()")
    # TODO: all these should be cleaned up like this:
    #  https://github.com/sisl/MADRL/blob/master/madrl_environments/walker/train_multi_walker.py
    parser = argparse.ArgumentParser(description="Simulation of drivers' behavior")
    parser.add_argument('-f', '--fleet',
                        help='Fleet sizes to simulate, formatted as comma-separated list (i.e. "-f 250,275,300")')
    parser.add_argument('-m', '--multiplier',
                        help='Surge multiplier, formatted as comma-separated list (i.e. "-m 1,1.5,2")')
    parser.add_argument('-b', '--bonus', type=int,
                        help='Bonus')
    parser.add_argument('-d', '--demand',
                        help='Percent false demand ')
    parser.add_argument('-k', '--know',
                        help='Percent knowing fare, formatted as comma-separated list (i.e. "-m 1,1.5,2") ')
    parser.add_argument('-p', '--pro',
                        help='Percent pro drivers, formatted as comma-separated list (i.e. "-m 1,1.5,2") ')
    parser.add_argument('-r', '--replications',
                        help='number of times to run the simulation')
    parser.add_argument('-bb', '--beta',
                        help='BETA')
    parser.add_argument('-b_policy', '--bonus_policy',
                        help='bonus per zone ')
    parser.add_argument('-budget', '--budget',
                        help='budget ')
    args = parser.parse_args()
    # TODO: argpars should get the bonus policy as input
    print("instantiate Data object")
    data_instance = Data()
    if args.fleet:
        fleet_sizes = [int(args.fleet)]
    else:
        fleet_sizes = data_instance.FLEET_SIZE

    if args.multiplier:
        # surge = args.multiplier
        surges = [float(x) for x in args.multiplier.split(',')]
    else:
        surges = [data_instance.SURGE_MULTIPLIER]

    if args.know:
        perc_know = [float(args.know)]
    else:
        perc_know = [data_instance.PERCE_KNOW]

    if args.bonus:
        bonus = args.bonus
    else:
        bonus = data_instance.BONUS
    if args.beta:
        beta = float(args.beta)
    else:
        beta = config_dict["BETA"]

    if args.pro:
        pro_share = [float(x) for x in args.pro.split(',')]
    else:
        pro_share = [data_instance.PRO_SHARE]

    if args.demand:
        percent_false_demand = float(args.demand)
    else:
        percent_false_demand = data_instance.PERCENT_FALSE_DEMAND
    if args.replications:
        n_rep = int(args.replications)
    else:
        n_rep = 5
    if args.bonus_policy:
        bonus_policy = args.bonus_policy
    else:
        bonus_policy = data_instance.BONUS_POLICY
    if args.budget:
        budget = args.budget
    else:
        budget = data_instance.BUDGET
    # output_path = "./Outputs/avg_fare_info/" + str(beta) + "/"

    for fleet_size in fleet_sizes:
        for surge in surges:
            for perc_k in perc_know:
                for pro_s in pro_share:
                    for repl in range(n_rep):
                        # output_path = "./Outputs/avg_fare_info/" + str(budget) + "_" + str(bonus_policy) + "_" + \
                        #               str(datetime.datetime.now()).split('.')[0] + "/"
                        # if not os.path.exists(output_path):
                        #     os.makedirs(output_path)
                        print("iteration number ", repl)
                        print('Fleet size is {f}'.format(f=fleet_size))
                        print('Surge is {}'.format(surge))
                        print('Percentage knowing fares is {}'.format(perc_k))
                        print('Percentage of professional drivers {}'.format(pro_s))

                        data_instance.FLEET_SIZE = fleet_size
                        data_instance.PRO_SHARE = pro_s
                        data_instance.SURGE_MULTIPLIER = surge
                        data_instance.BONUS = bonus
                        data_instance.PERCENT_FALSE_DEMAND = percent_false_demand
                        data_instance.PERCE_KNOW = perc_k
                        print("Instantiated the model")
                        m = Model(data_instance, beta)

                        # start time
                        stime = time.time()

                        # # dispatch the system for T_TOTAL seconds, at the interval of INT_ASSIGN
                        for T in range(data_instance.WARMUP_TIME_SECONDS,
                                       data_instance.T_TOTAL_SECONDS,
                                       data_instance.INT_ASSIGN):
                            m.dispatch_at_time(T)

                        # end time
                        etime = time.time()
                        # run time of this simulation
                        runtime = etime - stime
                        print("The run time was {runtime} minutes ".format(runtime=runtime / 60))

                        m.save_zonal_stats("../performance_stats/")
Exemplo n.º 18
0
class Exchange:
    """This class is used to interact with the market. It's a wrapper for a ccxt exchange object.
	"""
    def __init__(self,
                 logger,
                 data,
                 capital_allowed,
                 live_mode,
                 default_ticker=None,
                 default_period=None):
        """
		- logger: a Logger instance linked to a bot
		- data: a Data instance linked to a bot
		- capital_allowed: float, percentage (0-100) of the capital this instance is able to trade with
		- live_mode: bool, should we make real orders on the markets or simulate them
		- default_ticker: string, the ticker formatted like that: ASSET1/ASSET2, optional 
		- default_period: string, the period resolution you want to get data in (1m, 5m, 1h...), optional
		"""
        self.logger = logger
        self.data = data
        self.capital_allowed = capital_allowed
        self.default_ticker = default_ticker
        self.default_period = default_period
        self.live_mode = live_mode
        self.fake_balance = []
        self.fake_pnl = []
        self.fake_current_price = None
        self.fake_current_date = None
        self.fake_orders = []
        if (self.default_period and self.default_ticker):
            self.cache = Data(
                f"{self.default_period}-{''.join(self.default_ticker.split('/'))}-cache"
            )
        else:
            self.cache = None
        self.client = ccxt.binance(config.get_creds()['binance'])

    def candles_to_df(self, candles):
        data = pd.DataFrame()
        data['timestamp'] = candles[:, 0]
        data['date'] = pd.to_datetime(data['timestamp'] * 1000000)
        data['open'] = candles[:, 1]
        data['high'] = candles[:, 2]
        data['low'] = candles[:, 3]
        data['close'] = candles[:, 4]
        data['volume'] = candles[:, 5]
        return data

    def get_latest_data(self, ticker=None, period=None, length=0):
        """Fetch the latest data for the given ticker. It will return at least lenth candles.
		
		- ticker: string, the ticker formatted like that: ASSET1/ASSET2, optional if default is set
		- period: string, the period resolution you want (1m, 5m, 1h...), optional is default is set
		- length: int, the minimum number of past candles you want, optional
		Returns a pandas dataframe.
		"""
        if (ticker is None):
            ticker = self.default_ticker
        if (period is None):
            period = self.default_period
        candles = None
        try:
            candles = np.array(self.client.fetch_ohlcv(ticker, period))
        except:
            self.logger.log(
                "❗️", "Unable to fetch live data, retrying in 10 seconds")
            time.sleep(10)
            return self.get_latest_data(ticker, length)
        return self.candles_to_df(candles)

    def get_data(self, start_date, end_date, ticker=None, period=None):
        """Get historical data between the given dates.

		- start_date: string, a date formatted in ISO 8601 from when to download data
		- end_date: string, a date formatted in ISO 8601
		"""
        if (ticker is None):
            ticker = self.default_ticker
        if (period is None):
            period = self.default_period
        start = self.client.parse8601(start_date)
        end = self.client.parse8601(end_date)

        candles = None
        last_date = start
        while (last_date < end):
            print(
                f"Downloading {datetime.utcfromtimestamp(last_date / 1000).isoformat()}"
            )
            if (not self.cache is None
                    and not self.cache.get(last_date) is None):
                new_candles = self.cache.get(last_date)
                print("Found in cache")
            else:
                new_candles = np.array(
                    self.client.fetch_ohlcv(ticker, period, last_date))
                if (not self.cache is None):
                    self.cache.set(last_date, new_candles)
                time.sleep(1)
            if (candles is None):
                candles = new_candles
            else:
                candles = np.vstack([candles, new_candles])
            last_date = int(candles[-1][0])
        df = self.candles_to_df(candles)
        return df

    def buy(self, ticker=None, max_try=3):
        """Buy the given ticker.

		- ticker: string, the ticker formatted like that: ASSET1/ASSET2, optional if default is set
		Returns a trade object.
		"""
        if (max_try <= 0):
            self.logger.log("❌", "Failed 3 times to buy, giving up")
            return None
        if (ticker is None):
            ticker = self.default_ticker
        if (not self.live_mode):
            return self.fake_buy(ticker)
        asset1 = ticker.split("/")[0]
        asset2 = ticker.split("/")[1]
        balance = self.get_balance(asset2)
        price = self.client.fetch_ticker(ticker)['last']
        proportion = (self.capital_allowed / 100)
        qty = (balance * proportion) / price
        qty = self.client.amount_to_precision(ticker, qty)
        try:
            self.logger.log("ℹ️", f"Buying {qty}{asset1}")
            trade = self.client.create_market_buy_order(ticker, qty)
            self.logger.log(
                "💵", f"Bought {qty}{asset1} for {trade['price']:.2f}{asset2}")
            self.logger.order('buy', trade['price'], trade['cost'])
            self.data.set("buy_cost", trade['cost'])
            return trade
        except:
            traceback.print_exc()
            self.logger.log("❌", "Cannot buy, retrying in 3 seconds")
            time.sleep(3)
            return self.buy(ticker, max_try - 1)

    def sell(self, ticker=None, max_try=3):
        """Sell the given ticker.

		- ticker: string, the ticker formatted like that: ASSET1/ASSET2, optional if default is set
		Returns a trade object.
		"""
        if (max_try <= 0):
            self.logger.log("❌", "Failed 3 times to sell, giving up")
            return None
        if (ticker is None):
            ticker = self.default_ticker
        if (not self.live_mode):
            return self.fake_sell(ticker)
        asset1 = ticker.split("/")[0]
        asset2 = ticker.split("/")[1]
        balance = self.get_balance(asset1)
        try:
            self.logger.log("ℹ️", f"Selling {balance}{asset1}")
            trade = self.client.create_market_sell_order(ticker, balance)
            self.logger.log(
                "💵", f"Sold {balance}{asset1} for {trade['price']}{asset2}")
            self.logger.order('sell', trade['price'], trade['cost'])
            balance_diff = trade['cost'] - self.data.get("buy_cost")
            self.logger.pnl(balance_diff / self.data.get("buy_cost") * 100,
                            balance_diff)
            self.logger.balance(self.get_balance())
            self.data.remove("buy_cost")
            return trade
        except:
            traceback.print_exc()
            self.logger.log("❌", "Cannot sell, retrying in 3 seconds")
            time.sleep(3)
            return self.sell(ticker, max_try - 1)

    def fake_buy(self, ticker):
        """This functions creates a fake buy order.
		The buy function of a bot in backtracking mode is redirected here.
		It's called automatically by the backtracking algorithm, you shouldn't
		have to use it.
		"""
        self.data.set("buy_price", self.fake_current_price)
        self.fake_orders.append({
            'action': 'buy',
            'date': self.fake_current_date
        })

    def fake_sell(self, ticker):
        """This functions creates a fake sell order.
		The sell function of a bot in backtracking mode is redirected here.
		It's called automatically by the backtracking algorithm, you shouldn't
		have to use it.
		It will calculate estimated PNL for the trade.
		"""
        diff_cost = self.fake_current_price - self.data.get("buy_price")
        diff_per = (diff_cost / self.data.get("buy_price")) * 100
        diff_per -= 0.2
        profit = self.fake_balance[-1] * (diff_per / 100)
        self.fake_balance.append(self.fake_balance[-1] + profit)
        self.fake_pnl.append(diff_per)
        self.data.remove("buy_price")
        self.fake_orders.append({
            'action': 'sell',
            'date': self.fake_current_date
        })

    def get_balance(self, asset=None):
        """Get the balance of the account for the given asset.

		- asset: string, the asset to check, optional if default is set
		Returns the current asset balance as float.
		"""
        if (not self.live_mode):
            return None
        if (asset is None):
            asset = self.default_ticker.split("/")[1]
        try:
            return self.client.fetch_balance()[asset]['free']
        except:
            self.logger.log("❌", f"Cannot fetch balance for {asset}")
            return None

    def init_fake_balance(self):
        """This functions initializes the backtesting fake balance array
		"""
        self.fake_balance = [100]
        self.fake_pnl = []
        self.fake_orders = []
Exemplo n.º 19
0
 def setUp(self):
     self.data = Data('testdb.sqlite')
     self.data.set('runTests', 'true')
Exemplo n.º 20
0
class TestDataMethods(unittest.TestCase):
    def setUp(self):
        self.data = Data('testdb.sqlite')
        self.data.set('runTests', 'true')

    def test_initial_state(self):
        ''' self.data.keys will be empty at first '''
        self.assertEqual(self.data.keys[0], 'runTests')

    def test_get(self):
        ''' self.data.get test '''
        self.assertEqual(self.data.get('runTests'), 'true')

    def test_getAll(self):
        ''' set a couple more keys '''
        self.data.set('anotherKey', 'false')
        self.data.set('maybeOneMore', 'test')

        self.assertEqual(self.data.getAll(), {
            'anotherKey': 'false',
            'runTests': 'true',
            'maybeOneMore': 'test'
        })

    def test_delete(self):
        self.data.delete('runTests')

        self.assertEqual(self.data.get('runTests'), None)

    # def test_get(self):
    #     ''' set a key/value pair '''
    #     self.data.set('runTests','true')

    def tearDown(self):
        os.remove('./data/testdb.sqlite')
def main():
    parser = argparse.ArgumentParser(
        description="Simulation of drivers' behavior")
    # from lib.Constants import PERCE_KNOW
    parser.add_argument(
        '-f',
        '--fleet',
        help=
        'Fleet sizes to simulate, formatted as comma-separated list (i.e. "-f 250,275,300")'
    )
    parser.add_argument(
        '-m',
        '--multiplier',
        help=
        'Surge multiplier, formatted as comma-separated list (i.e. "-m 1,1.5,2")'
    )
    parser.add_argument('-b', '--bonus', type=int, help='Bonus')
    parser.add_argument('-d', '--demand', help='Percent false demand ')
    parser.add_argument('-AV',
                        '--AV_fleet_size',
                        help="Number of Naive drivers ")
    parser.add_argument('-NAIVE',
                        '--NAIVE_fleet_size',
                        help="Number of Naive drivers ")
    parser.add_argument('-PRO',
                        '--PRO_fleet_size',
                        help="Number of Professional drivers ")
    parser.add_argument(
        '-BH',
        '--behavioral_opt',
        help="Perform behavioral optimization, pass 'yes' or 'no' ")
    parser.add_argument('-SURGE',
                        '--surge_pricing',
                        help="should do surge pricing, pass 'yes' or 'no' ")

    parser.add_argument(
        '-k',
        '--know',
        help=
        'Percent knowing fare, formatted as comma-separated list (i.e. "-m 1,1.5,2") '
    )
    parser.add_argument(
        '-p',
        '--pro',
        help=
        'Percent pro drivers, formatted as comma-separated list (i.e. "-m 1,1.5,2") '
    )
    parser.add_argument('-r',
                        '--replications',
                        help='number of times to run the simulation')
    parser.add_argument('-bb', '--beta', help='BETA')
    parser.add_argument('-b_policy', '--bonus_policy', help='bonus per zone ')
    parser.add_argument('-budget', '--budget', help='budget ')
    args = parser.parse_args()
    # TODO: argpars should get the bonus policy as input
    data_instance = Data()

    if args.fleet:
        fleet_sizes = [int(args.fleet)]
    else:
        fleet_sizes = data_instance.FLEET_SIZE

    if args.behavioral_opt:
        if args.behavioral_opt.lower() in ('yes', 'true'):
            do_behavioral_opt = True
        else:
            do_behavioral_opt = False
    else:
        do_behavioral_opt = data_instance.do_behavioral_opt

    if args.surge_pricing:
        if args.surge_pricing.lower() in ('yes', 'true'):
            do_surge_pricing = True
        else:
            do_surge_pricing = False
    else:
        do_surge_pricing = data_instance.do_surge_pricing

    if args.PRO_fleet_size:
        set_of_NUM_OF_PRO_DRIVERS = [int(args.PRO_fleet_size)]
    else:
        set_of_NUM_OF_PRO_DRIVERS = [data_instance.PRO_FLEET_SIZE]

    if args.NAIVE_fleet_size:
        set_of_NUM_OF_NAIVE_DRIVERS = [int(args.NAIVE_fleet_size)]
    else:
        set_of_NUM_OF_NAIVE_DRIVERS = [data_instance.NAIVE_FLEET_SIZE]

    if args.AV_fleet_size:
        set_of_NUM_OF_AV_DRIVERS = [int(args.AV_fleet_size)]
    else:
        set_of_NUM_OF_AV_DRIVERS = [data_instance.AV_FLEET_SIZE]

    if args.multiplier:
        # surge = args.multiplier
        surges = [float(x) for x in args.multiplier.split(',')]
    else:
        surges = [data_instance.SURGE_MULTIPLIER]

    if args.know:
        perc_know = [float(args.know)]
    else:
        perc_know = [data_instance.PERCE_KNOW]

    if args.bonus:
        bonus = args.bonus
    else:
        bonus = data_instance.BONUS
    if args.beta:
        beta = float(args.beta)
    else:
        beta = configs_dict["BETA"]

    if args.pro:
        pro_share = [float(x) for x in args.pro.split(',')]
    else:
        pro_share = [data_instance.PRO_SHARE]

    if args.demand:
        percent_false_demand = float(args.demand)
    else:
        percent_false_demand = data_instance.PERCENT_FALSE_DEMAND
    if args.replications:
        n_rep = int(args.replications)
    else:
        n_rep = 1
    if args.bonus_policy:
        bonus_policy = args.bonus_policy
    else:
        bonus_policy = data_instance.BONUS_POLICY
    if args.budget:
        budget = args.budget
    else:
        budget = data_instance.BUDGET
    # output_path = "./Outputs/avg_fare_info/" + str(beta) + "/"

    from lib.rebalancing_optimizer import RebalancingOpt

    for num_pros in set_of_NUM_OF_PRO_DRIVERS:
        for num_naives in set_of_NUM_OF_NAIVE_DRIVERS:
            for num_avs in set_of_NUM_OF_AV_DRIVERS:
                for surge in surges:
                    for repl in range(n_rep):
                        TOTAL_FLEET_SIZE = 2500
                        num_naives = TOTAL_FLEET_SIZE - num_pros
                        data_instance.AV_FLEET_SIZE = num_avs
                        data_instance.NAIVE_FLEET_SIZE = num_naives
                        data_instance.PRO_FLEET_SIZE = num_pros
                        data_instance.do_behavioral_opt = do_behavioral_opt
                        data_instance.do_surge_pricing = do_surge_pricing

                        if do_behavioral_opt:
                            st = '/with_behavioral_opt/'
                        else:
                            st = '/no_behavioral_opt/'
                        output_path = "./Outputs/" + datetime.datetime.now().strftime("%Y-%m-%d-%H-%M") + \
                                      st + str('Pro_') + str(num_pros) \
                                      + str('NAIVE_') + str(num_naives) \
                                      + str('AV_') + str(num_avs) \
                                      + str('budget_') + str(budget) + "_" \
                                      + str("bonus_policy") + "_" + str(bonus_policy) + "_" \
                                      + str('do_surge') + "_" + str(data_instance.do_surge_pricing) + "_" \
                                      + str('do_opt') + "_" + str(data_instance.do_behavioral_opt) + "_" \
                                      + str(datetime.datetime.now()).split('.')[0] + "/"

                        if not os.path.exists(output_path):
                            os.makedirs(output_path)

                        print("iteration number ", repl)
                        print('Surge is {}'.format(surge))

                        data_instance.SURGE_MULTIPLIER = surge
                        data_instance.BONUS = bonus
                        data_instance.output_path = output_path

                        # data_instance.do_behavioral_opt = False
                        m = Model(data_instance, configs_dict, beta,
                                  output_path)
                        # start time
                        stime = time.time()
                        # dispatch the system for T_TOTAL seconds, at the interval of INT_ASSIGN
                        # TODO: every run should in include the policy from the start
                        # TODO: process Feb's month as well.
                        months = [1, 2]
                        days = [30, 15]
                        stop_month = months[-1]
                        for ix, month in enumerate(months):
                            for d_idx in range(1, days[ix]):
                                stop_day = days[ix]

                                if month == 1 and d_idx >= 15:
                                    # NOTE: THIS WILL NOT HAVE THE DESIRED EFFECT, BC OPERATOR has attribute set in the beginning
                                    data_instance.do_behavioral_opt = True
                                    m.operator.do_behavioral_opt = True

                                    # data_instance.do_surge_pricing = True
                                    # m.operator.do_surge_pricing = True

                                for T in range(
                                        data_instance.WARMUP_TIME_SECONDS,
                                        data_instance.T_TOTAL_SECONDS,
                                        data_instance.INT_ASSIGN):
                                    m.dispatch_at_time(T, day_idx=d_idx)
                                m.get_service_rate_per_zone(d_idx, month)
                                m.get_drivers_earnings_for_one_day(
                                    d_idx, month)
                                m.get_operators_earnings_for_one_day(
                                    d_idx, month)
                                print(
                                    f"Starting a new day, finished day number {d_idx + 1} of month {month}"
                                )
                                print(f"it took {(time.time() - stime) / 60}")
                                m.reset_after_one_day_of_operation(
                                    stop_month, stop_day)

                        if num_pros > 0:
                            all_dfs = pd.concat([
                                v.report_learning_rates() for v in m.vehicles
                                if v.driver_type == DriverType.PROFESSIONAL
                            ],
                                                ignore_index=True)
                            all_dfs.to_csv(output_path +
                                           "fmean for all drivers.csv")

                            all_fare_reliability_dfs = pd.concat(
                                [
                                    v.report_fare_reliability_evolution()
                                    for v in m.vehicles
                                    if v.driver_type == DriverType.PROFESSIONAL
                                ],
                                ignore_index=True)
                            all_fare_reliability_dfs.to_csv(
                                output_path +
                                "fare reliability for all drivers.csv")

                            all_m_reliability_dfs = pd.concat(
                                [
                                    v.report_matching_reliability_evolution()
                                    for v in m.vehicles
                                    if v.driver_type == DriverType.PROFESSIONAL
                                ],
                                ignore_index=True)
                            all_m_reliability_dfs.to_csv(
                                output_path +
                                "matching reliability for all drivers.csv")

                            all_fare_reliability_dfs = pd.concat(
                                [
                                    v.report_surge_bonus_behavior()
                                    for v in m.vehicles
                                    if v.driver_type == DriverType.PROFESSIONAL
                                ],
                                ignore_index=True)
                            all_fare_reliability_dfs.to_csv(
                                output_path +
                                "surge behavior for all drivers.csv")

                        all_earning_dfs = pd.concat(
                            [v.report_final_earnings() for v in m.vehicles],
                            ignore_index=True)
                        all_earning_dfs.to_csv(output_path +
                                               "earnings for all drivers.csv")
                        operators_revenue = m.operator.report_final_revenue()
                        operators_revenue.to_csv(output_path +
                                                 "operators_revenue.csv")

                        print('Total drivers: ', len(m.vehicles))
                        print(
                            '# of Pro drivers: ',
                            len([
                                v for v in m.vehicles
                                if v.driver_type == DriverType.PROFESSIONAL
                            ]))
                        print(
                            '# of naive drivers: ',
                            len([
                                v for v in m.vehicles
                                if v.driver_type == DriverType.NAIVE
                            ]))
                        print(
                            '# of inexperienced drivers: ',
                            len([
                                v for v in m.vehicles
                                if v.driver_type == DriverType.INEXPERIENCED
                            ]))
                        # end time
                        etime = time.time()
                        # run time of this simulation
                        runtime = etime - stime
                        print("The run time was {runtime} minutes ".format(
                            runtime=runtime / 60))

                        report = m.report_final_performance()

                        # So that it doesn't save a file with 1.5.py, rather 15.py
                        ss = str(surge).split('.')
                        ss = ''.join(ss)

                        fleet_size = num_avs + num_pros + num_naives
                        report.to_csv(output_path + "report for fleet size " +
                                      str(fleet_size) + " surge " + str(ss) +
                                      "pro_ " + str(num_pros) + "naive_ " +
                                      str(num_naives) + "AV_" + str(num_avs) +
                                      " repl" + str(repl) + ".csv")
Exemplo n.º 22
0
import numpy as np
from lib.Data import Data
from lib.configs import config_dict
from lib.utils import Model
from lib.Constants import POLICY_UPDATE_INTERVAL, WARMUP_TIME_SECONDS, T_TOTAL_SECONDS, INT_ASSIGN, \
    ANALYSIS_TIME_SECONDS, DEMAND_UPDATE_INTERVAL
import time
data_instance = Data.init_from_config_dic(config_dict)
m = Model(data_instance)

print('Fleet size is {f}'.format(f=data_instance.FLEET_SIZE))

stime = time.time()

# # dispatch the system for T_TOTAL seconds, at the interval of INT_ASSIGN
for T in range(data_instance.WARMUP_TIME_SECONDS,
               data_instance.T_TOTAL_SECONDS,
               data_instance.INT_ASSIGN):
    m.dispatch_at_time(T)

# end time
etime = time.time()
# run time of this simulation
runtime = etime - stime
print("The run time was {runtime} minutes ".format(runtime=runtime / 60))

m.save_zonal_stats("../performance_stats/")