基于条件的Pandas递归切片及交易指标计算需求
问题需求
- 定位所有
slice列值为10的行; - 对每个
slice=10的行,确定其与前一个slice列非0值行之间的区间; - 计算该区间内:
- Entry Price:
open列与close列的最小值; - Stop Loss:
low列的最小值减去10; - Target:
Entry Price + (Entry Price - Stop Loss)*2;
- Entry Price:
- 若前一个行的
slice值也为10,则排除该行作为区间起始行。
现有DataFrame
date open high low close slice 0 2022-05-19 09:15:00 33461.00 33624.90 33403.20 33412.45 0 1 2022-05-19 09:20:00 33413.10 33450.65 33393.90 33429.10 0 2 2022-05-19 09:25:00 33433.20 33490.05 33421.95 33460.25 0 3 2022-05-19 09:30:00 33460.55 33509.40 33419.05 33489.80 0 4 2022-05-19 09:35:00 33492.20 33506.40 33450.30 33454.70 20 5 2022-05-19 09:40:00 33452.25 33452.95 33396.40 33436.15 0 6 2022-05-19 09:45:00 33434.30 33454.80 33401.35 33439.05 0 7 2022-05-19 09:50:00 33438.30 33482.85 33423.50 33477.30 10 8 2022-05-19 09:55:00 33480.60 33535.85 33462.40 33523.65 30 9 2022-05-19 10:00:00 33527.65 33527.65 33484.10 33521.40 0 10 2022-05-19 10:05:00 33519.35 33599.25 33505.95 33530.55 0 11 2022-05-19 10:10:00 33527.50 33544.20 33496.60 33538.65 0 12 2022-05-19 10:15:00 33540.15 33565.85 33522.75 33563.25 0 13 2022-05-19 10:20:00 33563.50 33582.45 33525.95 33539.25 0 14 2022-05-19 10:25:00 33537.25 33537.50 33511.80 33516.35 20 15 2022-05-19 10:30:00 33518.00 33561.80 33513.60 33528.55 0 16 2022-05-19 10:35:00 33527.80 33551.00 33527.55 33550.50 10 17 2022-05-19 10:40:00 33551.50 33573.60 33525.85 33537.45 0 18 2022-05-19 10:45:00 33534.80 33563.10 33510.75 33555.95 0 19 2022-05-19 10:50:00 33555.55 33573.45 33540.45 33541.00 0 20 2022-05-19 10:55:00 33545.40 33586.80 33542.75 33586.80 10
现有代码
def buy_sell(data): Time = [] SignalBuy = [] BuySL = [] BuyTgt = [] for i in range(len(data)): if data["slice"][i] == 10: Time.append(data["date"][i]) entry = data["open"][i] sl = data["low"][i] - 10 SignalBuy.append(entry) BuySL.append(sl) BuyTgt.append(entry + (entry - sl) * 2) return pd.Series([Time, SignalBuy, BuyTgt, BuySL]) SignalDemand = pd.DataFrame() SignalDemand["Time"], SignalDemand["Entry Price"], SignalDemand["Target"], SignalDemand["Stop Loss"] = buy_sell(data) print(SignalDemand.head())
当前输出
Time Entry Price Target Stop Loss 0 2022-05-19 09:50:00 33438.30 33487.90 33413.50 1 2022-05-19 10:35:00 33527.80 33548.30 33517.55 2 2022-05-19 10:55:00 33545.40 33570.70 33532.75
期望输出
Time Entry Price Target Stop Loss 0 2022-05-19 09:50:00 33434.30 33530.10 33386.40 1 2022-05-19 10:35:00 33516.35 33545.45 33501.80 2 2022-05-19 10:55:00 33534.80 33602.90 33500.75
解决方案
修正后的代码如下,核心逻辑是找到每个slice=10行对应的有效区间,再在区间内计算指标:
import pandas as pd def buy_sell(data): Time = [] EntryPrice = [] StopLoss = [] Target = [] # 筛选所有slice非0的行,保留索引和slice值 non_zero_slices = data[data['slice'] != 0][['slice']].reset_index() # 获取所有slice=10的行的索引列表 slice_10_indices = data[data['slice'] == 10].index.tolist() for idx in slice_10_indices: # 找到当前索引之前,slice非0且不等于10的最近行 valid_prev = non_zero_slices[(non_zero_slices['index'] < idx) & (non_zero_slices['slice'] != 10)] if not valid_prev.empty: # 区间起始为前一个有效行的下一行 start_idx = valid_prev['index'].iloc[-1] + 1 # 提取区间内的所有行 interval_data = data.loc[start_idx:idx] # 计算Entry Price:open和close的最小值 entry = min(interval_data['open'].min(), interval_data['close'].min()) # 计算Stop Loss:low的最小值减10 sl = interval_data['low'].min() - 10 # 计算Target tgt = entry + (entry - sl) * 2 # 收集结果 Time.append(data['date'].loc[idx]) EntryPrice.append(entry) StopLoss.append(sl) Target.append(tgt) return pd.Series([Time, EntryPrice, Target, StopLoss]) # 初始化给定的DataFrame data = pd.DataFrame({ 'date': ['2022-05-19 09:15:00', '2022-05-19 09:20:00', '2022-05-19 09:25:00', '2022-05-19 09:30:00', '2022-05-19 09:35:00', '2022-05-19 09:40:00', '2022-05-19 09:45:00', '2022-05-19 09:50:00', '2022-05-19 09:55:00', '2022-05-19 10:00:00', '2022-05-19 10:05:00', '2022-05-19 10:10:00', '2022-05-19 10:15:00', '2022-05-19 10:20:00', '2022-05-19 10:25:00', '2022-05-19 10:30:00', '2022-05-19 10:35:00', '2022-05-19 10:40:00', '2022-05-19 10:45:00', '2022-05-19 10:50:00', '2022-05-19 10:55:00'], 'open': [33461.00, 33413.10, 33433.20, 33460.55, 33492.20, 33452.25, 33434.30, 33438.30, 33480.60, 33527.65, 33519.35, 33527.50, 33540.15, 33563.50, 33537.25, 33518.00, 33527.80, 33551.50, 33534.80, 33555.55, 33545.40], 'high': [33624.90, 33450.65, 33490.05, 33509.40, 33506.40, 33452.95, 33454.80, 33482.85, 33535.85, 33527.65, 33599.25, 33544.20, 33565.85, 33582.45, 33537.50, 33561.80, 33551.00, 33573.60, 33563.10, 33573.45, 33586.80], 'low': [33403.20, 33393.90, 33421.95, 33419.05, 33450.30, 33396.40, 33401.35, 33423.50, 33462.40, 33484.10, 33505.95, 33496.60, 33522.75, 33525.95, 33511.80, 33513.60, 33527.55, 33525.85, 33510.75, 33540.45, 33542.75], 'close': [33412.45, 33429.10, 33460.25, 33489.80, 33454.70, 33436.15, 33439.05, 33477.30, 33523.65, 33521.40, 33530.55, 33538.65, 33563.25, 33539.25, 33516.35, 33528.55, 33550.50, 33537.45, 33555.95, 33541.00, 33586.80], 'slice': [0, 0, 0, 0, 20, 0, 0, 10, 30, 0, 0, 0, 0, 0, 20, 0, 10, 0, 0, 0, 10] }) # 生成结果DataFrame SignalDemand = pd.DataFrame() SignalDemand["Time"], SignalDemand["Entry Price"], SignalDemand["Target"], SignalDemand["Stop Loss"] = buy_sell(data) print(SignalDemand)
代码说明
- 先筛选出所有
slice非0的行,方便快速定位每个slice=10行的前一个有效起始点; - 遍历每个
slice=10的行索引,找到其之前最近的slice≠0且≠10的行,以此确定区间的起始位置(起始行的下一行到当前slice=10的行); - 在目标区间内计算三个指标:
- Entry Price:取区间内`
相关产品推荐
相关产品推荐

