def __init__(self, **kwargs): self.kwargs = kwargs self.window_name = kwargs.get("window_name") self.is_launched = True self.if_move_window = kwargs.get('move_window') self.window_controller = WindowController() self.game_launcher = ExecutableGameLauncher(**kwargs)
def __init__(self, **kwargs): super().__init__(**kwargs) self.config = config.get(f"{self.__class__.__name__}Plugin") self.platform = kwargs.get("platform") self.window_id = None self.window_name = kwargs.get("window_name") self.window_geometry = None self.window_controller = WindowController() self.is_launched = False self.frame_grabber_process = None self.game_frame_limiter = GameFrameLimiter( fps=self.config.get("fps", 4)) self.api_class = None self.api_instance = None self.sprites = self._discover_sprites() self.redis_client = StrictRedis(**config["redis"]) self.kwargs = kwargs
def window_name(): clear_terminal() print("Open the Game manually.") input("\nPress Enter and then focus the game window...") window_controller = WindowController() time.sleep(5) focused_window_name = window_controller.get_focused_window_name() print( f"\nGame Window Detected! Please set the kwargs['window_name'] value in the Game plugin to:" ) print("\n" + focused_window_name + "\n")
def __init__(self, **kwargs): super().__init__(**kwargs) self.config = config.get(f"{self.__class__.__name__}Plugin", dict()) self.platform = kwargs.get("platform") default_input_controller_backend = InputControllers.CLIENT self.input_controller = kwargs.get( "input_controller") or default_input_controller_backend self.window_id = None self.window_name = kwargs.get("window_name") self.window_geometry = None self.dashboard_window_id = None self.window_controller = WindowController() self.is_launched = False self.frame_grabber_process = None self.frame_transformation_pipeline_string = None self.crossbar_process = None self.input_controller_process = None self.game_frame_limiter = GameFrameLimiter( fps=self.config.get("fps", 30)) self.api_class = None self.api_instance = None self.environments = dict() self.environment_data = dict() self.sprites = self._discover_sprites() self.redis_client = StrictRedis(**config["redis"]) self.pause_callback_fired = False self.kwargs = kwargs
class Game: def __init__(self, **kwargs): self.kwargs = kwargs self.window_name = kwargs.get("window_name") self.is_launched = True self.if_move_window = kwargs.get('move_window') self.window_controller = WindowController() self.game_launcher = ExecutableGameLauncher(**kwargs) def launch(self, dry_run=False): self.before_launch() if not dry_run: self.game_launcher.launch(**self.kwargs) self.after_launch() def before_launch(self): pass def after_launch(self): self.is_launched = True time.sleep(3) self.window_id = self.window_controller.locate_window(self.window_name) if self.if_move_window: self.window_controller.move_window(self.window_id, 0, 0) self.window_controller.focus_window(self.window_id) self.window_geometry = self.extract_window_geometry() print(self.window_geometry) return self.window_geometry def extract_window_geometry(self): if self.is_launched: return self.window_controller.get_window_geometry(self.window_id) return None def is_focused(self): return self.window_controller.is_window_focused(self.window_id)
class Game(offshoot.Pluggable): def __init__(self, **kwargs): super().__init__(**kwargs) self.config = config.get(f"{self.__class__.__name__}Plugin", dict()) self.platform = kwargs.get("platform") default_input_controller_backend = InputControllers.CLIENT self.input_controller = kwargs.get( "input_controller") or default_input_controller_backend self.window_id = None self.window_name = kwargs.get("window_name") self.window_geometry = None self.dashboard_window_id = None self.window_controller = WindowController() self.is_launched = False self.frame_grabber_process = None self.frame_transformation_pipeline_string = None self.crossbar_process = None self.input_controller_process = None self.game_frame_limiter = GameFrameLimiter( fps=self.config.get("fps", 30)) self.api_class = None self.api_instance = None self.environments = dict() self.environment_data = dict() self.sprites = self._discover_sprites() self.redis_client = StrictRedis(**config["redis"]) self.pause_callback_fired = False self.kwargs = kwargs @property @offshoot.forbidden def game_name(self): return self.__class__.__name__.replace("Serpent", "").replace("Game", "") @property @offshoot.forbidden def game_launcher(self): return self.game_launchers.get(self.platform) @property @offshoot.forbidden def game_launchers(self): return { "steam": SteamGameLauncher, "executable": ExecutableGameLauncher, "web_browser": WebBrowserGameLauncher } @property @offshoot.expected def screen_regions(self): raise NotImplementedError() @property @offshoot.forbidden def api(self): if self.api_instance is None: self.api_instance = self.api_class(game=self) else: return self.api_instance @property @offshoot.forbidden def is_focused(self): return self.window_controller.is_window_focused(self.window_id) @offshoot.forbidden def launch(self, dry_run=False): self.before_launch() if not dry_run: self.game_launcher().launch(**self.kwargs) self.after_launch() @offshoot.forbidden def relaunch(self, before_relaunch=None, after_relaunch=None): clear_terminal() print("") print("Relaunching the game...") self.stop_frame_grabber() time.sleep(1) if before_relaunch is not None: before_relaunch() time.sleep(1) subprocess.call(shlex.split(f"serpent launch {self.game_name}")) self.launch(dry_run=True) self.start_frame_grabber() self.redis_client.delete(config["frame_grabber"]["redis_key"]) while self.redis_client.llen( config["frame_grabber"]["redis_key"]) == 0: time.sleep(0.1) self.window_controller.focus_window(self.window_id) if after_relaunch is not None: after_relaunch() def before_launch(self): pass def after_launch(self): self.is_launched = True current_attempt = 1 while current_attempt <= 100: self.window_id = self.window_controller.locate_window( self.window_name) if self.window_id not in [0, "0"]: break time.sleep(0.1) time.sleep(3) if self.window_id in [0, "0"]: raise SerpentError("Game window not found...") self.window_controller.move_window(self.window_id, 0, 0) self.dashboard_window_id = self.window_controller.locate_window( "Serpent.AI Dashboard") # TODO: Test on macOS and Linux if self.dashboard_window_id is not None and self.dashboard_window_id not in [ 0, "0" ]: self.window_controller.bring_window_to_top( self.dashboard_window_id) self.window_controller.focus_window(self.window_id) self.window_geometry = self.extract_window_geometry() print(self.window_geometry) def play(self, game_agent_class_name="GameAgent", frame_handler=None, **kwargs): if not self.is_launched: raise GameError( f"Game '{self.__class__.__name__}' is not running...") self.start_crossbar() time.sleep(3) self.start_input_controller() game_agent_class = offshoot.discover( "GameAgent", selection=game_agent_class_name).get(game_agent_class_name, GameAgent) if game_agent_class is None: raise GameError( "The provided Game Agent class name does not map to an existing class..." ) game_agent = game_agent_class(game=self, input_controller=InputController( game=self, backend=self.input_controller), **kwargs) # Look if we need to auto-append PNG to frame transformation pipeline based on given frame_handler png_frame_handlers = ["RECORD"] if frame_handler in png_frame_handlers and self.frame_transformation_pipeline_string is not None: if not self.frame_transformation_pipeline_string.endswith("|PNG"): self.frame_transformation_pipeline_string += "|PNG" self.start_frame_grabber() self.redis_client.delete(config["frame_grabber"]["redis_key"]) while self.redis_client.llen( config["frame_grabber"]["redis_key"]) == 0: time.sleep(0.1) self.window_controller.focus_window(self.window_id) # Override FPS Config? if frame_handler == "RECORD": self.game_frame_limiter = GameFrameLimiter(fps=10) try: while True: self.game_frame_limiter.start() game_frame, game_frame_pipeline = self.grab_latest_frame() try: if self.is_focused: self.pause_callback_fired = False game_agent.on_game_frame(game_frame, game_frame_pipeline, frame_handler=frame_handler, **kwargs) else: if not self.pause_callback_fired: print("PAUSED\n") game_agent.on_pause(frame_handler=frame_handler, **kwargs) self.pause_callback_fired = True time.sleep(1) except Exception as e: raise e # print(e) # time.sleep(0.1) self.game_frame_limiter.stop_and_delay() except Exception as e: raise e finally: self.stop_frame_grabber() self.stop_input_controller() self.stop_crossbar() @offshoot.forbidden def extract_window_geometry(self): if self.is_launched: return self.window_controller.get_window_geometry(self.window_id) return None @offshoot.forbidden def start_frame_grabber(self, pipeline_string=None): if not self.is_launched: raise GameError( f"Game '{self.__class__.__name__}' is not running...") if self.frame_grabber_process is not None: self.stop_frame_grabber() frame_grabber_command = f"serpent grab_frames {self.window_geometry['width']} {self.window_geometry['height']} {self.window_geometry['x_offset']} {self.window_geometry['y_offset']}" pipeline_string = pipeline_string or self.frame_transformation_pipeline_string if pipeline_string is not None: frame_grabber_command += f" {pipeline_string}" self.frame_grabber_process = subprocess.Popen( shlex.split(frame_grabber_command)) signal.signal(signal.SIGINT, self._handle_signal_frame_grabber) signal.signal(signal.SIGTERM, self._handle_signal_frame_grabber) atexit.register(self._handle_signal_frame_grabber, 15, None, False) @offshoot.forbidden def stop_frame_grabber(self): if self.frame_grabber_process is None: return None self.frame_grabber_process.kill() self.frame_grabber_process = None atexit.unregister(self._handle_signal_frame_grabber) @offshoot.forbidden def grab_latest_frame(self): game_frame_buffer, game_frame_buffer_pipeline = FrameGrabber.get_frames_with_pipeline( [0]) return game_frame_buffer.frames[0], game_frame_buffer_pipeline.frames[ 0] @offshoot.forbidden def start_crossbar(self): if self.crossbar_process is not None: self.stop_crossbar() crossbar_command = f"crossbar start --config crossbar.json" self.crossbar_process = subprocess.Popen(shlex.split(crossbar_command)) signal.signal(signal.SIGINT, self._handle_signal_crossbar) signal.signal(signal.SIGTERM, self._handle_signal_crossbar) atexit.register(self._handle_signal_crossbar, 15, None, False) @offshoot.forbidden def stop_crossbar(self): if self.crossbar_process is None: return None self.crossbar_process.kill() self.crossbar_process = None atexit.unregister(self._handle_signal_crossbar) @offshoot.forbidden def start_input_controller(self): if self.input_controller_process is not None: self.stop_input_controller() self.redis_client.set("SERPENT:GAME", self.__class__.__name__) input_controller_command = f"python -m serpent.wamp_components.input_controller_component" self.input_controller_process = subprocess.Popen( shlex.split(input_controller_command)) signal.signal(signal.SIGINT, self._handle_signal_input_controller) signal.signal(signal.SIGTERM, self._handle_signal_input_controller) atexit.register(self._handle_signal_input_controller, 15, None, False) @offshoot.forbidden def stop_input_controller(self): if self.input_controller_process is None: return None self.input_controller_process.kill() self.input_controller_process = None atexit.unregister(self._handle_signal_input_controller) def _discover_sprites(self): plugin_path = offshoot.config["file_paths"]["plugins"] sprites = dict() sprite_path = f"{plugin_path}/{self.__class__.__name__}Plugin/files/data/sprites" if os.path.isdir(sprite_path): files = os.scandir(sprite_path) for file in files: if file.name.endswith(".png"): sprite_name = "_".join( file.name.split("/")[-1].split("_")[:-1]).replace( ".png", "").upper() sprite_image_data = skimage.io.imread( f"{sprite_path}/{file.name}") sprite_image_data = sprite_image_data[..., np.newaxis] if sprite_name not in sprites: sprite = Sprite(sprite_name, image_data=sprite_image_data) sprites[sprite_name] = sprite else: sprites[sprite_name].append_image_data( sprite_image_data) return sprites def _handle_signal_frame_grabber(self, signum=15, frame=None, do_exit=True): if self.frame_grabber_process is not None: if self.frame_grabber_process.poll() is None: self.frame_grabber_process.send_signal(signum) if do_exit: exit() def _handle_signal_crossbar(self, signum=15, frame=None, do_exit=True): if self.crossbar_process is not None: if self.crossbar_process.poll() is None: self.crossbar_process.send_signal(signum) if do_exit: exit() def _handle_signal_input_controller(self, signum=15, frame=None, do_exit=True): if self.input_controller_process is not None: if self.input_controller_process.poll() is None: self.input_controller_process.send_signal(signum) if do_exit: exit()
class Game(offshoot.Pluggable): def __init__(self, **kwargs): super().__init__(**kwargs) self.config = config.get(f"{self.__class__.__name__}Plugin") self.platform = kwargs.get("platform") self.window_id = None self.window_name = kwargs.get("window_name") self.window_geometry = None self.window_controller = WindowController() self.is_launched = False self.frame_grabber_process = None self.game_frame_limiter = GameFrameLimiter( fps=self.config.get("fps", 4)) self.api_class = None self.api_instance = None self.sprites = self._discover_sprites() self.redis_client = StrictRedis(**config["redis"]) self.kwargs = kwargs @property @offshoot.forbidden def game_launcher(self): return self.game_launchers.get(self.platform) @property @offshoot.forbidden def game_launchers(self): return { "steam": SteamGameLauncher, "executable": ExecutableGameLauncher } @property @offshoot.expected def screen_regions(self): raise NotImplementedError() @property @offshoot.expected def ocr_presets(self): raise NotImplementedError() @property @offshoot.forbidden def api(self): if self.api_instance is None: self.api_instance = self.api_class(game=self) else: return self.api_instance @property @offshoot.forbidden def is_focused(self): return self.window_controller.is_window_focused(self.window_id) @offshoot.forbidden def launch(self, dry_run=False): self.before_launch() if not dry_run: self.game_launcher().launch(**self.kwargs) self.after_launch() def before_launch(self): pass def after_launch(self): self.is_launched = True time.sleep(5) self.window_id = self.window_controller.locate_window(self.window_name) self.window_controller.move_window(self.window_id, 0, 0) self.window_controller.focus_window(self.window_id) self.window_geometry = self.extract_window_geometry() print(self.window_geometry) def play(self, game_agent_class_name=None, frame_handler=None, **kwargs): if not self.is_launched: raise GameError( f"Game '{self.__class__.__name__}' is not running...") game_agent_class = offshoot.discover("GameAgent").get( game_agent_class_name, GameAgent) if game_agent_class is None: raise GameError( "The provided Game Agent class name does not map to an existing class..." ) game_agent = game_agent_class( game=self, input_controller=InputController(game=self)) self.start_frame_grabber() self.redis_client.delete(config["frame_grabber"]["redis_key"]) while self.redis_client.llen( config["frame_grabber"]["redis_key"]) == 0: time.sleep(0.1) self.window_controller.focus_window(self.window_id) while True: self.game_frame_limiter.start() game_frame = self.grab_latest_frame() try: if self.is_focused: game_agent.on_game_frame(game_frame, frame_handler=frame_handler, **kwargs) else: serpent.utilities.clear_terminal() print("PAUSED\n") game_agent.on_pause(frame_handler=frame_handler, **kwargs) time.sleep(1) except Exception as e: raise e # print(e) # time.sleep(0.1) self.game_frame_limiter.stop_and_delay() @offshoot.forbidden def extract_window_geometry(self): if self.is_launched: return self.window_controller.get_window_geometry(self.window_id) return None @offshoot.forbidden def start_frame_grabber(self): if not self.is_launched: raise GameError( f"Game '{self.__class__.__name__}' is not running...") if self.frame_grabber_process is not None: self.stop_frame_grabber() frame_grabber_command = f"serpent grab_frames {self.window_geometry['width']} {self.window_geometry['height']} {self.window_geometry['x_offset']} {self.window_geometry['y_offset']}" self.frame_grabber_process = subprocess.Popen( shlex.split(frame_grabber_command)) signal.signal(signal.SIGINT, self._handle_signal) signal.signal(signal.SIGTERM, self._handle_signal) atexit.register(self._handle_signal, 15, None, False) @offshoot.forbidden def stop_frame_grabber(self): if self.frame_grabber_process is None: return None self.frame_grabber_process.kill() self.frame_grabber_process = None atexit.unregister(self._handle_signal) @offshoot.forbidden def grab_latest_frame(self): game_frame_buffer = FrameGrabber.get_frames( [0], (self.window_geometry.get("height"), self.window_geometry.get("width"), 3)) return game_frame_buffer.frames[0] def _discover_sprites(self): plugin_path = offshoot.config["file_paths"]["plugins"] sprites = dict() sprite_path = f"{plugin_path}/{self.__class__.__name__}Plugin/files/data/sprites" if os.path.isdir(sprite_path): files = os.scandir(sprite_path) for file in files: if file.name.endswith(".png"): sprite_name = "_".join( file.name.split("/")[-1].split("_")[:-1]).replace( ".png", "").upper() sprite_image_data = skimage.io.imread( f"{sprite_path}/{file.name}") sprite_image_data = sprite_image_data[..., np.newaxis] if sprite_name not in sprites: sprite = Sprite(sprite_name, image_data=sprite_image_data) sprites[sprite_name] = sprite else: sprites[sprite_name].append_image_data( sprite_image_data) return sprites def _handle_signal(self, signum=15, frame=None, do_exit=True): if self.frame_grabber_process is not None: if self.frame_grabber_process.poll() is None: self.frame_grabber_process.send_signal(signum) if do_exit: exit()
def __init__(self, fake=False, metrics_key='001'): with open('running', 'w') as f: f.write(str(os.getpid())) self._episode_ended = False self.game = serpent.initialize_game('T4TF1') game_frame = self.game.screen_regions['GAME_REGION'] self.width = 10 self.height = 10 self.state_shape = (int(self.height / 2), int(self.width / 2), 1) self._action_spec = array_spec.BoundedArraySpec( shape=(), dtype=np.int32, minimum=0, maximum=1, name='action') self._observation_spec = array_spec.BoundedArraySpec( shape=self.state_shape, dtype=np.float32, minimum=0.0, name='observation') self._state = np.zeros(self.state_shape).astype(np.float32) if fake: return self.interrupted = False self.game.launch() self.game.start_frame_grabber() self.input_controller = InputController(game=self.game) # self.input_proc = self.frame_buffer = FrameGrabber.get_frames([0]) self.frame_buffer = self.extract_game_area(self.frame_buffer) self.width = self.frame_buffer[0].shape[1] self.height = self.frame_buffer[0].shape[0] print('width: %d' % self.width) print('height: %d' % self.height) self.state_shape = (self.height, self.width, 3) self._action_spec = array_spec.BoundedArraySpec( shape=(), dtype=np.int32, minimum=0, maximum=1, name='action') self._observation_spec = array_spec.BoundedArraySpec( shape=self.state_shape, dtype=np.float32, minimum=0.0, name='observation') self._state = np.zeros(self.state_shape).astype(np.float32) # print('created input with pid: %s' % self.input_proc.pid) self.sell_keys = [KeyboardKey.KEY_LEFT_SHIFT, KeyboardKey.KEY_LEFT_CTRL, KeyboardKey.KEY_S] self.buy_keys = [KeyboardKey.KEY_LEFT_SHIFT, KeyboardKey.KEY_LEFT_CTRL, KeyboardKey.KEY_B] self.step_keys = [KeyboardKey.KEY_LEFT_SHIFT, KeyboardKey.KEY_LEFT_CTRL, KeyboardKey.KEY_F] self.visual_debugger = VisualDebugger() self.scraper = T4Scraper(game=self.game, visual_debugger=self.visual_debugger) frame = self.game.grab_latest_frame() self.scraper.current_frame = frame self.pl = 0 self.working_trade = 0 self.current_action = '' self.held = False self.fill_count = 0 self.window_controller = WindowController() self.window_id = self.window_controller.locate_window(".*Mini-Dow .*") # self.window_id = self.window_controller.locate_window(".*S&P .*") self.keys = RedisKeys(metrics_key) # self.redis = redis.Redis(port=6001) self.number_of_trades = 0 self.number_of_wins = 0 self.buys = 0 self.sells = 0 self.holds = 0 self.history = list() self.actions = 0 self.last_action = '' self.previous_write = -1 self.get_metadata() self.active_frame = None self.start_time = time.time() self.step_read_time = 0 self.step_write_time = 0
class T4TFEnv(py_environment.PyEnvironment): def __init__(self, fake=False, metrics_key='001'): with open('running', 'w') as f: f.write(str(os.getpid())) self._episode_ended = False self.game = serpent.initialize_game('T4TF1') game_frame = self.game.screen_regions['GAME_REGION'] self.width = 10 self.height = 10 self.state_shape = (int(self.height / 2), int(self.width / 2), 1) self._action_spec = array_spec.BoundedArraySpec( shape=(), dtype=np.int32, minimum=0, maximum=1, name='action') self._observation_spec = array_spec.BoundedArraySpec( shape=self.state_shape, dtype=np.float32, minimum=0.0, name='observation') self._state = np.zeros(self.state_shape).astype(np.float32) if fake: return self.interrupted = False self.game.launch() self.game.start_frame_grabber() self.input_controller = InputController(game=self.game) # self.input_proc = self.frame_buffer = FrameGrabber.get_frames([0]) self.frame_buffer = self.extract_game_area(self.frame_buffer) self.width = self.frame_buffer[0].shape[1] self.height = self.frame_buffer[0].shape[0] print('width: %d' % self.width) print('height: %d' % self.height) self.state_shape = (self.height, self.width, 3) self._action_spec = array_spec.BoundedArraySpec( shape=(), dtype=np.int32, minimum=0, maximum=1, name='action') self._observation_spec = array_spec.BoundedArraySpec( shape=self.state_shape, dtype=np.float32, minimum=0.0, name='observation') self._state = np.zeros(self.state_shape).astype(np.float32) # print('created input with pid: %s' % self.input_proc.pid) self.sell_keys = [KeyboardKey.KEY_LEFT_SHIFT, KeyboardKey.KEY_LEFT_CTRL, KeyboardKey.KEY_S] self.buy_keys = [KeyboardKey.KEY_LEFT_SHIFT, KeyboardKey.KEY_LEFT_CTRL, KeyboardKey.KEY_B] self.step_keys = [KeyboardKey.KEY_LEFT_SHIFT, KeyboardKey.KEY_LEFT_CTRL, KeyboardKey.KEY_F] self.visual_debugger = VisualDebugger() self.scraper = T4Scraper(game=self.game, visual_debugger=self.visual_debugger) frame = self.game.grab_latest_frame() self.scraper.current_frame = frame self.pl = 0 self.working_trade = 0 self.current_action = '' self.held = False self.fill_count = 0 self.window_controller = WindowController() self.window_id = self.window_controller.locate_window(".*Mini-Dow .*") # self.window_id = self.window_controller.locate_window(".*S&P .*") self.keys = RedisKeys(metrics_key) # self.redis = redis.Redis(port=6001) self.number_of_trades = 0 self.number_of_wins = 0 self.buys = 0 self.sells = 0 self.holds = 0 self.history = list() self.actions = 0 self.last_action = '' self.previous_write = -1 self.get_metadata() self.active_frame = None self.start_time = time.time() self.step_read_time = 0 self.step_write_time = 0 def get_state(self, zeros=False): if zeros: return np.zeros(self.state_shape).astype(np.float32) self.frame_history = [ np.zeros((int(self.width / 4), int(self.height / 4))).astype(np.float32), np.zeros((int(self.width / 4), int(self.height / 4))).astype(np.float32), np.zeros((int(self.width / 4), int(self.height / 4))).astype(np.float32), np.zeros((int(self.width / 4), int(self.height / 4))).astype(np.float32) ] st = np.stack( self.frame_history, axis=2 ).astype(np.float32) print(st.shape) return st def is_focused(self): return self.window_controller.is_window_focused(self.window_id) def display_frame(self): frame = self.game.grab_latest_frame() self.visual_debugger.store_image_data( frame.frame, frame.frame.shape, 2 ) def action_spec(self): return self._action_spec def observation_spec(self): return self._observation_spec def _reset(self): print('RESTARTING') self._state = np.zeros(self.state_shape).astype(np.float32) self._episode_ended = False return ts.restart(self._state) def update_scraper_frame(self): self.scraper.current_frame = self.game.grab_latest_frame() self.visual_debugger.store_image_data( self.scraper.current_frame.frame, self.scraper.current_frame.frame.shape, str(2) ) def stop(self): self.input_proc.kill() self.game.stop_frame_grabber() return ts.termination(self._state, 0) def write_order(self, order_type): write_start = time.time() # if order_type is self.previous_write: return with open('/home/dan/.wine/drive_c/input.txt', 'w') as f: f.write('%d' % (order_type)) self.step_write_time += (time.time() - write_start) self.previous_write = order_type def step_forward(self): self.write_order(3) def add_to_history(self, frame, action, reward): history_start = time.time() im = Image.fromarray(frame) im.save('history/%d_%d_%f.jpg' % (int(datetime.now().timestamp() * 100), action, reward)) print("history add time: %s seconds" % (time.time() - history_start)) # def log(self, string): # if self.actions % 200 == 0: # print(string) # def _step(self, action): self.step_read_time = 0 self.step_write_time = 0 if self.interrupted: return self.stop() print('----') if self._episode_ended: # The last action ended the episode. Ignore the current action and start # a new episode. return self.reset() if action == 0: # perform buy self.current_action = 'buy' self.working_trade = True # self.input_controller.tap_keys(self.buy_keys, duration=0.001) self.write_order(action) elif action == 1: # perform sell self.current_action = 'sell' self.working_trade = True # self.input_controller.tap_keys(self.sell_keys, duration=0.001) self.write_order(action) elif action == 2: print('hold') self.current_action = 'hold' y = 0 while y < 3: # self.write_order(action) self.step_forward() sleep(0.1) y = y + 1 self.actions += 1 if action < 2: self.number_of_trades += 1 while not self.has_open_positions(): sleep(0.01) if self.interrupted: return self.stop() while self.has_open_positions(): self.step_forward() sleep(0.01) if self.interrupted: return self.stop() self.write_order(4) sleep(0.2) reward = self.reward_agent() if self.actions > 1: self.add_to_history(self.active_frame, action, reward) start_grab_frame = time.time() self.frame_buffer = FrameGrabber.get_frames([0]) self.frame_buffer = self.extract_game_area(self.frame_buffer) print("frame grab time: %s seconds" % (time.time() - start_grab_frame)) self.active_frame = self.frame_buffer[0] # for i, game_frame in enumerate(self.frame_buffer): # if i >= 3: break # self.visual_debugger.store_image_data( # game_frame, # game_frame.shape, # str(i) # ) print(self.frame_buffer[0].shape) # self.frame_history.insert(0, self.frame_buffer[0]) # self._states = self.get_state() states_shape = self.state_shape print(states_shape) self._states = np.reshape(self.frame_buffer[0], (states_shape[0], states_shape[1], states_shape[2])).astype(np.float32) print(self._states.shape) if self.number_of_trades > 0: self.push_metadata(action=self.current_action, reward=reward) print('Wins: %d%% - %d / %d' % ((self.number_of_wins / self.number_of_trades * 100), self.number_of_wins, self.number_of_trades)) # print history if len(self.history) > 0: historical_wins = len(list(filter(lambda x: x[1] > 0, self.history))) print('Wins (last %d): %d%%' % (len(self.history), (historical_wins / len(self.history) * 100))) print('Buys: %d' % self.buys) print('Sells: %d' % self.sells) print('Holds: %d' % self.holds) print('Step read time: %s' % self.step_read_time) print('Step write time: %s' % self.step_write_time) # print(states.shape) return ts.transition(self._states, reward=reward, discount=1.0) def read_position_and_pl(self): read_start = time.time() result = ['',''] while len(result[0]) < 1 or len(result[1]) < 1: with open('/home/dan/.wine/drive_c/output.txt', 'r') as f: result = [x.strip() for x in f.read().split(',')] self.step_read_time += (time.time() - read_start) return (int(result[0]), int(result[1])) def has_open_positions(self): result = self.read_position_and_pl() pos = result[0] pl = result[1] # if self.working_trade: # if pos != 0: # self.working_trade = False # else: # if pl != self.pl: # self.working_trade = False # return False # else: # return True if pos != 0: return True return False def reward_agent(self): # get pl for last trade newPL = self.read_position_and_pl()[1] print('old pl: %d' % self.pl) print('new pl: %d' % newPL) if newPL > self.pl: reward = 1.0 else: reward = -1.0 if self.current_action is 'hold': reward = -0.25 else: if reward > 0: if self.last_action is 'hold': reward = 1.25 # if reward is 1.0: # if self.current_action is 'buy' and self.buys > self.sells: # reward = 0.8 # elif self.current_action is 'sell' and self.sells > self.buys: # reward = 0.8 # elif reward is -1.0: # if self.current_action is 'sell' and self.buys > self.sells: # reward = -0.8 # elif self.current_action is 'buy' and self.sells > self.buys: # reward = -0.8 self.last_action = self.current_action print('REWARD: %f' % reward) self.pl = newPL return reward def extract_game_area(self, frame_buffer): game_area_buffer = [] # for game_frame in frame_buffer.frames: # game_area = cv.extract_region_from_image( # game_frame.grayscale_frame, # self.game.screen_regions["GAME_REGION"] # ) frame = frame_buffer.frames[0].quarter_resolution_frame # frame = FrameTransformer.rescale(frame_buffer.frames[0].grayscale_frame, 0.5) game_area_buffer.append(frame) return game_area_buffer def get_metadata(self): return if self.redis.exists(self.keys.trades): self.number_of_trades = self.redis.llen(self.keys.trades) self.history = list() history_strings = self.redis.lrange(self.keys.trades, -100, 100) for s in history_strings: d = json.loads(s) self.history.append((d['action'], float(d['reward']))) if self.redis.exists(self.keys.wins): self.number_of_wins = int(self.redis.get(self.keys.wins)) if self.redis.exists(self.keys.buys): self.buys = int(self.redis.get(self.keys.buys)) if self.redis.exists(self.keys.sells): self.sells = int(self.redis.get(self.keys.sells)) if self.redis.exists(self.keys.holds): self.holds = int(self.redis.get(self.keys.holds)) def push_metadata(self, action, reward, reset=False): return if action is None: return # last 100 if not action is 'hold': while len(self.history) >= 100: self.history.pop(0) self.history.append((action, reward)) obj = { 'timestamp':str(datetime.now().timestamp()), 'action': action, 'reward': str(reward) } self.redis.rpush(self.keys.trades, json.dumps(obj)) if action == 'buy': self.buys += 1 self.redis.incr(self.keys.buys) elif action == 'sell': self.sells += 1 self.redis.incr(self.keys.sells) elif action == 'hold': self.holds += 1 self.redis.incr(self.keys.holds) if reward > 0: self.number_of_wins += 1 self.redis.incr(self.keys.wins) if reset: self.redis.set(self.keys.buys, "0") self.redis.set(self.keys.sells, "0") self.redis.set(self.keys.wins, "0") self.redis.set(self.keys.trades, "0") self.redis.set(self.keys.holds, "0")