I just transferred it (FinRL-Tutorials/3-Practical/FinRL_MultiCrypto_Trading.ipynb) to a file (main.py)
Error 1:
If I want to DEBUG my script (main.py) - I get an error:
'''
conda activate base
(base) drulye@drulye-MS-7885:~/vscode/MCpypto$ conda activate base
/usr/bin/env /home/drulye/anaconda3/bin/python /home/drulye/.vscode/extensions/ms-python.python-2022.20.1/pythonFiles/lib/python/debugpy/adapter/../../debugpy/launcher 36507 -- /home/drulye/vscode/MCpypto/main.py
(base) drulye@drulye-MS-7885:~/vscode/MCpypto$ /usr/bin/env /home/drulye/anaconda3/bin/python /home/drulye/.vscode/extensions/ms-python.python-2022.20.1/pythonFiles/lib/python/debugpy/adapter/../../debugpy/launcher 36507 -- /home/drulye/vscode/MCpypto/main.py
/home/drulye/anaconda3/lib/python3.9/site-packages/scipy/__init__.py:146: UserWarning: A NumPy version >=1.16.5 and <1.23.0 is required for this version of SciPy (detected version 1.23.5
warnings.warn(f"A NumPy version >={np_minversion} and <{np_maxversion}"
QObject::moveToThread: Current thread (0x8cbc810) is not the object's thread (0x904ade0).
Cannot move to target thread (0x8cbc810)
qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "/home/drulye/anaconda3/lib/python3.9/site-packages/cv2/qt/plugins" even though it was found.
This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.
Available platform plugins are: xcb, eglfs, minimal, minimalegl, offscreen, vnc, webgl.
(base) drulye@drulye-MS-7885:~/vscode/MCpypto$
'''
Error 2:
If I want to RUN my script (main.py) - I get an error:
'''
conda activate base
(base) drulye@drulye-MS-7885:~/vscode/MCpypto$ conda activate base
/home/drulye/anaconda3/bin/python /home/drulye/vscode/MCpypto/main.py
(base) drulye@drulye-MS-7885:~/vscode/MCpypto$ /home/drulye/anaconda3/bin/python /home/drulye/vscode/MCpypto/main.py
/home/drulye/anaconda3/lib/python3.9/site-packages/scipy/__init__.py:146: UserWarning: A NumPy version >=1.16.5 and <1.23.0 is required for this version of SciPy (detected version 1.23.5
warnings.warn(f"A NumPy version >={np_minversion} and <{np_maxversion}"
binance successfully connected
Using cached file ./cache/BTCUSDT_ETHUSDT_ADAUSDT_BNBUSDT_XRPUSDT_SOLUSDT_DOTUSDT_DOGEUSDT_AVAXUSDT_UNIUSDT_binance_2021-09-01_2021-09-02_5m.pickle
tech_indicator_list: ['macd', 'rsi', 'cci', 'dx']
indicator: macd
indicator: rsi
indicator: cci
indicator: dx
Succesfully add technical indicators
Successfully transformed into array
| Arguments Remove cwd: ./test_ppo
Traceback (most recent call last):
File "/home/drulye/vscode/MCpypto/main.py", line 329, in <module>
train(start_date=TRAIN_START_DATE,
File "/home/drulye/vscode/MCpypto/main.py", line 89, in train
trained_model = agent.train_model(model=model,
File "/home/drulye/vscode/FinRL-Meta/agents/elegantrl_models.py", line 79, in train_model
train_and_evaluate(model)
File "/home/drulye/vscode/ElegantRL/elegantrl/train/run.py", line 95, in train_and_evaluate
agent = init_agent(args, gpu_id, env)
File "/home/drulye/vscode/ElegantRL/elegantrl/train/run.py", line 24, in init_agent
agent = args.agent_class(args.net_dim, args.state_dim, args.action_dim, gpu_id=gpu_id, args=args)
File "/home/drulye/vscode/ElegantRL/elegantrl/agents/AgentPPO.py", line 40, in __init__
AgentBase.__init__(self, net_dim, state_dim, action_dim, gpu_id, args)
File "/home/drulye/vscode/ElegantRL/elegantrl/agents/AgentBase.py", line 57, in __init__
self.act = act_class(net_dim, state_dim, action_dim).to(self.device)
File "/home/drulye/vscode/ElegantRL/elegantrl/agents/net.py", line 397, in __init__
self.net = build_mlp_net(dims=[state_dim, *dims, action_dim])
TypeError: Value after * must be an iterable, not int
(base) drulye@drulye-MS-7885:~/vscode/MCpypto$
'''
My script file:
main.py
Import Related Packages
import math
import numpy as np
import sys
sys.path.insert(0, "/home/drulye/vscode/FinRL")
sys.path.insert(0, "/home/drulye/vscode/ElegantRL")
sys.path.insert(0, "/home/drulye/vscode/FinRL-Meta")
from agents.elegantrl_models import DRLAgent as DRLAgent_erl
from agents.rllib_models import DRLAgent as DRLAgent_rllib
from agents.stablebaselines3_models import DRLAgent as DRLAgent_sb3
from meta.data_processor import DataProcessor
Function for Training
def train(start_date, end_date, ticker_list, data_source, time_interval,
technical_indicator_list, drl_lib, env, model_name, if_vix=True,
**kwargs):
#process data using unified data processor
DP = DataProcessor(data_source, start_date, end_date, time_interval, **kwargs)
price_array, tech_array, turbulence_array = DP.run(ticker_list,
technical_indicator_list,
if_vix, cache=True)
data_config = {'price_array': price_array,
'tech_array': tech_array,
'turbulence_array': turbulence_array}
#build environment using processed data
env_instance = env(config=data_config)
#read parameters and load agents
current_working_dir = kwargs.get('current_working_dir','./'+str(model_name))
if drl_lib == 'elegantrl':
break_step = kwargs.get('break_step', 1e6)
erl_params = kwargs.get('erl_params')
agent = DRLAgent_erl(env = env,
price_array = price_array,
tech_array=tech_array,
turbulence_array=turbulence_array)
model = agent.get_model(model_name, model_kwargs = erl_params)
trained_model = agent.train_model(model=model,
cwd=current_working_dir,
total_timesteps=break_step)
elif drl_lib == 'rllib':
total_episodes = kwargs.get('total_episodes', 100)
rllib_params = kwargs.get('rllib_params')
agent_rllib = DRLAgent_rllib(env = env,
price_array=price_array,
tech_array=tech_array,
turbulence_array=turbulence_array)
model,model_config = agent_rllib.get_model(model_name)
model_config['lr'] = rllib_params['lr']
model_config['train_batch_size'] = rllib_params['train_batch_size']
model_config['gamma'] = rllib_params['gamma']
trained_model = agent_rllib.train_model(model=model,
model_name=model_name,
model_config=model_config,
total_episodes=total_episodes)
trained_model.save(current_working_dir)
elif drl_lib == 'stable_baselines3':
total_timesteps = kwargs.get('total_timesteps', 1e6)
agent_params = kwargs.get('agent_params')
agent = DRLAgent_sb3(env = env_instance)
model = agent.get_model(model_name, model_kwargs = agent_params)
trained_model = agent.train_model(model=model,
tb_log_name=model_name,
total_timesteps=total_timesteps)
print('Training finished!')
trained_model.save(current_working_dir)
print('Trained model saved in ' + str(current_working_dir))
else:
raise ValueError('DRL library input is NOT supported. Please check.')
Function for Testing
def test(start_date, end_date, ticker_list, data_source, time_interval,
technical_indicator_list, drl_lib, env, model_name, if_vix=True,
**kwargs):
#process data using unified data processor
DP = DataProcessor(data_source, start_date, end_date, time_interval, **kwargs)
price_array, tech_array, turbulence_array = DP.run(ticker_list,
technical_indicator_list,
if_vix, cache=True)
np.save('./price_array.npy', price_array)
data_config = {'price_array':price_array,
'tech_array':tech_array,
'turbulence_array':turbulence_array}
#build environment using processed data
env_instance = env(config=data_config)
env_config = {
"price_array": price_array,
"tech_array": tech_array,
"turbulence_array": turbulence_array,
"if_train": False,
}
env_instance = env(config=env_config)
# load elegantrl needs state dim, action dim and net dim
net_dimension = kwargs.get("net_dimension", 2 ** 7)
current_working_dir = kwargs.get("current_working_dir", "./" + str(model_name))
print("price_array: ", len(price_array))
if drl_lib == "elegantrl":
episode_total_assets = DRLAgent_erl.DRL_prediction(
model_name=model_name,
cwd=current_working_dir,
net_dimension=net_dimension,
environment=env_instance,
)
return episode_total_assets
elif drl_lib == "rllib":
# load agent
episode_total_assets = DRLAgent_rllib.DRL_prediction(
model_name=model_name,
env=env,
price_array=price_array,
tech_array=tech_array,
turbulence_array=turbulence_array,
agent_path=current_working_dir,
)
return episode_total_assets
elif drl_lib == "stable_baselines3":
episode_total_assets = DRLAgent_sb3.DRL_prediction_load_from_file(
model_name=model_name, environment=env_instance, cwd=current_working_dir
)
return episode_total_assets
else:
raise ValueError("DRL library input is NOT supported. Please check.")
Multiple Cryptocurrencies Trading Env
class CryptoEnv: # custom env
def __init__(self, config, lookback=1, initial_capital=1e6,
buy_cost_pct=1e-3, sell_cost_pct=1e-3, gamma=0.99):
self.lookback = lookback
self.initial_total_asset = initial_capital
self.initial_cash = initial_capital
self.buy_cost_pct = buy_cost_pct
self.sell_cost_pct = sell_cost_pct
self.max_stock = 1
self.gamma = gamma
self.price_array = config['price_array']
self.tech_array = config['tech_array']
self._generate_action_normalizer()
self.crypto_num = self.price_array.shape[1]
self.max_step = self.price_array.shape[0] - lookback - 1
# reset
self.time = lookback-1
self.cash = self.initial_cash
self.current_price = self.price_array[self.time]
self.current_tech = self.tech_array[self.time]
self.stocks = np.zeros(self.crypto_num, dtype=np.float32)
self.total_asset = self.cash + (self.stocks * self.price_array[self.time]).sum()
self.episode_return = 0.0
self.gamma_return = 0.0
'''env information'''
self.env_name = 'MulticryptoEnv'
self.state_dim = 1 + (self.price_array.shape[1] + self.tech_array.shape[1])*lookback
self.action_dim = self.price_array.shape[1]
self.if_discrete = False
self.target_return = 10
def reset(self) -> np.ndarray:
self.time = self.lookback-1
self.current_price = self.price_array[self.time]
self.current_tech = self.tech_array[self.time]
self.cash = self.initial_cash # reset()
self.stocks = np.zeros(self.crypto_num, dtype=np.float32)
self.total_asset = self.cash + (self.stocks * self.price_array[self.time]).sum()
state = self.get_state()
return state
def step(self, actions) -> (np.ndarray, float, bool, None):
self.time += 1
price = self.price_array[self.time]
for i in range(self.action_dim):
norm_vector_i = self.action_norm_vector[i]
actions[i] = actions[i] * norm_vector_i
for index in np.where(actions < 0)[0]: # sell_index:
if price[index] > 0: # Sell only if current asset is > 0
sell_num_shares = min(self.stocks[index], -actions[index])
self.stocks[index] -= sell_num_shares
self.cash += price[index] * sell_num_shares * (1 - self.sell_cost_pct)
for index in np.where(actions > 0)[0]: # buy_index:
if price[index] > 0: # Buy only if the price is > 0 (no missing data in this particular date)
buy_num_shares = min(self.cash // price[index], actions[index])
self.stocks[index] += buy_num_shares
self.cash -= price[index] * buy_num_shares * (1 + self.buy_cost_pct)
"""update time"""
done = self.time == self.max_step
state = self.get_state()
next_total_asset = self.cash + (self.stocks * self.price_array[self.time]).sum()
reward = (next_total_asset - self.total_asset) * 2 ** -16
self.total_asset = next_total_asset
self.gamma_return = self.gamma_return * self.gamma + reward
self.cumu_return = self.total_asset / self.initial_cash
if done:
reward = self.gamma_return
self.episode_return = self.total_asset / self.initial_cash
return state, reward, done, None
def get_state(self):
state = np.hstack((self.cash * 2 ** -18, self.stocks * 2 ** -3))
for i in range(self.lookback):
tech_i = self.tech_array[self.time-i]
normalized_tech_i = tech_i * 2 ** -15
state = np.hstack((state, normalized_tech_i)).astype(np.float32)
return state
def close(self):
pass
def _generate_action_normalizer(self):
action_norm_vector = []
price_0 = self.price_array[0]
for price in price_0:
x = math.floor(math.log(price, 10)) #the order of magnitude
action_norm_vector.append(1/((10)**x))
action_norm_vector = np.asarray(action_norm_vector) * 10000
self.action_norm_vector = np.asarray(action_norm_vector)
Set Parameters
env = CryptoEnv
TICKER_LIST = ['BTCUSDT','ETHUSDT','ADAUSDT','BNBUSDT','XRPUSDT',
'SOLUSDT','DOTUSDT', 'DOGEUSDT','AVAXUSDT','UNIUSDT']
TRAIN_START_DATE = '2021-09-01'
TRAIN_END_DATE = '2021-09-02'
TEST_START_DATE = '2021-09-21'
TEST_END_DATE = '2021-09-30'
INDICATORS = ['macd', 'rsi', 'cci', 'dx'] #self-defined technical indicator list is NOT supported yet
ERL_PARAMS = {"learning_rate": 2**-15,"batch_size": 2**11,
"gamma": 0.99, "seed":312,"net_dimension": 2**9,
"target_step": 5000, "eval_gap": 30, "eval_times": 1}
Training
train(start_date=TRAIN_START_DATE,
end_date=TRAIN_END_DATE,
ticker_list=TICKER_LIST,
data_source='binance',
time_interval='5m',
technical_indicator_list=INDICATORS,
drl_lib='elegantrl',
env=env,
model_name='ppo',
current_working_dir='./test_ppo',
erl_params=ERL_PARAMS,
break_step=5e4,
if_vix=False
)
Testing
account_value_erl = test(start_date = TEST_START_DATE,
end_date = TEST_END_DATE,
ticker_list = TICKER_LIST,
data_source = 'binance',
time_interval= '5m',
technical_indicator_list= INDICATORS,
drl_lib='elegantrl',
env=env,
model_name='ppo',
current_working_dir='./test_ppo',
net_dimension = 2**9,
if_vix=False
)
Plotting
TODO: Let's leave it for later