Appearance
question:报错了: --------------------------------------------------------------------------- TypeError Traceback (most recent call last) Cell In [3], line 1 ----> 1 returns = train(train_env, eval_env, model_name=model_name) File /tf/notebooks/reinforcement/train.py:89, in train(train_env, eval_env, model_name, epoch, num_iterations, collect_steps_per_iteration, log_interval, eval_interval) 86 with tqdm(total=len(range(num_iterations))) as progress_bar: 87 for _ in range(num_iterations): 88 # 从训练环境中收集一些步骤(使用代理的collect_policy)并存储到replay buffer。 ---> 89 collect_data(train_env, agent.collect_policy, replay_buffer, collect_steps_per_iteration) 91 # 每次收集后都从replay buffer中取出一小批数据用于学习。 92 experience, _ = next(iterator) File /tf/notebooks/reinforcement/train.py:15, in collect_data(env, policy, buffer, steps) 13 def collect_data(env, policy, buffer, steps): 14 for _ in range(steps): ---> 15 collect_step(env, policy, buffer) File /tf/notebooks/reinforcement/learn.py:108, in collect_step(environment, policy, replay_buffer) 106 time_step = environment.current_time_step() 107 action_step = policy.action(time_step) --> 108 next_time_step = environment.step(action_step.action) 109 traj = trajectory.from_transition(time_step, action_step, next_time_step) 110 replay_buffer.add_batch(traj) File /usr/local/lib/python3.8/dist-packages/tf_agents/environments/tf_environment.py:241, in TFEnvironment.step(self, action) 211 def step(self, action): 212 """Steps the environment according to the action. 213 214 If the environment returned a `TimeStep` with `StepType.LAST` at the (...) 239 corresponding to `observation_spec()`. 240 """ --> 241 return self._step(action) File /usr/local/lib/python3.8/dist-packages/tf_agents/environments/tf_py_environment.py:315, in TFPyEnvironment._step(self, actions) 309 if (action.shape.rank == 0 or 310 (dim_value is not None and dim_value != self.batch_size)): 311 raise ValueError( 312 'Expected actions whose major dimension is batch_size (%d), ' 313 'but saw action with shape %s:n %s' % 314 (self.batch_size, action.shape, action)) --> 315 outputs = tf.numpy_function( 316 _isolated_step_py, 317 flat_actions, 318 self._time_step_dtypes, 319 name='step_py_func') 320 return self._time_step_from_numpy_function_outputs(outputs) File /usr/local/lib/python3.8/dist-packages/tensorflow/python/util/traceback_utils.py:153, in filter_traceback.<locals>.error_handler(*args, **kwargs) 151 except Exception as e: 152 filtered_tb = _process_traceback_frames(e.__traceback__) --> 153 raise e.with_traceback(filtered_tb) from None 154 finally: 155 del filtered_tb File /usr/local/lib/python3.8/dist-packages/tf_agents/environments/tf_py_environment.py:302, in TFPyEnvironment._step.<locals>._isolated_step_py(*flattened_actions) 301 def _isolated_step_py(*flattened_actions): --> 302 return self._execute(_step_py, *flattened_actions) File /usr/local/lib/python3.8/dist-packages/tf_agents/environments/tf_py_environment.py:211, in TFPyEnvironment._execute(self, fn, *args, **kwargs) 209 def _execute(self, fn, *args, **kwargs): 210 if not self._pool: --> 211 return fn(*args, **kwargs) 212 return self._pool.apply(fn, args=args, kwds=kwargs) File /usr/local/lib/python3.8/dist-packages/tf_agents/environments/tf_py_environment.py:298, in TFPyEnvironment._step.<locals>._step_py(*flattened_actions) 295 with _check_not_called_concurrently(self._lock): 296 packed = tf.nest.pack_sequence_as( 297 structure=self.action_spec(), flat_sequence=flattened_actions) --> 298 self._time_step = self._env.step(packed) 299 return tf.nest.flatten(self._time_step) File /usr/local/lib/python3.8/dist-packages/tf_agents/environments/py_environment.py:232, in PyEnvironment.step(self, action) 228 if (self._current_time_step is None or 229 self.should_reset(self._current_time_step)): 230 return self.reset() --> 232 self._current_time_step = self._step(action) 233 return self._current_time_step File /usr/local/lib/python3.8/dist-packages/tf_agents/environments/batched_py_environment.py:173, in BatchedPyEnvironment._step(self, actions) 169 if len(unstacked_actions) != self.batch_size: 170 raise ValueError( 171 "Primary dimension of action items does not match " 172 "batch size: %d vs. %d" % (len(unstacked_actions), self.batch_size)) --> 173 time_steps = self._execute( 174 lambda env_action: env_action[0].step(env_action[1]), 175 zip(self._envs, unstacked_actions)) 176 return nest_utils.stack_nested_arrays(time_steps) File /usr/local/lib/python3.8/dist-packages/tf_agents/environments/batched_py_environment.py:106, in BatchedPyEnvironment._execute(self, fn, iterable) 104 def _execute(self, fn, iterable): 105 if self._parallel_execution: --> 106 return self._pool.map(fn, iterable) 107 else: 108 return [fn(x) for x in iterable] File /usr/lib/python3.8/multiprocessing/pool.py:364, in Pool.map(self, func, iterable, chunksize) 359 def map(self, func, iterable, chunksize=None): 360 ''' 361 Apply `func` to each element in `iterable`, collecting the results 362 in a list that is returned. 363 ''' --> 364 return self._map_async(func, iterable, mapstar, chunksize).get() File /usr/lib/python3.8/multiprocessing/pool.py:771, in ApplyResult.get(self, timeout) 769 return self._value 770 else: --> 771 raise self._value File /usr/lib/python3.8/multiprocessing/pool.py:125, in worker(inqueue, outqueue, initializer, initargs, maxtasks, wrap_exception) 123 job, i, func, args, kwds = task 124 try: --> 125 result = (True, func(*args, **kwds)) 126 except Exception as e: 127 if wrap_exception and func is not _helper_reraises_exception: File /usr/lib/python3.8/multiprocessing/pool.py:48, in mapstar(args) 47 def mapstar(args): ---> 48 return list(map(*args)) File /usr/local/lib/python3.8/dist-packages/tf_agents/environments/batched_py_environment.py:174, in BatchedPyEnvironment._step.<locals>.<lambda>(env_action) 169 if len(unstacked_actions) != self.batch_size: 170 raise ValueError( 171 "Primary dimension of action items does not match " 172 "batch size: %d vs. %d" % (len(unstacked_actions), self.batch_size)) 173 time_steps = self._execute( --> 174 lambda env_action: env_action[0].step(env_action[1]), 175 zip(self._envs, unstacked_actions)) 176 return nest_utils.stack_nested_arrays(time_steps) File /usr/local/lib/python3.8/dist-packages/tf_agents/environments/py_environment.py:232, in PyEnvironment.step(self, action) 228 if (self._current_time_step is None or 229 self.should_reset(self._current_time_step)): 230 return self.reset() --> 232 self._current_time_step = self._step(action) 233 return self._current_time_step File /tf/notebooks/reinforcement/env.py:76, in StockTradingEnv._step(self, action) 74 if self._episode_ended: 75 self._episode_counter += 1 # 跟踪轮数的计数器增加 ---> 76 self._draw_charts() # 绘制并保存K线图和资金变化曲线 77 return ts.termination(np.array(self._state, dtype=np.float32), reward) 78 else: File /tf/notebooks/reinforcement/env.py:113, in StockTradingEnv._draw_charts(self) 104 stock_df = stock_df.set_index('Date') 106 trade_markers = [mpf.make_addplot([stock_df.iloc[trade[0]].Close if trade[1] == 'buy' else None 107 for trade in self._trades], scatter=True, markersize=200, color='g', 108 marker='^'), 109 mpf.make_addplot([stock_df.iloc[trade[0]].Close if trade[1] == 'sell' else None 110 for trade in self._trades], scatter=True, markersize=200, color='r', 111 marker='v')] --> 113 fig, axlist = mpf.plot(stock_df, type='candle', style='charles', addplot=trade_markers, 114 title=f'Stock Trading K - line - Episode {self._episode_counter}', returnfig=True) 115 axlist[0].legend(['Buy Signal', 'Sell Signal'], loc='upper left') 116 # 保存K线图 File /usr/local/lib/python3.8/dist-packages/mplfinance/plotting.py:808, in plot(data, **kwargs) 806 for column in apdata: 807 ydata = apdata.loc[:,column] if havedf else column --> 808 ax = _addplot_columns(panid,panels,ydata,apdict,xdates,config,colcount) 809 _addplot_apply_supplements(ax,apdict,xdates) 810 colcount += 1 File /usr/local/lib/python3.8/dist-packages/mplfinance/plotting.py:1107, in _addplot_columns(panid, panels, ydata, apdict, xdates, config, colcount) 1105 secondary_y = False 1106 if apdict['secondary_y'] == 'auto': -> 1107 yd = [y for y in ydata if not math.isnan(y)] 1108 ymhi = math.log(max(math.fabs(np.nanmax(yd)),1e-7),10) 1109 ymlo = math.log(max(math.fabs(np.nanmin(yd)),1e-7),10) File /usr/local/lib/python3.8/dist-packages/mplfinance/plotting.py:1107, in <listcomp>(.0) 1105 secondary_y = False 1106 if apdict['secondary_y'] == 'auto': -> 1107 yd = [y for y in ydata if not math.isnan(y)] 1108 ymhi = math.log(max(math.fabs(np.nanmax(yd)),1e-7),10) 1109 ymlo = math.log(max(math.fabs(np.nanmin(yd)),1e-7),10) TypeError: must be real number, not NoneType
answer:错误信息显示在尝试绘制addplot时,传给mplfinance的数据中有`None`,而mplfinance期望的是实数。这通常发生在试图为未发生的交易(即`None`点)绘制标记时。我们需要确保只传递有效的交易数据点给mplfinance。 为了解决这个问题,我们应该修改绘制图表的方式,只为实际发生的买入和卖出动作添加标记。这意味着当action等于1或2时,我们需要记录交易以及对应的时间步。下面我将展示如何修改`_draw_charts`方法来解决这个问题: ```python # ...省略其他代码,只显示_draw_charts方法... def _draw_charts(self): # 为绘制K线图准备数据 lengths = len(self._stock_data[:self._current_step]) stock_df = pd.DataFrame(self._stock_data[:self._current_step], columns=['Open', 'High', 'Low', 'Close']) stock_df['Date'] = pd.date_range(start='1/1/2000', periods=lengths, freq='B') stock_df = stock_df.set_index('Date') # 得到买入和卖出点的数据 buys = [self._stock_data[trade_step, 3] if trade_action == 'buy' else None for trade_step, trade_action in self._trades] sells = [self._stock_data[trade_step, 3] if trade_action == 'sell' else None for trade_step, trade_action in self._trades] buy_sell_signal = pd.DataFrame({'Buy': buys, 'Sell': sells}, index=stock_df.index) # 绘制股价K线图 apds = [mpf.make_addplot(buy_sell_signal['Buy'], type='scatter', markersize=100, marker='^', color='green'), mpf.make_addplot(buy_sell_signal['Sell'], type='scatter', markersize=100, marker='v', color='red')] mpf.plot(stock_df, type='candle', addplot=apds, style='yahoo', figsize=(10, 6), title=f'Stock Trading K-line - Episode {self._episode_counter}') # 保存股价K线图 plt.savefig(f"{self._filename}_{self._episode_counter}.png") # 绘制资产变化曲线 plt.figure(figsize=(10, 4)) plt.plot(self._total_asset_record, color='blue') plt.title(f'Total Asset Value - Episode {self._episode_counter}') plt.xlabel('Time Step') plt.ylabel('Total Asset Value') # 保存资产变化曲线图 plt.savefig(f"{self._filename}_{self._episode_counter}_assets.png") plt.close('all') # 关闭matplotlib的所有窗口 ``` 在这个更改后的代码中,我们首先为绘制K线图准备数据,然后创建一个新的DataFrame,其中包含了只对应于买入和卖出交易的价格数据点,其余为`None`。使用这个DataFrame来确保我们只为实际的交易添加标记点。接着使用mplfinance进行绘图,然后保存为图像文件。资产曲线的绘制过程也类似。最后,使用`plt.close('all')`来关闭所有可能未关闭的matplotlib窗口或图表。 请更新您的环境类以包含这些修改,并验证这个新的绘图实现是否正常工作并解决了先前的错误。这个解决方案假设`self._trades`是一个列表,其中每个交易都包含时间步(索引)和操作类型。请确保您在交易时正确地将交易数据添加到这个列表中。
question:stock_df['Date'] 可否换为数字
answer:在mplfinance库中,K线图的X轴是基于日期索引的,因为股票数据通常与时间相关联。mplfinance期望其传入的DataFrame有一个DatetimeIndex。 如果没有真实的日期数据,通常我们会创建一个代表时间序列的日期范围作为数据的索引。然而,如果您只希望使用步数的数字索引来代替具体的日期,那么不能直接在mplfinance中使用数字索引。您可以尝试通过自定义标签来在matplotlib上直接生成散点图。 不过,如果只是想在内部逻辑中使用数字索引,这当然是可行的。您可以使用一个递增的数字列表来替代日期索引,但实际绘图时,仍然需要符合mplfinance所需的日期索引。 例如,如果您想在DataFrame中使用数字索引,可以这样操作: ```python # 使用数字作为索引构建DataFrame lengths = len(self._stock_data[:self._current_step]) index = range(lengths) stock_df = pd.DataFrame(self._stock_data[:self._current_step], columns=['Open', 'High', 'Low', 'Close'], index=index) ``` 在上面的例子中,我们使用了一个简单的递增整数序列作为DataFrame的索引。注意这样做只限于在内部处理数据时使用数字索引,因为mplfinance绘图时将无法接受这种索引。如果想在mplfinance中使用该DataFrame绘制图表,您可能需要使用mplfinance外部的matplotlib功能来自行绘图。 如果您只是想要去除依赖于特定日期的假设,或者您已经有了一套规则化处理的日期数据,那么上述修改是可以的。但是,请记住对于mplfinance绘制K线图的目的,DataFrame仍然需要一个DatetimeIndex。
question:plt.savefig 同样的名字会覆盖吗
answer:是的,`plt.savefig` 会覆盖同名的文件。当你调用`plt.savefig(filename)`时,如果已经存在与`filename`相同名字的文件,matplotlib会覆盖这个文件,而不会给出任何警告。 如果你不希望覆盖现有文件,可以在保存之前检查文件是否存在,并根据需要调整文件名。这可以用Python标准库中的`os.path.exists()`函数来实现: ```python import os # 文件名 file_path = f"{self._filename}_{self._episode_counter}.png" # 检查文件是否存在,如果存在,则调整文件名以避免覆盖 if os.path.exists(file_path): # 可以添加一个额外的后缀或数字 file_path = f"{self._filename}_{self._episode_counter}_2.png" # 保存文件 plt.savefig(file_path) ``` 在实际使用中,您可以设计一个更复杂的逻辑来处理重复的文件名,例如,在文件名后添加递增的编号或者时间戳,以确保每个文件都有唯一的文件名。
question:还是报错 : --------------------------------------------------------------------------- ValueError Traceback (most recent call last) Cell In [4], line 1 ----> 1 returns = train(train_env, eval_env, model_name=model_name) File /tf/notebooks/reinforcement/train.py:89, in train(train_env, eval_env, model_name, epoch, num_iterations, collect_steps_per_iteration, log_interval, eval_interval) 86 with tqdm(total=len(range(num_iterations))) as progress_bar: 87 for _ in range(num_iterations): 88 # 从训练环境中收集一些步骤(使用代理的collect_policy)并存储到replay buffer。 ---> 89 collect_data(train_env, agent.collect_policy, replay_buffer, collect_steps_per_iteration) 91 # 每次收集后都从replay buffer中取出一小批数据用于学习。 92 experience, _ = next(iterator) File /tf/notebooks/reinforcement/train.py:15, in collect_data(env, policy, buffer, steps) 13 def collect_data(env, policy, buffer, steps): 14 for _ in range(steps): ---> 15 collect_step(env, policy, buffer) File /tf/notebooks/reinforcement/learn.py:108, in collect_step(environment, policy, replay_buffer) 106 time_step = environment.current_time_step() 107 action_step = policy.action(time_step) --> 108 next_time_step = environment.step(action_step.action) 109 traj = trajectory.from_transition(time_step, action_step, next_time_step) 110 replay_buffer.add_batch(traj) File /usr/local/lib/python3.8/dist-packages/tf_agents/environments/tf_environment.py:241, in TFEnvironment.step(self, action) 211 def step(self, action): 212 """Steps the environment according to the action. 213 214 If the environment returned a `TimeStep` with `StepType.LAST` at the (...) 239 corresponding to `observation_spec()`. 240 """ --> 241 return self._step(action) File /usr/local/lib/python3.8/dist-packages/tf_agents/environments/tf_py_environment.py:315, in TFPyEnvironment._step(self, actions) 309 if (action.shape.rank == 0 or 310 (dim_value is not None and dim_value != self.batch_size)): 311 raise ValueError( 312 'Expected actions whose major dimension is batch_size (%d), ' 313 'but saw action with shape %s:n %s' % 314 (self.batch_size, action.shape, action)) --> 315 outputs = tf.numpy_function( 316 _isolated_step_py, 317 flat_actions, 318 self._time_step_dtypes, 319 name='step_py_func') 320 return self._time_step_from_numpy_function_outputs(outputs) File /usr/local/lib/python3.8/dist-packages/tensorflow/python/util/traceback_utils.py:153, in filter_traceback.<locals>.error_handler(*args, **kwargs) 151 except Exception as e: 152 filtered_tb = _process_traceback_frames(e.__traceback__) --> 153 raise e.with_traceback(filtered_tb) from None 154 finally: 155 del filtered_tb File /usr/local/lib/python3.8/dist-packages/tf_agents/environments/tf_py_environment.py:302, in TFPyEnvironment._step.<locals>._isolated_step_py(*flattened_actions) 301 def _isolated_step_py(*flattened_actions): --> 302 return self._execute(_step_py, *flattened_actions) File /usr/local/lib/python3.8/dist-packages/tf_agents/environments/tf_py_environment.py:211, in TFPyEnvironment._execute(self, fn, *args, **kwargs) 209 def _execute(self, fn, *args, **kwargs): 210 if not self._pool: --> 211 return fn(*args, **kwargs) 212 return self._pool.apply(fn, args=args, kwds=kwargs) File /usr/local/lib/python3.8/dist-packages/tf_agents/environments/tf_py_environment.py:298, in TFPyEnvironment._step.<locals>._step_py(*flattened_actions) 295 with _check_not_called_concurrently(self._lock): 296 packed = tf.nest.pack_sequence_as( 297 structure=self.action_spec(), flat_sequence=flattened_actions) --> 298 self._time_step = self._env.step(packed) 299 return tf.nest.flatten(self._time_step) File /usr/local/lib/python3.8/dist-packages/tf_agents/environments/py_environment.py:232, in PyEnvironment.step(self, action) 228 if (self._current_time_step is None or 229 self.should_reset(self._current_time_step)): 230 return self.reset() --> 232 self._current_time_step = self._step(action) 233 return self._current_time_step File /usr/local/lib/python3.8/dist-packages/tf_agents/environments/batched_py_environment.py:173, in BatchedPyEnvironment._step(self, actions) 169 if len(unstacked_actions) != self.batch_size: 170 raise ValueError( 171 "Primary dimension of action items does not match " 172 "batch size: %d vs. %d" % (len(unstacked_actions), self.batch_size)) --> 173 time_steps = self._execute( 174 lambda env_action: env_action[0].step(env_action[1]), 175 zip(self._envs, unstacked_actions)) 176 return nest_utils.stack_nested_arrays(time_steps) File /usr/local/lib/python3.8/dist-packages/tf_agents/environments/batched_py_environment.py:106, in BatchedPyEnvironment._execute(self, fn, iterable) 104 def _execute(self, fn, iterable): 105 if self._parallel_execution: --> 106 return self._pool.map(fn, iterable) 107 else: 108 return [fn(x) for x in iterable] File /usr/lib/python3.8/multiprocessing/pool.py:364, in Pool.map(self, func, iterable, chunksize) 359 def map(self, func, iterable, chunksize=None): 360 ''' 361 Apply `func` to each element in `iterable`, collecting the results 362 in a list that is returned. 363 ''' --> 364 return self._map_async(func, iterable, mapstar, chunksize).get() File /usr/lib/python3.8/multiprocessing/pool.py:771, in ApplyResult.get(self, timeout) 769 return self._value 770 else: --> 771 raise self._value File /usr/lib/python3.8/multiprocessing/pool.py:125, in worker(inqueue, outqueue, initializer, initargs, maxtasks, wrap_exception) 123 job, i, func, args, kwds = task 124 try: --> 125 result = (True, func(*args, **kwds)) 126 except Exception as e: 127 if wrap_exception and func is not _helper_reraises_exception: File /usr/lib/python3.8/multiprocessing/pool.py:48, in mapstar(args) 47 def mapstar(args): ---> 48 return list(map(*args)) File /usr/local/lib/python3.8/dist-packages/tf_agents/environments/batched_py_environment.py:174, in BatchedPyEnvironment._step.<locals>.<lambda>(env_action) 169 if len(unstacked_actions) != self.batch_size: 170 raise ValueError( 171 "Primary dimension of action items does not match " 172 "batch size: %d vs. %d" % (len(unstacked_actions), self.batch_size)) 173 time_steps = self._execute( --> 174 lambda env_action: env_action[0].step(env_action[1]), 175 zip(self._envs, unstacked_actions)) 176 return nest_utils.stack_nested_arrays(time_steps) File /usr/local/lib/python3.8/dist-packages/tf_agents/environments/py_environment.py:232, in PyEnvironment.step(self, action) 228 if (self._current_time_step is None or 229 self.should_reset(self._current_time_step)): 230 return self.reset() --> 232 self._current_time_step = self._step(action) 233 return self._current_time_step File /tf/notebooks/reinforcement/env.py:78, in StockTradingEnv._step(self, action) 76 if self._episode_ended: 77 self._episode_counter += 1 # 跟踪轮数的计数器增加 ---> 78 self._draw_charts() # 绘制并保存K线图和资金变化曲线 79 return ts.termination(np.array(self._state, dtype=np.float32), reward) 80 else: File /tf/notebooks/reinforcement/env.py:115, in StockTradingEnv._draw_charts(self) 111 buys = [self._stock_data[trade_step, 3] if trade_action == 'buy' else None 112 for trade_step, trade_action in self._trades] 113 sells = [self._stock_data[trade_step, 3] if trade_action == 'sell' else None 114 for trade_step, trade_action in self._trades] --> 115 buy_sell_signal = pd.DataFrame({'Buy': buys, 'Sell': sells}, index=stock_df.index) 117 # 绘制股价K线图 118 apds = [ 119 mpf.make_addplot(buy_sell_signal['Buy'], type='scatter', markersize=100, marker=' ^ ', color='green'), 120 mpf.make_addplot(buy_sell_signal['Sell'], type='scatter', markersize=100, marker='v', color='red')] File /usr/local/lib/python3.8/dist-packages/pandas/core/frame.py:709, in DataFrame.__init__(self, data, index, columns, dtype, copy) 703 mgr = self._init_mgr( 704 data, axes={"index": index, "columns": columns}, dtype=dtype, copy=copy 705 ) 707 elif isinstance(data, dict): 708 # GH#38939 de facto copy defaults to False only in non-dict cases --> 709 mgr = dict_to_mgr(data, index, columns, dtype=dtype, copy=copy, typ=manager) 710 elif isinstance(data, ma.MaskedArray): 711 from numpy.ma import mrecords File /usr/local/lib/python3.8/dist-packages/pandas/core/internals/construction.py:481, in dict_to_mgr(data, index, columns, dtype, typ, copy) 477 else: 478 # dtype check to exclude e.g. range objects, scalars 479 arrays = [x.copy() if hasattr(x, "dtype") else x for x in arrays] --> 481 return arrays_to_mgr(arrays, columns, index, dtype=dtype, typ=typ, consolidate=copy) File /usr/local/lib/python3.8/dist-packages/pandas/core/internals/construction.py:120, in arrays_to_mgr(arrays, columns, index, dtype, verify_integrity, typ, consolidate) 117 index = ensure_index(index) 119 # don't force copy because getting jammed in an ndarray anyway --> 120 arrays, refs = _homogenize(arrays, index, dtype) 121 # _homogenize ensures 122 # - all(len(x) == len(index) for x in arrays) 123 # - all(x.ndim == 1 for x in arrays) (...) 126 127 else: 128 index = ensure_index(index) File /usr/local/lib/python3.8/dist-packages/pandas/core/internals/construction.py:608, in _homogenize(data, index, dtype) 605 val = lib.fast_multiget(val, oindex._values, default=np.nan) 607 val = sanitize_array(val, index, dtype=dtype, copy=False) --> 608 com.require_length_match(val, index) 609 refs.append(None) 611 homogenized.append(val) File /usr/local/lib/python3.8/dist-packages/pandas/core/common.py:576, in require_length_match(data, index) 572 """ 573 Check the length of data matches the length of the index. 574 """ 575 if len(data) != len(index): --> 576 raise ValueError( 577 "Length of values " 578 f"({len(data)}) " 579 "does not match length of index " 580 f"({len(index)})" 581 ) ValueError: Length of values (74) does not match length of index (518) --- 代码: def _draw_charts(self): # 为绘制K线图准备数据 lengths = len(self._stock_data[:self._current_step]) stock_df = pd.DataFrame(self._stock_data[:self._current_step], columns=['Open', 'High', 'Low', 'Close']) stock_df['Date'] = pd.date_range(start='1/1/2000', periods=lengths, freq='B') stock_df = stock_df.set_index('Date') # 得到买入和卖出点的数据 buys = [self._stock_data[trade_step, 3] if trade_action == 'buy' else None for trade_step, trade_action in self._trades] sells = [self._stock_data[trade_step, 3] if trade_action == 'sell' else None for trade_step, trade_action in self._trades] buy_sell_signal = pd.DataFrame({'Buy': buys, 'Sell': sells}, index=stock_df.index) # 绘制股价K线图 apds = [ mpf.make_addplot(buy_sell_signal['Buy'], type='scatter', markersize=100, marker=' ^ ', color='green'), mpf.make_addplot(buy_sell_signal['Sell'], type='scatter', markersize=100, marker='v', color='red')] mpf.plot(stock_df, type='candle', addplot=apds, style='yahoo', figsize=(10, 6), title=f'Stock Trading K - line - Episode {self._episode_counter}') # 保存股价K线图 plt.savefig(f"{self._plt_dir}{self.filename}{self._episode_counter}.png") # 绘制资产变化曲线 plt.figure(figsize=(10, 4)) plt.plot(self._total_asset_record, color='blue') plt.title(f'Total Asset Value - Episode {self._episode_counter}') plt.xlabel('Time Step') plt.ylabel('Total Asset Value') # 保存资产变化曲线图 plt.savefig(f"{self._plt_dir}{self.filename}{self._episode_counter}_assets.png") plt.close('all') # 关闭matplotlib的所有窗口
answer:错误提示的根源在于向`pd.DataFrame`中传递的'Buy'和'Sell'列中的数据长度与`stock_df.index`的长度不匹配。问题出现在使用列表推导式的方式去创建`buys`和`sells`时,这些列表的长度实际上与执行买入和卖出操作的次数相同,而不是与K线数据的长度(`self._current_step`)相同。 为了正确地绘制交易标记,我们需要先创建一个与K线数据长度相等且默认值为`None`的`buys`和`sells`数组,然后只在实际发生交易的步长处填充买入和卖出的价格。修正过的`_draw_charts`方法如下所示: ```python def _draw_charts(self): # 为绘制K线图准备数据 lengths = len(self._stock_data[:self._current_step]) stock_df = pd.DataFrame(self._stock_data[:self._current_step], columns=['Open', 'High', 'Low', 'Close']) stock_df['Date'] = pd.date_range(start='1/1/2000', periods=lengths, freq='B') stock_df = stock_df.set_index('Date') # 初始化buys和sells数组 buys = [None] * lengths sells = [None] * lengths for trade_step, trade_action in self._trades: if trade_action == 'buy': buys[trade_step-self._history_length] = stock_df['Close'].iloc[trade_step-self._history_length] elif trade_action == 'sell': sells[trade_step-self._history_length] = stock_df['Close'].iloc[trade_step-self._history_length] buy_signals = mpf.make_addplot(buys, type='scatter', markersize=100, marker='^', color='green', panel=0) sell_signals = mpf.make_addplot(sells, type='scatter', markersize=100, marker='v', color='red', panel=0) # 绘制K线图 mpf.plot(stock_df, type='candle', addplot=[buy_signals, sell_signals], style='yahoo', figsize=(10, 6), title=f'Stock Trading K-line - Episode {self._episode_counter}') # 保存K线图 plot_filename = f"{self._filename}_ep_{self._episode_counter}.png" plt.savefig(plot_filename) # 绘制资金变化曲线 plt.figure(figsize=(10, 4)) plt.plot(self._total_asset_record, color='blue') plt.title(f'Total Asset Value - Episode {self._episode_counter}') plt.xlabel('Time Step') plt.ylabel('Total Asset Value') # 保存资金变化曲线图 assets_filename = f"{self._filename}_ep_{self._episode_counter}_assets.png" plt.savefig(assets_filename) plt.close('all') # 关闭matplotlib的所有窗口 ``` 在这段修改过的代码中,我们初始化了与`self._stock_data`相等长度的`buys`和`sells`数据数组。然后通过遍历`self._trades`来设置相应股票操作的价格。确保交易记录的步骤`trade_step`与K线数据的时间步对齐。然后,我们使用`make_addplot`创建买入和卖出信号的绘图,并将其传递给`mpf.plot`。 请注意以下几点: - 确保在`self._trades`添加交易时记录了对应的**实际步数**而非索引(例如,可能需要考虑到`_history_length`的偏移)。 - 您可能需要根据您K线数据的时间范围和出现的交易实际调整代码中数组索引操作的逻辑。 - 当前示例中的日期开始于 `1/1/2000`,并偏设每个时间步对应一个工作日。 替换为您具体数据的时间信息。 - 在保存图表的文件路径,请确保该路径存在,有权访问,并且考虑系统的文件分隔符。 现在,您应该能够将上述代码插入您的环境类中,并用其替换之前的`_draw_charts`方法,以创建交易标记并保存K线图和资金变化曲线。