健身任何交易 Python 数据框格式

-1 投票
1 回答
127 浏览
提问于 2025-04-12 22:09

我刚接触gym anytrading,手头有一个pandas数据框,其中有一列是不同长度的列表的列表。我正在尝试把这个数据放入gym anytrading环境中。下面是一个链接,里面有这个数据框的样本数据的csv文件,还有一段代码示例。我一直遇到这个错误:TypeError: cannot unpack non-iterable NoneType object。

import gym
import pandas as pd
import numpy as np
from gym_anytrading.envs import TradingEnv

    
class CustomTradingEnv(TradingEnv):
    def __init__(self, df):
        super().__init__(df, window_size=10)
        self.reward_range = (0, 1)

    def _process_data(self):
        # Process your DataFrame to ensure it's in the correct format
        # Here, you can perform any necessary preprocessing steps
        pass

    def reset(self):
        # Initialize the environment with the data from the DataFrame
        self._process_data()
        return super().reset()
    
    

    env = CustomTradingEnv(df)

    observation = env.reset()
    for _ in range(100):  # Run for 100 steps
    action = env.action_space.sample()  # Sample a random action
    observation, reward, done, info = env.step(action)
    if done:
        break

https://docs.google.com/spreadsheets/d/1-LFNzZKXUG44smSYOy2rgVVnqiygLfs00lAl2vFdsxM/edit?usp=sharing

1 个回答

3

首先,你使用的 gym 包不对:

import gym

应该改成

import gymnasium as gym

因为 gym_anytrading 也使用了 gymnasium(这个和不再维护的旧版 gym 有些不同)。

然后,你代码里的缩进不对——我猜这只是个打字错误。循环的写法应该是:

for _ in range(100):  # Run for 100 steps
    action = env.action_space.sample()  # Sample a random action
    observation, reward, done, info = env.step(action)
    if done:
        break

实际的错误来自于 __init__ 函数和 _process_data 函数。完整的错误追踪信息是:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "...", line 24, in test
    env = CustomTradingEnv(df)
  File "...", line 9, in __init__
    super().__init__(df, window_size=10)
  File "/.../anaconda3/envs/py310/lib/python3.10/site-packages/gym_anytrading/envs/trading_env.py", line 35, in __init__
    self.prices, self.signal_features = self._process_data()
TypeError: cannot unpack non-iterable NoneType object

要解决这个问题,你需要修改 process_data,让它返回一个包含 numpy 数组的元组,prices(一个一维的浮点数数组)和 signal_features(一个二维数组)。这在 gym_anytrading 的说明文档里也有详细解释。你可以用你的数据框做类似这样的操作:

    def _process_data(self):
        env = self.unwrapped        
        start = 0
        end = len(env.df)
        prices = env.df.loc[:, 'low'].to_numpy()[start:end]
        signal_features = env.df.loc[:, ['close', 'open', 'high', 'low']].to_numpy()[start:end]
        return prices, signal_features

这样做后,你的测试循环就能正常工作了,除了你没有提供任何奖励函数。自定义环境需要实现一个 _calculate_reward 函数,这个函数会为可能的每个动作返回一个奖励信号(在这个例子里只有两个动作)。所以这个函数应该看起来像:

    def _calculate_reward(self, action):
        # I'm assuming 0 and 1 stand for sell and buy (or viceversa)
        match action:
             case 0: return 0.1 # or some other more suitable value
             case 1: return -0.1 # or something more suitable
             case _: raise Exception("bug")

另外,_update_profit(self, action) 函数也需要实现(它需要更新环境的内部状态,self.unwrapped._total_profit,不过你也可以让它 pass)。

最后,你代码里的 env.step 函数不正确(对于最新版本的 gymnasium)。它应该这样使用:

   observation, reward, done, terminated, info = env.step(action)

撰写回答