Skip to content

ASX Gym Observations

James Shen edited this page Jun 13, 2020 · 3 revisions

Definition of Gym Observations

Observations If we ever want to do better than take random actions at each step, it’d probably be good to actually know what our actions are doing to the environment.

The environment’s step function returns exactly what we need. In fact, step returns four values. These are:

  • observation (object): an environment-specific object representing your observation of the environment. For example, pixel data from a camera, joint angles and joint velocities of a robot, or the board state in a board game.
  • reward (float): the amount of reward achieved by the previous action. The scale varies between environments, but the goal is always to increase your total reward.
  • done (boolean): whether it’s time to reset the environment again. Most (but not all) tasks are divided up into well-defined episodes, and done being True indicates the episode has terminated. (For example, perhaps the pole tipped too far, or you lost your last life.)
  • info (dict): diagnostic information useful for debugging. It can sometimes be useful for learning (for example, it might contain the raw probabilities behind the environment’s last state change). However, official evaluations of your agent are not allowed to use this for learning.

Observations in ASX Gym

following is the code snippet for Observations in ASX Gym

self.observation_space = spaces.Dict(
    {
        "indexes": spaces.Dict({
            'open': spaces.Box(low=np.float32(0),
                                high=np.float32(self.number_infinite),
                                dtype=np.float32),
            'close': spaces.Box(low=np.float32(0),
                                high=np.float32(self.number_infinite),
                                dtype=np.float32),
            'high': spaces.Box(low=np.float32(0),
                                high=np.float32(self.number_infinite),
                                dtype=np.float32),
            'low': spaces.Box(low=np.float32(0),
                                high=np.float32(self.number_infinite),
                                dtype=np.float32),

        }
        ),
        "day": spaces.Discrete(self.number_infinite),
        "seconds": spaces.Discrete(24 * 3600),
        "company_count": spaces.Discrete(self.max_company_number),
        "prices:": spaces.Dict({
            "company_id": spaces.MultiDiscrete([self.max_company_number]
                                                * self.max_company_number),
            "ask_price": spaces.Box(low=np.float32(0),
                                    high=np.float32(self.max_stock_price),
                                    shape=(self.max_company_number,),
                                    dtype=np.float32),
            "bid_price": spaces.Box(low=np.float32(0),
                                    high=np.float32(self.max_stock_price),
                                    shape=(self.max_company_number,),
                                    dtype=np.float32),
            "price": spaces.Box(low=np.float32(0),
                                high=np.float32(self.max_stock_price),
                                shape=(self.max_company_number,),
                                dtype=np.float32)}),

        "portfolio_company_count": spaces.Discrete(self.max_company_number),
        "portfolios": spaces.Dict(
            {
                "company_id": spaces.MultiDiscrete([self.max_company_number]
                                                    * self.max_company_number),

                "volume": spaces.Box(np.float32(0),
                                        high=np.float32(self.number_infinite),
                                        shape=(self.max_company_number,),
                                        dtype=np.float32),
                "buy_price": spaces.Box(low=np.float32(0),
                                        high=np.float32(self.max_stock_price),
                                        shape=(self.max_company_number,),
                                        dtype=np.float32),
                "sell_price": spaces.Box(low=np.float32(0),
                                            high=np.float32(self.max_stock_price),
                                            shape=(self.max_company_number,),
                                            dtype=np.float32),
                "price": spaces.Box(low=np.float32(0),
                                    high=np.float32(self.max_stock_price),
                                    shape=(self.max_company_number,),
                                    dtype=np.float32),
            }),
        "bank_balance:": spaces.Box(low=np.float32(0),
                                    high=np.float32(self.number_infinite),
                                    dtype=np.float32),

        "total_value:": spaces.Box(low=np.float32(0),
                                    high=np.float32(self.number_infinite),
                                    dtype=np.float32),
        "available_fund:": spaces.Box(low=np.float32(0),
                                        high=np.float32(self.number_infinite),
                                        dtype=np.float32)

    }
)

what you can see is the daily Stock index, your bank account details, your current state of portfolios.

like action, ASX Gym also provides some helper models to help you process observations

company_id is the id of company ,you can refer to the Company List

class StockIndex:
    def __init__(self, index_date, open_index, close_index, high_index, low_index):
        self.index_date = index_date
        self.open_index = open_index
        self.close_index = close_index
        self.high_index = high_index
        self.low_index = low_index

    def to_json_obj(self):
        json_obj = {
            'index_date': self.index_date,
            'open_index': round(self.open_index, 2),
            'close_index': round(self.close_index, 2),
            'high_index': round(self.high_index, 2),
            'low_index': round(self.low_index, 2)

        }
        return json_obj


class StockPrice:
    def __init__(self, price_date, company_id, open_price,
                 close_price, high_price, low_price):
        self.price_date = price_date
        self.company_id = company_id
        self.open_price = open_price
        self.close_price = close_price
        self.high_price = high_price
        self.low_price = low_price

    def to_json_obj(self):
        json_obj = {
            'price_date': self.price_date,
            'company_id': int(self.company_id),
            'open_price': round(self.open_price, 2),
            'close_price': round(self.close_price, 2),
            'high_price': round(self.high_price, 2),
            'low_price': round(self.low_price, 2)
        }
        return json_obj


class StockRecord:
    def __init__(self, company_id, volume, buy_price, sell_price, price):
        self.company_id = company_id
        self.volume = volume
        self.buy_price = buy_price
        self.sell_price = sell_price
        self.price = price


class AsxObservation:
    def __init__(self, observation):
        self.day = observation['day']
        self.seconds = observation['second']
        self.total_value = float(observation['total_value'].item())
        self.available_fund = float(observation['available_fund'].item())
        self.bank_balance = float(observation['bank_balance'].item())
        open_index = float(observation['indexes']['open'].item())
        close_index = float(observation['indexes']['close'].item())
        high_index = float(observation['indexes']['high'].item())
        low_index = float(observation['indexes']['low'].item())
        self.stock_index = StockIndex('', open_index,
                                      close_index, high_index, low_index)

        self.portfolios = []
        self.prices = {}
        company_count = observation['company_count']
        for c in range(company_count):
            company_id = observation['prices']['company_id'][c].item()
            ask_price = observation['prices']['ask_price'][c].item()
            bid_price = observation['prices']['bid_price'][c].item()
            price = observation['prices']['price'][c].item()
            self.prices[company_id] = StockSimulationPrice(ask_price, bid_price, price)

        portfolio_company_count = observation['portfolio_company_count']
        for c in range(portfolio_company_count):
            company_id = observation['portfolios']['company_id'][c].item()
            volume = observation['portfolios']['volume'][c].item()
            buy_price = observation['portfolios']['buy_price'][c].item()
            sell_price = observation['portfolios']['sell_price'][c].item()
            price = observation['portfolios']['price'][c].item()
            stock_record = StockRecord(company_id, volume, buy_price, sell_price, price)
            self.portfolios.append(stock_record)

    def to_json_obj(self):
        json_obj = {"day": int(self.day),
                    "seconds": int(self.seconds),
                    "total_value": round(self.total_value, 2),
                    "available_fund": round(self.available_fund, 2),
                    "bank_balance": round(self.bank_balance, 2),
                    "index": {
                        "open": round(self.stock_index.open_index, 2),
                        "close": round(self.stock_index.close_index, 2),
                        "high": round(self.stock_index.high_index, 2),
                        "low": round(self.stock_index.low_index, 2)
                    },
                    "prices": {},
                    "portfolios": {}}
        for company_id, prices in self.prices.items():
            json_obj["prices"][company_id] = {
                "ask_price": round(prices.ask_price, 2),
                "bid_price": round(prices.bid_price, 2),
                "price": round(prices.price, 2)

            }
        for stock_record in self.portfolios:
            json_obj["portfolios"][stock_record.company_id] = {
                "volume": round(stock_record.volume, 2),
                "buy_price": round(stock_record.buy_price, 2),
                "sell_price": round(stock_record.sell_price, 2),
                "price": round(stock_record.price, 2)
            }

        return json_obj

sample observation

{
   "day":1,
   "seconds":36000,
   "total_value":100000.0,
   "available_fund":96690.03,
   "bank_balance":0.0,
   "index":{
      "open":6746.2,
      "close":6735.8,
      "high":6759.6,
      "low":6735.8
   },
   "prices":{
      2:{
         "ask_price":80.91,
         "bid_price":80.91,
         "price":80.91
      },
      3:{
         "ask_price":40.75,
         "bid_price":40.75,
         "price":40.75
      },
      4:{
         "ask_price":27.82,
         "bid_price":27.82,
         "price":27.82
      },
      5:{
         "ask_price":27.0,
         "bid_price":27.0,
         "price":27.0
      },
      6:{
         "ask_price":27.17,
         "bid_price":27.17,
         "price":27.17
      },
      44:{
         "ask_price":3.11,
         "bid_price":3.11,
         "price":3.11
      },
      67:{
         "ask_price":21.84,
         "bid_price":21.84,
         "price":21.84
      },
      100:{
         "ask_price":61.74,
         "bid_price":61.74,
         "price":61.74
      },
      200:{
         "ask_price":5.63,
         "bid_price":5.63,
         "price":5.63
      },
      300:{
         "ask_price":1.75,
         "bid_price":1.75,
         "price":1.75
      }
   },
   "portfolios":{
      200:{
         "volume":54.0,
         "buy_price":5.63,
         "sell_price":0.0,
         "price":5.63
      },
      300:{
         "volume":82.0,
         "buy_price":1.75,
         "sell_price":0.0,
         "price":1.75
      },
      2:{
         "volume":23.0,
         "buy_price":80.91,
         "sell_price":0.0,
         "price":80.91
      },
      4:{
         "volume":36.0,
         "buy_price":27.82,
         "sell_price":0.0,
         "price":27.82
      }
   }
}