分享

强化学习DeepAlpha之“逆波兰表达式”,去除qlib依赖(代码+数据)

 AI量化实验室 2024-04-25 发布于北京

原创文章第521篇,专注“AI量化投资、世界运行的规律、个人成长与财富自由"。

逆波兰表达式如何构建,是强化学习因子挖掘的关系:网上有开源的代码,使用qlib的底层,实现了很多类,用递归的方式,很不好理解,而且与qlib的因子表达式绑定的很厉害:

我重写了这个问题,只需要token。——这里的逻辑与 gplearn 里构建的表达式树的逻辑一样,重点是如何校验生成的表达式是有效的,而不是一堆token的混合体。

# from alphagen.data.expression import *
from typing import List

from datafeed.mining.tokens import *
from datafeed.expr_functions import *

class ExpressionBuilder:
stack: List[Token]

def __init__(self):
self.stack = []

def get_tree(self) -> Token:
if len(self.stack) == 1:
return self.stack[0]
else:
raise InvalidExpressionException(f"Expected only one tree, got {len(self.stack)}")

def add_token(self, token: Token):
if not self.validate(token):
raise InvalidExpressionException(f"Token {token} not allowed here, stack: {self.stack}.")
if isinstance(token, OperatorToken):
n_args: int = token.n_args()
children = []
for _ in range(n_args):
children.append(self.stack.pop())
token.add_children(list(reversed(children)))
self.stack.append(token)
elif isinstance(token, ConstantToken):
self.stack.append(token)
elif isinstance(token, DeltaTimeToken):
self.stack.append(token)
elif isinstance(token, FeatureToken):
self.stack.append(token)
else:
assert False

def is_valid(self) -> bool:
return len(self.stack) == 1 and self.stack[0].is_featured

def validate(self, token: Token) -> bool:
if isinstance(token, OperatorToken):
return self.validate_op(token)
elif isinstance(token, DeltaTimeToken):
return self.validate_dt()
elif isinstance(token, ConstantToken):
return self.validate_const()
elif isinstance(token, FeatureToken):
return self.validate_feature()
else:
assert False

def validate_op(self, op: Type[OperatorToken]) -> bool:
if len(self.stack) < op.n_args():
return False

if isinstance(op, UnaryOpsToken):
if not self.stack[-1].is_featured:
return False
elif isinstance(op, BinaryOpsToken):
if not self.stack[-1].is_featured and not self.stack[-2].is_featured:
return False
if (isinstance(self.stack[-1], DeltaTimeToken) or
isinstance(self.stack[-2], DeltaTimeToken)):
return False
elif isinstance(op, UnaryRollingOpsToken):
if not isinstance(self.stack[-1], DeltaTimeToken):
return False
if not self.stack[-2].is_featured:
return False
elif isinstance(op, BinaryRollingOpsToken):
if not isinstance(self.stack[-1], DeltaTimeToken):
return False
if not self.stack[-2].is_featured or not self.stack[-3].is_featured:
return False
else:
assert False
return True

def validate_dt(self) -> bool:
return len(self.stack) > 0 and self.stack[-1].is_featured

def validate_const(self) -> bool:
return len(self.stack) == 0 or self.stack[-1].is_featured

def validate_feature(self) -> bool:
return not (len(self.stack) >= 1 and isinstance(self.stack[-1], DeltaTimeToken))


class InvalidExpressionException(ValueError):
pass


if __name__ == '__main__':
tokens = [
FeatureToken(FeatureType.LOW),
UnaryOpsToken(abs),
DeltaTimeToken(10),
UnaryRollingOpsToken(rank),
FeatureToken(FeatureType.HIGH),
FeatureToken(FeatureType.CLOSE),
BinaryOpsToken(Div),
BinaryOpsToken(Add),
]

builder = ExpressionBuilder()
for token in tokens:
#print(token)
builder.add_token(token)
#print(builder.stack)
print(f'res: {str(builder.get_tree())}')
print(f'ref: Add(rank(abs(low),10),Div(high,close))')

我们已经正确生成了表达式,当然可以把Add,Div简化成 + 和 /,这是小事了。

后续加上强化学习的环境,结合咱们的因子计算引擎,就可以进行因子挖掘了。

代码在如下位置:

重构强化学习DeepAlpha之“逆波兰表达式”构建(代码+数据)

AI量化实验室——2024量化投资的星辰大海

吾日三省吾身

高速增长的团队或组织,也并不是没有问题和矛盾,只是矛盾和消化在增长中。

大家也不是着急抢地盘,机会多的是;

出现一些问题也能消化,也因为机会多的是,所以大家相对和谐。

当周期下行,矛盾凸显。

蛋糕就这么大,开始分存量蛋糕的时候,情况就不同了。

当然,古代的仕途华山一条道,因此都是你死我活。

职场再怎么着,总有别的路可以走。

历史文章:

重构强化学习DeepAlpha之“逆波兰表达式”构建(代码+数据)

AI量化实验室——2024量化投资的星辰大海

    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约