Shortcuts

Quick start

Welcome to sharpe quick start guide that just covers the essentials of getting a project up and walking through the code.

In several lines of this given code, you can backtest your first rule-based trading strategy as shown below:

Code

 from sharpe.utils.mock_data import create_toy_feature
 from sharpe.data.data_source import DataSource
 from sharpe.environment import TradingEnv
 from sharpe.mod.sys_account.api import order_target_weights
 import random
 random.seed(111)

 feature_df, price_s = create_toy_feature(order_book_ids_number=2, feature_number=3, start="2020-01-01", end="2020-01-11", random_seed=111)
 data_source = DataSource(feature_df=feature_df, price_s=price_s)

 env= TradingEnv(data_source=data_source, look_backward_window=4)
 print('----------------------------------------------------------------------')

 company_id = "000001.XSHE"


 def your_strategy(state):
      """
      here is a random strategy, only trade the first stock with a random target percent
      """

      target_percent_of_position =  round(random.random(),2)
      target_position_dict = {company_id : target_percent_of_position}
      print("the target portfolio is to be: {}".format(target_position_dict))
      # call trade API
      action = order_target_weights(target_position_dict)
      return action


 state = env.reset()

 while True:
      print("the current trading_dt is: {}".format(env.trading_dt))
      action = your_strategy(state)

      next_state, reward, done, info = env.step(action)
      print("the reward of this action: {}".format(reward))
      print("the next state is \n {}".format(next_state))
      if done:
           break
      else:
           state = next_state
env.render()

Explanation

Now let’s break up the code and review it in details. the first step is to create your custom data source.

the input of DataSource involves in one pd.DataFrame(called feature_df) and one pd.Series(called price_s) with multiindex.

feature_df, price_s = create_toy_feature(order_book_ids_number=2, feature_number=3, start="2020-01-01", end="2020-01-11", random_seed=111)
data_source = DataSource(feature_df=feature_df, price_s=price_s)

the feature_df is a multindex dataframe, the first index is instrument name, the second index is timestamp, the data containw your instruments’ features(like the raw feature, open, high, low, close ,volume or features(factors) after feature engineering), that is the states of the market you care about.

                          feature_1  feature_2  feature_3
order_book_id datetime
000001.XSHE   2020-01-01  -1.133838   0.384319   1.496554
              2020-01-02  -0.355382  -0.787534  -0.459439
              2020-01-03  -0.059169  -0.354174  -0.735523
              2020-01-04  -1.183940   0.238894  -0.589920
              2020-01-05  -1.440585   0.773703  -1.027967
              2020-01-06  -0.090986   0.492003   0.424672
              2020-01-07   1.283049   0.315986  -0.408082
              2020-01-08  -0.067948  -0.952427  -0.110677
              2020-01-09   0.570594   0.915420  -1.669341
              2020-01-10   0.482714  -0.310473   2.394690
              2020-01-11   1.550931  -0.646465  -0.928937
000002.XSHE   2020-01-01  -1.654976   0.350193  -0.141757
              2020-01-02   0.521082  -0.020901  -1.743844
              2020-01-03  -0.799159  -1.303570   0.178105
              2020-01-04  -0.334402  -0.306027  -0.332406
              2020-01-05   1.962947   0.719242   1.142887
              2020-01-06   2.082877  -1.284648   0.538128
              2020-01-07  -0.044539   2.597164  -0.058266
              2020-01-08  -0.945287   0.541172  -0.055009
              2020-01-09   1.120021  -0.191643  -0.610138
              2020-01-10  -0.444579  -2.204009  -0.430670
              2020-01-11  -0.425093   0.147292   0.424924

the price_s is a multiindex pd.Series, contraining the price of the instrument at different timestamp. this is an important component of the DataSource, which is used to backtest.

order_book_id  datetime
000001.XSHE    2020-01-01    42.31
               2020-01-02    43.61
               2020-01-03    40.40
               2020-01-04    43.11
               2020-01-05    46.29
               2020-01-06    43.01
               2020-01-07    38.62
               2020-01-08    46.05
               2020-01-09    45.38
               2020-01-10    39.80
               2020-01-11    42.19
000002.XSHE    2020-01-01    10.59
               2020-01-02    13.08
               2020-01-03    12.07
               2020-01-04    19.72
               2020-01-05    19.09
               2020-01-06    16.76
               2020-01-07    11.15
               2020-01-08    19.58
               2020-01-09    10.92
               2020-01-10    16.30
               2020-01-11    19.03
Name: price, dtype: float64

Next we define the environment. the input of TradingEnv is the data_source we have created and a int parameter, called look_backward_window, which tells the enviontment, at each timestamp. we can observe the past feature with window size==4, which consist the state of the environment at that timestamp. that means the shape of the state of environment is (instrument_numbers, look_backward_window, feature_numbers)

env= TradingEnv(data_source=data_source, look_backward_window=4)

The most interesting part of the code snippet is define your trading strategy which is a mapping from state to investment action(all instrument investment weight). it actually involve in two steps. the first step is to determine the investment percent(weight) of instruments based on the current state, which is your core logic of trading strategy. the output of this step is a dict {instrument_1_name: percent1, instrument_2_name: percent2},. the next step is call builtin trade API order_target_portfolio to create action(a order list)

def your_strategy(state):
     """
     here is a random strategy, only trade the first stock with a random target percent
     """
     #step1
     target_percent_of_postion =  round(random.random(),2)
     target_pososition_dict = {company_id : target_percent_of_postion}
     print("the target portfolio is to be: {}".format(target_pososition_dict))
     #step2: call trade API
     action = order_target_portfolio(target_pososition_dict)
     return action

the last step is backtest your strategy, iterate all available timestamps

 state = env.reset() #the initial state of environment
 while True:
      print("the current trading_dt is: {}".format(env.trading_dt))
      action = your_strategy(state)

      next_state, reward, done, info = env.step(action)
      print("the reward of this action: {}".format(reward))
      print("the next state is \n {}".format(next_state))
      if done:
           break
      else:
           state = next_state
env.render()