【期权合约排序】由于dataframe多列排序算法bug,可以创建复合键数组实现多列排序

//------------------------------------------------------------------------ // 简称: NAME // 名称: // 类别: 策略应用 // 类型: 用户应用 // 输出: Void //------------------------------------------------------------------------ Params Vars //此处添加变量 Global Array<Array<String>> stock_codes; Numeric i; Numeric j; Numeric k; Numeric index; Numeric cx; DataFrame df; DataFrame df2; Events //此处实现事件函数 //初始化事件函数,策略运行期间,首先运行且只有一次,应用在订阅数据等操作 OnInit() { //与数据源有关 stock_codes[0] = ["000300.SSE"]; for i = 0 to GetArraySize(stock_codes[0]) - 1 { SubscribeBar(stock_codes[0][i], "1m", 20251013); } Array<string> str; GetOptSymbolsByCode("510300.SSE", str); Array<string> Callcontracts = str; CodeProperty props; // 存储数据的数组 Array<Numeric> datas1; // ExpiredDateTime Array<Numeric> datas3; // opType Array<Numeric> datas4; // strikePrice Array<Numeric> datas5; // OpenDateTime Array<string> datas6; // Symbol Array<string> datas7; // SymbolName Array<string> datas8; // symbolType // 用于DataFrame的map map<String, Array<Numeric>> datas2; for i = 0 to GetArraySize(Callcontracts) - 1 { GetProperty(Callcontracts[i], props); datas2["props.ExpiredDateTime"][i] = props.ExpiredDateTime; datas1[i] = props.ExpiredDateTime; datas3[i] = props.opType; datas4[i] = props.strikePrice; datas5[i] = props.OpenDateTime; datas6[i] = props.Symbol; datas7[i] = props.SymbolName; datas8[i] = props.symbolType; } // 初始化并显示原始DataFrame df.init(datas2); df.setPos("opType", [:], datas3); df.setPos("strikePrice", [:], datas4); df.setPos("OpenDateTime", [:], datas5); df.setPos("SymbolName", [:], datas7); df.setPos("symbolType", [:], datas8); df.setPos("Symbol", [:], datas6); print(df.toString()); // ========== 复合键排序方法 ========== Print("\n=== 开始复合键排序 ==="); // 创建复合键数组 Array<Numeric> compositeKeys; Array<Numeric> originalIndices; for i = 0 to GetArraySize(Callcontracts) - 1 { GetProperty(Callcontracts[i], props); // 转换为排序用的键值 // 注意:我们使用负号来实现降序排序 // 1. ExpiredDateTime(最主要权重,降序) // 格式:20251224.180000 → 202512241800000 Numeric expKey = props.ExpiredDateTime*10000000; // 2. 分红影响(根据symbol长度,升序)12>12000 Numeric lenKey = -1*Len(props.symbol)*1000;// // 3. opType(次要权重,降序:2认沽 > 1认购) // 放大到100级别,2>200 Numeric opKey = props.opType * 100; // 10^10 // 4. strikePrice(第三权重,降序) Numeric strikeKey = props.strikePrice ; // // 构建复合键(用负数实现降序排序) compositeKeys[i] = -(expKey + lenKey + opKey + strikeKey ); // 保存原始索引 originalIndices[i] = i; } // 创建索引数组 Array<Integer> id1; Array<Integer> id2; for i = 0 to GetArraySize(Callcontracts) - 1 { id1[i] = i; id2[i] = i; } // 使用复合键进行一次排序 // 注意:复合键是负数,所以用升序排序实际上是降序 SortIds(compositeKeys, id1, id2, 0, GetArraySize(id1) - 1, True); // 根据最终索引重新排列合约 Array<String> sortedContracts; for i = 0 to GetArraySize(id1) - 1 { sortedContracts[i] = Callcontracts[id1[i]]; } // ========== 重新整理数据用于df2 ========== // 注意:需要重新获取属性,因为sortedContracts的顺序已经改变 for i = 0 to GetArraySize(sortedContracts) - 1 { GetProperty(sortedContracts[i], props); datas2["props.ExpiredDateTime"][i] = props.ExpiredDateTime; datas1[i] = props.ExpiredDateTime; datas3[i] = props.opType; datas4[i] = props.strikePrice; datas5[i] = props.OpenDateTime; datas6[i] = props.Symbol; datas7[i] = props.SymbolName; datas8[i] = props.symbolType; } // 创建并显示排序后的DataFrame df2.init(datas2); df2.setPos("opType", [:], datas3); df2.setPos("strikePrice", [:], datas4); df2.setPos("OpenDateTime", [:], datas5); df2.setPos("SymbolName", [:], datas7); df2.setPos("symbolType", [:], datas8); df2.setPos("Symbol", [:], datas6); print(df2.toString()); } 最近也在研究期权,dataframe用起来更顺眼,可惜多列排序有bug,绞尽脑汁终于搞定^_^,效果如下:

先Mark一下等有空再深入学习请教🙏

收藏好久才仔细看哇 太妙了 这脑子怎么长的

回复:😁

回复:先生大财👍

回复:看着你的帖子溯源写的😁,你写完期权函数之后,官方更新了这个GetOptSymbolsByCode函数,就方便了

回复:这个函数我感觉用处不大不方便如果只是读取期权合约自己一两行代码就完成了……

回复:总体而言你的合约属性+双数组方式更易于理解和维护先生大才

回复:我就写了个排序,那时候啥都没有,要不是看你写期权合约的函数,我都不知道怎么弄期权了🙃

回复:可别这么说,我是你的迷弟啊😋

回复:大佬们互相谦虚了你们分享好货 我跟在后面抄一抄

回复:你也超强,人形字典👍

回复: