This commit is contained in:
jack
2026-04-22 11:31:11 +08:00
parent 2f420e3348
commit 61633b21b4
25 changed files with 14763 additions and 0 deletions
+1803
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -0,0 +1 @@
# Transformer module
+1514
View File
File diff suppressed because it is too large Load Diff
+180
View File
@@ -0,0 +1,180 @@
import json
import os
from typing import Union
import pandas as pd
from pandas.io.formats.style import Styler
brain_api_url = os.environ.get("BRAIN_API_URL", "https://api.worldquantbrain.com")
brain_url = os.environ.get("BRAIN_URL", "https://platform.worldquantbrain.com")
def make_clickable_alpha_id(alpha_id: str) -> str:
"""
Create a clickable HTML link for an alpha ID.
Args:
alpha_id (str): The ID of the alpha.
Returns:
str: An HTML string containing a clickable link to the alpha's page on the platform.
"""
url = brain_url + "/alpha/"
return f'<a href="{url}{alpha_id}">{alpha_id}</a>'
def prettify_result(
result: list, detailed_tests_view: bool = False, clickable_alpha_id: bool = False
) -> Union[pd.DataFrame, Styler]:
"""
Combine and format simulation results into a single DataFrame for analysis.
Args:
result (list): A list of dictionaries containing simulation results.
detailed_tests_view (bool, optional): If True, include detailed test results. Defaults to False.
clickable_alpha_id (bool, optional): If True, make alpha IDs clickable. Defaults to False.
Returns:
pandas.DataFrame or pandas.io.formats.style.Styler: A DataFrame containing formatted results,
optionally with clickable alpha IDs.
"""
list_of_is_stats = [result[x]["is_stats"] for x in range(len(result)) if result[x]["is_stats"] is not None]
is_stats_df = pd.concat(list_of_is_stats).reset_index(drop=True)
is_stats_df = is_stats_df.sort_values("fitness", ascending=False)
expressions = {
result[x]["alpha_id"]: (
{
"selection": result[x]["simulate_data"]["selection"],
"combo": result[x]["simulate_data"]["combo"],
}
if result[x]["simulate_data"]["type"] == "SUPER"
else result[x]["simulate_data"]["regular"]
)
for x in range(len(result))
if result[x]["is_stats"] is not None
}
expression_df = pd.DataFrame(list(expressions.items()), columns=["alpha_id", "expression"])
list_of_is_tests = [result[x]["is_tests"] for x in range(len(result)) if result[x]["is_tests"] is not None]
is_tests_df = pd.concat(list_of_is_tests, sort=True).reset_index(drop=True)
is_tests_df = is_tests_df[is_tests_df["result"] != "WARNING"]
if detailed_tests_view:
cols = ["limit", "result", "value"]
is_tests_df["details"] = is_tests_df[cols].to_dict(orient="records")
is_tests_df = is_tests_df.pivot(index="alpha_id", columns="name", values="details").reset_index()
else:
is_tests_df = is_tests_df.pivot(index="alpha_id", columns="name", values="result").reset_index()
alpha_stats = pd.merge(is_stats_df, expression_df, on="alpha_id")
alpha_stats = pd.merge(alpha_stats, is_tests_df, on="alpha_id")
alpha_stats = alpha_stats.drop(columns=alpha_stats.columns[(alpha_stats == "PENDING").any()])
alpha_stats.columns = alpha_stats.columns.str.replace("(?<=[a-z])(?=[A-Z])", "_", regex=True).str.lower()
if clickable_alpha_id:
return alpha_stats.style.format({"alpha_id": lambda x: make_clickable_alpha_id(str(x))})
return alpha_stats
def concat_pnl(result: list) -> pd.DataFrame:
"""
Combine PnL results from multiple alphas into a single DataFrame.
Args:
result (list): A list of dictionaries containing simulation results with PnL data.
Returns:
pandas.DataFrame: A DataFrame containing combined PnL data for all alphas.
"""
list_of_pnls = [result[x]["pnl"] for x in range(len(result)) if result[x]["pnl"] is not None]
pnls_df = pd.concat(list_of_pnls).reset_index()
return pnls_df
def concat_is_tests(result: list) -> pd.DataFrame:
"""
Combine in-sample test results from multiple alphas into a single DataFrame.
Args:
result (list): A list of dictionaries containing simulation results with in-sample test data.
Returns:
pandas.DataFrame: A DataFrame containing combined in-sample test results for all alphas.
"""
is_tests_list = [result[x]["is_tests"] for x in range(len(result)) if result[x]["is_tests"] is not None]
is_tests_df = pd.concat(is_tests_list, sort=True).reset_index(drop=True)
return is_tests_df
def save_simulation_result(result: dict) -> None:
"""
Save the simulation result to a JSON file in the 'simulation_results' folder.
Args:
result (dict): A dictionary containing the simulation result for an alpha.
"""
alpha_id = result["id"]
region = result["settings"]["region"]
folder_path = "simulation_results/"
file_path = os.path.join(folder_path, f"{alpha_id}_{region}")
os.makedirs(folder_path, exist_ok=True)
with open(file_path, "w", encoding="utf-8") as file:
json.dump(result, file)
def save_pnl(pnl_df: pd.DataFrame, alpha_id: str, region: str) -> None:
"""
Save the PnL data for an alpha to a CSV file in the 'alphas_pnl' folder.
Args:
pnl_df (pandas.DataFrame): The DataFrame containing PnL data.
alpha_id (str): The ID of the alpha.
region (str): The region for which the PnL data was generated.
"""
folder_path = "alphas_pnl/"
file_path = os.path.join(folder_path, f"{alpha_id}_{region}.csv")
os.makedirs(folder_path, exist_ok=True)
pnl_df.to_csv(file_path)
def save_yearly_stats(yearly_stats: pd.DataFrame, alpha_id: str, region: str):
"""
Save the yearly statistics for an alpha to a CSV file in the 'yearly_stats' folder.
Args:
yearly_stats (pandas.DataFrame): The DataFrame containing yearly statistics.
alpha_id (str): The ID of the alpha.
region (str): The region for which the statistics were generated.
"""
folder_path = "yearly_stats/"
file_path = os.path.join(folder_path, f"{alpha_id}_{region}.csv")
os.makedirs(folder_path, exist_ok=True)
yearly_stats.to_csv(file_path, index=False)
def expand_dict_columns(data: pd.DataFrame) -> pd.DataFrame:
"""
Expand dictionary columns in a DataFrame into separate columns.
Args:
data (pandas.DataFrame): The input DataFrame with dictionary columns.
Returns:
pandas.DataFrame: A new DataFrame with expanded columns.
"""
dict_columns = list(filter(lambda x: isinstance(data[x].iloc[0], dict), data.columns))
new_columns = pd.concat(
[data[col].apply(pd.Series).rename(columns=lambda x: f"{col}_{x}") for col in dict_columns],
axis=1,
)
data = pd.concat([data, new_columns], axis=1)
return data
@@ -0,0 +1,112 @@
{
"ts_zscore(divide(avg_pct_change_estimate_12m_earnings_7d, add(count_analysts_lower_curr_qtr_earnings_30d, 0.0001)), 126)": {
"template_explanation": "This template applies a 126-day rolling z-score normalization to the original earnings confidence ratio. By standardizing the signal relative to its own historical distribution, it captures whether current earnings optimism (vs. near-term pessimism) is unusually strong or weak compared to historical norms, enabling mean-reversion or momentum trading around historical equilibrium points.",
"seed_alpha_settings": {
"instrumentType": "EQUITY",
"region": "IND",
"universe": "TOP500",
"delay": 1,
"decay": 6,
"neutralization": "SLOW_AND_FAST",
"truncation": 0.02,
"pasteurization": "ON",
"unitHandling": "VERIFY",
"nanHandling": "ON",
"maxTrade": "OFF",
"maxPosition": "OFF",
"language": "FASTEXPR",
"visualization": false,
"startDate": "2014-01-01",
"endDate": "2023-12-31"
},
"placeholder_candidates": {}
},
"group_zscore(ts_mean(avg_pct_change_estimate_12m_earnings_7d, 66), industry)": {
"template_explanation": "This template calculates the 66-day mean of the 12-month earnings estimate change and then performs industry-relative z-score normalization. It extracts pure earnings momentum by removing sector-wide trends, identifying stocks within each industry that have stronger or weaker earnings revisions than their peer group average.",
"seed_alpha_settings": {
"instrumentType": "EQUITY",
"region": "IND",
"universe": "TOP500",
"delay": 1,
"decay": 6,
"neutralization": "SLOW_AND_FAST",
"truncation": 0.02,
"pasteurization": "ON",
"unitHandling": "VERIFY",
"nanHandling": "ON",
"maxTrade": "OFF",
"maxPosition": "OFF",
"language": "FASTEXPR",
"visualization": false,
"startDate": "2014-01-01",
"endDate": "2023-12-31"
},
"placeholder_candidates": {}
},
"ts_decay_linear(avg_pct_change_estimate_12m_earnings_7d, 20)": {
"template_explanation": "This template applies exponential decay weighting to the 12-month earnings estimate changes over a 20-day window. Recent earnings revisions receive higher weight than older ones, creating a smoothed momentum signal that responds quickly to new information while filtering out short-term noise\u2014a refined version focusing purely on the numerator's forward-looking signal.",
"seed_alpha_settings": {
"instrumentType": "EQUITY",
"region": "IND",
"universe": "TOP500",
"delay": 1,
"decay": 6,
"neutralization": "SLOW_AND_FAST",
"truncation": 0.02,
"pasteurization": "ON",
"unitHandling": "VERIFY",
"nanHandling": "ON",
"maxTrade": "OFF",
"maxPosition": "OFF",
"language": "FASTEXPR",
"visualization": false,
"startDate": "2014-01-01",
"endDate": "2023-12-31"
},
"placeholder_candidates": {}
},
"regression_neut(ts_mean(avg_pct_change_estimate_12m_earnings_7d, 66), log(cap))": {
"template_explanation": "This template removes the market cap factor exposure from the earnings momentum signal using regression neutralization. By stripping out size bias (larger companies may have more analyst coverage and different revision patterns), this alpha isolates the pure earnings-specific component, reducing unintended factor tilts.",
"seed_alpha_settings": {
"instrumentType": "EQUITY",
"region": "IND",
"universe": "TOP500",
"delay": 1,
"decay": 6,
"neutralization": "SLOW_AND_FAST",
"truncation": 0.02,
"pasteurization": "ON",
"unitHandling": "VERIFY",
"nanHandling": "ON",
"maxTrade": "OFF",
"maxPosition": "OFF",
"language": "FASTEXPR",
"visualization": false,
"startDate": "2014-01-01",
"endDate": "2023-12-31"
},
"placeholder_candidates": {}
},
"divide(ts_rank(avg_pct_change_estimate_12m_earnings_7d, 252), add(ts_rank(count_analysts_lower_curr_qtr_earnings_30d, 126), 0.1))": {
"template_explanation": "This template converts both earnings estimate change and analyst cut counts into percentile ranks before taking their ratio. The 252-day rank for earnings captures long-term earnings momentum, while the 126-day rank for analyst cuts captures recent bearishness. Ranking before division creates a more robust, distribution-invariant signal that is comparable across different market regimes.",
"seed_alpha_settings": {
"instrumentType": "EQUITY",
"region": "IND",
"universe": "TOP500",
"delay": 1,
"decay": 6,
"neutralization": "SLOW_AND_FAST",
"truncation": 0.02,
"pasteurization": "ON",
"unitHandling": "VERIFY",
"nanHandling": "ON",
"maxTrade": "OFF",
"maxPosition": "OFF",
"language": "FASTEXPR",
"visualization": false,
"startDate": "2014-01-01",
"endDate": "2023-12-31"
},
"placeholder_candidates": {}
}
}
+654
View File
@@ -0,0 +1,654 @@
{
"group_rank(ts_mean(ts_delta(ts_backfill(<fundamental_field/>, <backfill_days/>), <delta_days/>), <mean_days/>) / ts_std_dev(ts_delta(ts_backfill(<fundamental_field/>, <backfill_days/>), <delta_days/>), <std_days/>), <group_field/>)": {
"template_explanation": "Generalized risk-adjusted fundamental momentum: replaces EPS with any quarterly fundamental, keeps the Sharpe-like score and intra-group ranking to isolate smooth, persistent trends while neutralizing structural differences across groups.",
"seed_alpha_settings": {
"instrumentType": "EQUITY",
"region": "GLB",
"universe": "TOPDIV3000",
"delay": 1,
"decay": 0,
"neutralization": "STATISTICAL",
"truncation": 0.01,
"pasteurization": "ON",
"unitHandling": "VERIFY",
"nanHandling": "ON",
"maxTrade": "OFF",
"language": "FASTEXPR",
"visualization": false,
"startDate": "2013-01-20",
"endDate": "2023-01-20"
},
"placeholder_candidates": {
"<fundamental_field/>": {
"type": "data_field",
"candidates": [
{
"id": "fnd23_icsm_m_vers",
"description": "[Quarterly] Revenue"
},
{
"id": "fnd72_s_pit_or_is_q_net_income",
"description": "Net Income"
},
{
"id": "mdl219_1_ocfmargin",
"description": "Operating cash flow margin calculated as operating cash flow divided by sales."
},
{
"id": "fnd23_tangible_bvps",
"description": "tangible book value per share."
},
{
"id": "ebitda_per_share_trailing_twelve_months",
"description": "EBITDA per share for the trailing twelve months."
}
]
},
"<backfill_days/>": {
"type": "integer_parameter",
"candidates": [
{
"value": 252
},
{
"value": 504
},
{
"value": 756
},
{
"value": 1008
},
{
"value": 1260
}
]
},
"<delta_days/>": {
"type": "integer_parameter",
"candidates": [
{
"value": 42
},
{
"value": 63
},
{
"value": 84
},
{
"value": 126
},
{
"value": 252
}
]
},
"<mean_days/>": {
"type": "integer_parameter",
"candidates": [
{
"value": 20
},
{
"value": 40
},
{
"value": 60
},
{
"value": 80
},
{
"value": 120
}
]
},
"<std_days/>": {
"type": "integer_parameter",
"candidates": [
{
"value": 20
},
{
"value": 40
},
{
"value": 60
},
{
"value": 120
},
{
"value": 252
}
]
},
"<group_field/>": {
"type": "group_data_field",
"candidates": [
{
"name": "industry"
},
{
"name": "sector"
},
{
"name": "subindustry"
}
]
}
}
},
"group_rank(ts_mean(ts_delta(<price_field/>, <short_delta/>), <medium_mean/>) / ts_std_dev(ts_delta(<price_field/>, <short_delta/>), <medium_std/>), <group_field/>)": {
"template_explanation": "Price-momentum version of the seed: uses returns instead of EPS change, still rewards consistent momentum within each sector/industry, producing a cleaner trend signal that is not distorted by industry-wide volatility regimes.",
"seed_alpha_settings": {
"instrumentType": "EQUITY",
"region": "GLB",
"universe": "TOPDIV3000",
"delay": 1,
"decay": 0,
"neutralization": "STATISTICAL",
"truncation": 0.01,
"pasteurization": "ON",
"unitHandling": "VERIFY",
"nanHandling": "ON",
"maxTrade": "OFF",
"language": "FASTEXPR",
"visualization": false,
"startDate": "2013-01-20",
"endDate": "2023-01-20"
},
"placeholder_candidates": {
"<price_field/>": {
"type": "data_field",
"candidates": [
{
"id": "close",
"description": "Daily close price"
},
{
"id": "open",
"description": "Daily open price"
},
{
"id": "vwap",
"description": "Daily volume weighted average price"
},
{
"id": "oth463_adjust_close",
"description": "Adjusted close price"
},
{
"id": "high",
"description": "Daily high price"
}
]
},
"<short_delta/>": {
"type": "integer_parameter",
"candidates": [
{
"value": 5
},
{
"value": 10
},
{
"value": 21
},
{
"value": 42
}
]
},
"<medium_mean/>": {
"type": "integer_parameter",
"candidates": [
{
"value": 10
},
{
"value": 21
},
{
"value": 42
},
{
"value": 63
},
{
"value": 126
}
]
},
"<medium_std/>": {
"type": "integer_parameter",
"candidates": [
{
"value": 20
},
{
"value": 40
},
{
"value": 60
},
{
"value": 80
},
{
"value": 120
}
]
},
"<group_field/>": {
"type": "group_data_field",
"candidates": [
{
"name": "industry"
},
{
"name": "subindustry"
},
{
"name": "sector"
}
]
}
}
},
"group_rank((<fundamental_field/> - ts_delay(<fundamental_field/>, <lag_quarters/>)) / ts_std_dev(<fundamental_field/> - ts_delay(<fundamental_field/>, <lag_quarters/>), <std_quarters/>), <group_field/>)": {
"template_explanation": "SUE-style surprise on any quarterly metric: standardizes the YoY (or QoQ) jump by its own historical volatility, then ranks within peer groups to highlight genuine outliers while canceling systematic industry drift.",
"seed_alpha_settings": {
"instrumentType": "EQUITY",
"region": "GLB",
"universe": "TOPDIV3000",
"delay": 1,
"decay": 0,
"neutralization": "STATISTICAL",
"truncation": 0.01,
"pasteurization": "ON",
"unitHandling": "VERIFY",
"nanHandling": "ON",
"maxTrade": "OFF",
"language": "FASTEXPR",
"visualization": false,
"startDate": "2013-01-20",
"endDate": "2023-01-20"
},
"placeholder_candidates": {
"<fundamental_field/>": {
"type": "data_field",
"candidates": [
{
"id": "fnd72_s_pit_or_is_q_net_income",
"description": "Net Income"
},
{
"id": "star_rev_surprise_prediction_fy2",
"description": "Revenue predicted surprise pct - forward 2 years"
},
{
"id": "star_eps_smart_estimate_12m",
"description": "SmartEstimate F12M EPS"
},
{
"id": "ebitda_per_share_trailing_twelve_months",
"description": "EBITDA per share for the trailing twelve months."
},
{
"id": "mdl219_1_ocfmargin",
"description": "Operating cash flow margin calculated as operating cash flow divided by sales."
}
]
},
"<lag_quarters/>": {
"type": "integer_parameter",
"candidates": [
{
"value": 1
},
{
"value": 4
},
{
"value": 8
}
]
},
"<std_quarters/>": {
"type": "integer_parameter",
"candidates": [
{
"value": 8
},
{
"value": 12
},
{
"value": 16
},
{
"value": 20
}
]
},
"<group_field/>": {
"type": "group_data_field",
"candidates": [
{
"name": "industry"
},
{
"name": "sector"
},
{
"name": "subindustry"
}
]
}
}
},
"group_rank(ts_mean(ts_delta(ts_backfill(<alternative_field/>, <backfill_days/>), <delta_days/>), <mean_days/>) / ts_std_dev(ts_delta(ts_backfill(<alternative_field/>, <backfill_days/>), <delta_days/>), <std_days/>), <group_field/>)": {
"template_explanation": "Alternative-data momentum clone: applies the same risk-adjusted change logic to non-traditional data (web-traffic, sentiment, etc.), yielding a smooth, comparable signal that is industry-neutral and robust to data gaps.",
"seed_alpha_settings": {
"instrumentType": "EQUITY",
"region": "GLB",
"universe": "TOPDIV3000",
"delay": 1,
"decay": 0,
"neutralization": "STATISTICAL",
"truncation": 0.01,
"pasteurization": "ON",
"unitHandling": "VERIFY",
"nanHandling": "ON",
"maxTrade": "OFF",
"language": "FASTEXPR",
"visualization": false,
"startDate": "2013-01-20",
"endDate": "2023-01-20"
},
"placeholder_candidates": {
"<alternative_field/>": {
"type": "data_field",
"candidates": [
{
"id": "fnd23_intfvalld1_qkim",
"description": "Traffic acquisition costs (TAC) represent the cost for a company to acquire traffic to their site."
},
{
"id": "snt22pos_min_377",
"description": "minimum positive sentiment score."
},
{
"id": "mdl106_tre",
"description": "earnings revenue trend"
},
{
"id": "fnd23_intfvalld1_liim",
"description": "Click Rate, Total - %. It shows the frequency an advertisement downloaded with a webpage is clicked on. This is obtained using the number of clicks on an ad on a webpage, divided by the total number of times that the ad was downloaded with a page."
},
{
"id": "headline_sentiment_value",
"description": "Aggregate sentiment value computed for the news headline."
}
]
},
"<backfill_days/>": {
"type": "integer_parameter",
"candidates": [
{
"value": 5
},
{
"value": 14
},
{
"value": 30
},
{
"value": 60
}
]
},
"<delta_days/>": {
"type": "integer_parameter",
"candidates": [
{
"value": 5
},
{
"value": 10
},
{
"value": 21
},
{
"value": 42
},
{
"value": 63
}
]
},
"<mean_days/>": {
"type": "integer_parameter",
"candidates": [
{
"value": 5
},
{
"value": 10
},
{
"value": 21
},
{
"value": 42
},
{
"value": 63
}
]
},
"<std_days/>": {
"type": "integer_parameter",
"candidates": [
{
"value": 5
},
{
"value": 10
},
{
"value": 20
},
{
"value": 40
},
{
"value": 60
}
]
},
"<group_field/>": {
"type": "group_data_field",
"candidates": [
{
"name": "industry"
},
{
"name": "sector"
},
{
"name": "subindustry"
}
]
}
}
},
"group_rank(ts_corr(ts_delta(ts_backfill(<fundamental_field/>, <bf/>), <d1/>), ts_delta(<price_field/>, <d2/>), <corr_win/>), <group_field/>)": {
"template_explanation": "Earnings-to-price alignment factor: measures how tightly fundamental momentum co-moves with price momentum; high correlation within group flags firms where the market promptly rewards improving fundamentals, suggesting continued follow-through.",
"seed_alpha_settings": {
"instrumentType": "EQUITY",
"region": "GLB",
"universe": "TOPDIV3000",
"delay": 1,
"decay": 0,
"neutralization": "STATISTICAL",
"truncation": 0.01,
"pasteurization": "ON",
"unitHandling": "VERIFY",
"nanHandling": "ON",
"maxTrade": "OFF",
"language": "FASTEXPR",
"visualization": false,
"startDate": "2013-01-20",
"endDate": "2023-01-20"
},
"placeholder_candidates": {
"<fundamental_field/>": {
"type": "data_field",
"candidates": [
{
"id": "ern3_all_delay_1_next_reptime",
"description": "next report time"
},
{
"id": "star_rev_surprise_prediction_fy2",
"description": "Revenue predicted surprise pct - forward 2 years"
},
{
"id": "fnd72_s_pit_or_is_q_net_income",
"description": "Net Income"
},
{
"id": "ebitda_per_share_trailing_twelve_months",
"description": "EBITDA per share for the trailing twelve months."
},
{
"id": "fnd7_ointfund_qfcnif",
"description": "Quarterly Fundamental Item: Financing Activities -> Net Cash Flow (Statement of Cash Flows)"
}
]
},
"<bf/>": {
"type": "integer_parameter",
"candidates": [
{
"value": 1
},
{
"value": 5
},
{
"value": 10
},
{
"value": 21
}
]
},
"<d1/>": {
"type": "integer_parameter",
"candidates": [
{
"value": 5
},
{
"value": 10
},
{
"value": 21
},
{
"value": 63
},
{
"value": 126
}
]
},
"<price_field/>": {
"type": "data_field",
"candidates": [
{
"id": "close",
"description": "Daily close price"
},
{
"id": "pv37_volume_13",
"description": "Trading volume"
},
{
"id": "srp_average_score",
"description": "Average score"
},
{
"id": "pv37_open_13",
"description": "Open price"
},
{
"id": "open",
"description": "Daily open price"
}
]
},
"<d2/>": {
"type": "integer_parameter",
"candidates": [
{
"value": 5
},
{
"value": 10
},
{
"value": 21
},
{
"value": 42
},
{
"value": 63
}
]
},
"<corr_win/>": {
"type": "integer_parameter",
"candidates": [
{
"value": 20
},
{
"value": 40
},
{
"value": 60
},
{
"value": 120
},
{
"value": 252
}
]
},
"<group_field/>": {
"type": "group_data_field",
"candidates": [
{
"name": "industry"
},
{
"name": "subindustry"
},
{
"name": "sector"
}
]
}
}
}
}
@@ -0,0 +1 @@
[]
@@ -0,0 +1,7 @@
[
"divide(ts_rank(avg_pct_change_estimate_12m_earnings_7d, 252), add(ts_rank(count_analysts_lower_curr_qtr_earnings_30d, 126), 0.1))",
"regression_neut(ts_mean(avg_pct_change_estimate_12m_earnings_7d, 66), log(cap))",
"ts_decay_linear(avg_pct_change_estimate_12m_earnings_7d, 20)",
"ts_zscore(divide(avg_pct_change_estimate_12m_earnings_7d, add(count_analysts_lower_curr_qtr_earnings_30d, 0.0001)), 126)",
"group_zscore(ts_mean(avg_pct_change_estimate_12m_earnings_7d, 66), industry)"
]
+60
View File
@@ -0,0 +1,60 @@
# parsetab.py
# This file is automatically generated. Do not edit.
# pylint: disable=W,C,R
_tabversion = '3.10'
_lr_method = 'LALR'
_lr_signature = 'ASSIGN BOOLEAN CATEGORY COMMA DIVIDE EQUAL FIELD FUNCTION GREATER GREATEREQUAL IDENTIFIER LESS LESSEQUAL LPAREN MINUS NOTEQUAL NUMBER PLUS RPAREN STRING TIMESexpression : comparison\n | expression EQUAL comparison\n | expression NOTEQUAL comparison\n | expression GREATER comparison\n | expression LESS comparison\n | expression GREATEREQUAL comparison\n | expression LESSEQUAL comparisoncomparison : term\n | comparison PLUS term\n | comparison MINUS termterm : factor\n | term TIMES factor\n | term DIVIDE factorfactor : NUMBER\n | STRING\n | FIELD\n | CATEGORY\n | IDENTIFIER\n | BOOLEAN\n | MINUS factor\n | LPAREN expression RPAREN\n | function_callfunction_call : FUNCTION LPAREN args RPARENargs : arg_list\n | emptyarg_list : arg\n | arg_list COMMA argarg : expression\n | IDENTIFIER ASSIGN expressionempty :'
_lr_action_items = {'NUMBER':([0,4,12,15,16,17,18,19,20,21,22,23,24,27,46,47,],[6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,]),'STRING':([0,4,12,15,16,17,18,19,20,21,22,23,24,27,46,47,],[7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,]),'FIELD':([0,4,12,15,16,17,18,19,20,21,22,23,24,27,46,47,],[8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,]),'CATEGORY':([0,4,12,15,16,17,18,19,20,21,22,23,24,27,46,47,],[9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,9,]),'IDENTIFIER':([0,4,12,15,16,17,18,19,20,21,22,23,24,27,46,47,],[10,10,10,10,10,10,10,10,10,10,10,10,10,44,44,10,]),'BOOLEAN':([0,4,12,15,16,17,18,19,20,21,22,23,24,27,46,47,],[11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,11,]),'MINUS':([0,2,3,4,5,6,7,8,9,10,11,12,13,15,16,17,18,19,20,21,22,23,24,25,27,28,29,30,31,32,33,34,35,36,37,38,44,45,46,47,],[4,22,-8,4,-11,-14,-15,-16,-17,-18,-19,4,-22,4,4,4,4,4,4,4,4,4,4,-20,4,22,22,22,22,22,22,-9,-10,-12,-13,-21,-18,-23,4,4,]),'LPAREN':([0,4,12,14,15,16,17,18,19,20,21,22,23,24,27,46,47,],[12,12,12,27,12,12,12,12,12,12,12,12,12,12,12,12,12,]),'FUNCTION':([0,4,12,15,16,17,18,19,20,21,22,23,24,27,46,47,],[14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,14,]),'$end':([1,2,3,5,6,7,8,9,10,11,13,25,28,29,30,31,32,33,34,35,36,37,38,45,],[0,-1,-8,-11,-14,-15,-16,-17,-18,-19,-22,-20,-2,-3,-4,-5,-6,-7,-9,-10,-12,-13,-21,-23,]),'EQUAL':([1,2,3,5,6,7,8,9,10,11,13,25,26,28,29,30,31,32,33,34,35,36,37,38,43,44,45,49,],[15,-1,-8,-11,-14,-15,-16,-17,-18,-19,-22,-20,15,-2,-3,-4,-5,-6,-7,-9,-10,-12,-13,-21,15,-18,-23,15,]),'NOTEQUAL':([1,2,3,5,6,7,8,9,10,11,13,25,26,28,29,30,31,32,33,34,35,36,37,38,43,44,45,49,],[16,-1,-8,-11,-14,-15,-16,-17,-18,-19,-22,-20,16,-2,-3,-4,-5,-6,-7,-9,-10,-12,-13,-21,16,-18,-23,16,]),'GREATER':([1,2,3,5,6,7,8,9,10,11,13,25,26,28,29,30,31,32,33,34,35,36,37,38,43,44,45,49,],[17,-1,-8,-11,-14,-15,-16,-17,-18,-19,-22,-20,17,-2,-3,-4,-5,-6,-7,-9,-10,-12,-13,-21,17,-18,-23,17,]),'LESS':([1,2,3,5,6,7,8,9,10,11,13,25,26,28,29,30,31,32,33,34,35,36,37,38,43,44,45,49,],[18,-1,-8,-11,-14,-15,-16,-17,-18,-19,-22,-20,18,-2,-3,-4,-5,-6,-7,-9,-10,-12,-13,-21,18,-18,-23,18,]),'GREATEREQUAL':([1,2,3,5,6,7,8,9,10,11,13,25,26,28,29,30,31,32,33,34,35,36,37,38,43,44,45,49,],[19,-1,-8,-11,-14,-15,-16,-17,-18,-19,-22,-20,19,-2,-3,-4,-5,-6,-7,-9,-10,-12,-13,-21,19,-18,-23,19,]),'LESSEQUAL':([1,2,3,5,6,7,8,9,10,11,13,25,26,28,29,30,31,32,33,34,35,36,37,38,43,44,45,49,],[20,-1,-8,-11,-14,-15,-16,-17,-18,-19,-22,-20,20,-2,-3,-4,-5,-6,-7,-9,-10,-12,-13,-21,20,-18,-23,20,]),'RPAREN':([2,3,5,6,7,8,9,10,11,13,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,48,49,],[-1,-8,-11,-14,-15,-16,-17,-18,-19,-22,-20,38,-30,-2,-3,-4,-5,-6,-7,-9,-10,-12,-13,-21,45,-24,-25,-26,-28,-18,-23,-27,-29,]),'COMMA':([2,3,5,6,7,8,9,10,11,13,25,28,29,30,31,32,33,34,35,36,37,38,40,42,43,44,45,48,49,],[-1,-8,-11,-14,-15,-16,-17,-18,-19,-22,-20,-2,-3,-4,-5,-6,-7,-9,-10,-12,-13,-21,46,-26,-28,-18,-23,-27,-29,]),'PLUS':([2,3,5,6,7,8,9,10,11,13,25,28,29,30,31,32,33,34,35,36,37,38,44,45,],[21,-8,-11,-14,-15,-16,-17,-18,-19,-22,-20,21,21,21,21,21,21,-9,-10,-12,-13,-21,-18,-23,]),'TIMES':([3,5,6,7,8,9,10,11,13,25,34,35,36,37,38,44,45,],[23,-11,-14,-15,-16,-17,-18,-19,-22,-20,23,23,-12,-13,-21,-18,-23,]),'DIVIDE':([3,5,6,7,8,9,10,11,13,25,34,35,36,37,38,44,45,],[24,-11,-14,-15,-16,-17,-18,-19,-22,-20,24,24,-12,-13,-21,-18,-23,]),'ASSIGN':([44,],[47,]),}
_lr_action = {}
for _k, _v in _lr_action_items.items():
for _x,_y in zip(_v[0],_v[1]):
if not _x in _lr_action: _lr_action[_x] = {}
_lr_action[_x][_k] = _y
del _lr_action_items
_lr_goto_items = {'expression':([0,12,27,46,47,],[1,26,43,43,49,]),'comparison':([0,12,15,16,17,18,19,20,27,46,47,],[2,2,28,29,30,31,32,33,2,2,2,]),'term':([0,12,15,16,17,18,19,20,21,22,27,46,47,],[3,3,3,3,3,3,3,3,34,35,3,3,3,]),'factor':([0,4,12,15,16,17,18,19,20,21,22,23,24,27,46,47,],[5,25,5,5,5,5,5,5,5,5,5,36,37,5,5,5,]),'function_call':([0,4,12,15,16,17,18,19,20,21,22,23,24,27,46,47,],[13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,13,]),'args':([27,],[39,]),'arg_list':([27,],[40,]),'empty':([27,],[41,]),'arg':([27,46,],[42,48,]),}
_lr_goto = {}
for _k, _v in _lr_goto_items.items():
for _x, _y in zip(_v[0], _v[1]):
if not _x in _lr_goto: _lr_goto[_x] = {}
_lr_goto[_x][_k] = _y
del _lr_goto_items
_lr_productions = [
("S' -> expression","S'",1,None,None,None),
('expression -> comparison','expression',1,'p_expression','validator.py',405),
('expression -> expression EQUAL comparison','expression',3,'p_expression','validator.py',406),
('expression -> expression NOTEQUAL comparison','expression',3,'p_expression','validator.py',407),
('expression -> expression GREATER comparison','expression',3,'p_expression','validator.py',408),
('expression -> expression LESS comparison','expression',3,'p_expression','validator.py',409),
('expression -> expression GREATEREQUAL comparison','expression',3,'p_expression','validator.py',410),
('expression -> expression LESSEQUAL comparison','expression',3,'p_expression','validator.py',411),
('comparison -> term','comparison',1,'p_comparison','validator.py',418),
('comparison -> comparison PLUS term','comparison',3,'p_comparison','validator.py',419),
('comparison -> comparison MINUS term','comparison',3,'p_comparison','validator.py',420),
('term -> factor','term',1,'p_term','validator.py',427),
('term -> term TIMES factor','term',3,'p_term','validator.py',428),
('term -> term DIVIDE factor','term',3,'p_term','validator.py',429),
('factor -> NUMBER','factor',1,'p_factor','validator.py',436),
('factor -> STRING','factor',1,'p_factor','validator.py',437),
('factor -> FIELD','factor',1,'p_factor','validator.py',438),
('factor -> CATEGORY','factor',1,'p_factor','validator.py',439),
('factor -> IDENTIFIER','factor',1,'p_factor','validator.py',440),
('factor -> BOOLEAN','factor',1,'p_factor','validator.py',441),
('factor -> MINUS factor','factor',2,'p_factor','validator.py',442),
('factor -> LPAREN expression RPAREN','factor',3,'p_factor','validator.py',443),
('factor -> function_call','factor',1,'p_factor','validator.py',444),
('function_call -> FUNCTION LPAREN args RPAREN','function_call',4,'p_function_call','validator.py',472),
('args -> arg_list','args',1,'p_args','validator.py',476),
('args -> empty','args',1,'p_args','validator.py',477),
('arg_list -> arg','arg_list',1,'p_arg_list','validator.py',484),
('arg_list -> arg_list COMMA arg','arg_list',3,'p_arg_list','validator.py',485),
('arg -> expression','arg',1,'p_arg','validator.py',492),
('arg -> IDENTIFIER ASSIGN expression','arg',3,'p_arg','validator.py',493),
('empty -> <empty>','empty',0,'p_empty','validator.py',500),
]
File diff suppressed because it is too large Load Diff
+1261
View File
File diff suppressed because it is too large Load Diff