You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
223 lines
7.7 KiB
223 lines
7.7 KiB
import time
|
|
import httpx
|
|
import datetime
|
|
|
|
|
|
def login():
|
|
username = "jack0210_@hotmail.com"
|
|
password = "!QAZ2wsx+0913"
|
|
|
|
timeout = httpx.Timeout(60.0, connect=10.0)
|
|
limits = httpx.Limits(max_keepalive_connections=20, max_connections=100)
|
|
transport = httpx.HTTPTransport(retries=3)
|
|
|
|
s = httpx.Client(
|
|
auth=(username, password),
|
|
timeout=timeout,
|
|
limits=limits,
|
|
transport=transport
|
|
)
|
|
response = s.post('https://api.worldquantbrain.com/authentication')
|
|
print(response.content)
|
|
return s
|
|
|
|
|
|
def wait_get(s, url: str, max_retries: int = 10):
|
|
retries = 0
|
|
while retries < max_retries:
|
|
while True:
|
|
simulation_progress = s.get(url)
|
|
if simulation_progress.headers.get("Retry-After", 0) == 0:
|
|
break
|
|
time.sleep(float(simulation_progress.headers["Retry-After"]))
|
|
if simulation_progress.status_code < 400:
|
|
break
|
|
else:
|
|
time.sleep(2 ** retries)
|
|
retries += 1
|
|
return simulation_progress
|
|
|
|
|
|
def get_alphas(start_date, end_date, sharpe_th, fitness_th, region, alpha_num, usage):
|
|
s = login()
|
|
output = []
|
|
count = 0
|
|
for i in range(0, alpha_num, 100):
|
|
print(i)
|
|
url_e = "https://api.worldquantbrain.com/users/self/alphas?limit=100&offset=%d" % (i) \
|
|
+ "&status=UNSUBMITTED%1FIS_FAIL&dateCreated%3E=2025-" + start_date \
|
|
+ "T00:00:00-04:00&dateCreated%3C2025-" + end_date \
|
|
+ "T00:00:00-04:00&is.fitness%3E" + str(fitness_th) + "&is.sharpe%3E" \
|
|
+ str(sharpe_th) + "&settings.region=" + region + "&order=-is.sharpe&hidden=false&type!=SUPER"
|
|
url_c = "https://api.worldquantbrain.com/users/self/alphas?limit=100&offset=%d" % (i) \
|
|
+ "&status=UNSUBMITTED%1FIS_FAIL&dateCreated%3E=2025-" + start_date \
|
|
+ "T00:00:00-04:00&dateCreated%3C2025-" + end_date \
|
|
+ "T00:00:00-04:00&is.fitness%3C-" + str(fitness_th) + "&is.sharpe%3C-" \
|
|
+ str(sharpe_th) + "&settings.region=" + region + "&order=is.sharpe&hidden=false&type!=SUPER"
|
|
urls = [url_e]
|
|
if usage != "submit":
|
|
urls.append(url_c)
|
|
for url in urls:
|
|
response = s.get(url)
|
|
try:
|
|
alpha_list = response.json()["results"]
|
|
for j in range(len(alpha_list)):
|
|
alpha_id = alpha_list[j]["id"]
|
|
name = alpha_list[j]["name"]
|
|
dateCreated = alpha_list[j]["dateCreated"]
|
|
sharpe = alpha_list[j]["is"]["sharpe"]
|
|
fitness = alpha_list[j]["is"]["fitness"]
|
|
turnover = alpha_list[j]["is"]["turnover"]
|
|
margin = alpha_list[j]["is"]["margin"]
|
|
longCount = alpha_list[j]["is"]["longCount"]
|
|
shortCount = alpha_list[j]["is"]["shortCount"]
|
|
decay = alpha_list[j]["settings"]["decay"]
|
|
exp = alpha_list[j]['regular']['code']
|
|
count += 1
|
|
if (longCount + shortCount) > 100:
|
|
if sharpe < -sharpe_th:
|
|
exp = "-%s" % exp
|
|
rec = [alpha_id, exp, sharpe, turnover, fitness, margin, dateCreated, decay]
|
|
print(rec)
|
|
if turnover > 0.7:
|
|
rec.append(decay * 4)
|
|
elif turnover > 0.6:
|
|
rec.append(decay * 3 + 3)
|
|
elif turnover > 0.5:
|
|
rec.append(decay * 3)
|
|
elif turnover > 0.4:
|
|
rec.append(decay * 2)
|
|
elif turnover > 0.35:
|
|
rec.append(decay + 4)
|
|
elif turnover > 0.3:
|
|
rec.append(decay + 2)
|
|
output.append(rec)
|
|
except:
|
|
print("%d finished re-login" % i)
|
|
s = login()
|
|
|
|
print("count: %d" % count)
|
|
return output, s
|
|
|
|
|
|
def check_consecutive_non_zero_values(alpha_id, data, required_streak=200):
|
|
if not data or len(data) < required_streak:
|
|
return True
|
|
|
|
def check_column(column_data):
|
|
if len(column_data) < required_streak:
|
|
return True
|
|
|
|
current_streak_count = 0
|
|
current_streak_value = None
|
|
|
|
for value in column_data:
|
|
if value != 0:
|
|
if value == current_streak_value:
|
|
current_streak_count += 1
|
|
else:
|
|
current_streak_value = value
|
|
current_streak_count = 1
|
|
else:
|
|
current_streak_value = None
|
|
current_streak_count = 0
|
|
|
|
if current_streak_count >= required_streak:
|
|
return False
|
|
return True
|
|
|
|
column1_values = []
|
|
column2_values = []
|
|
for row in data:
|
|
if len(row) >= 3:
|
|
column1_values.append(row[1])
|
|
column2_values.append(row[2])
|
|
|
|
if column1_values and column2_values:
|
|
is_col1_all_zeros = all(v == 0 for v in column1_values)
|
|
is_col2_all_zeros = all(v == 0 for v in column2_values)
|
|
if is_col1_all_zeros or is_col2_all_zeros:
|
|
print(alpha_id, "不合法")
|
|
return False
|
|
|
|
if not check_column(column1_values):
|
|
print(alpha_id, "不合法")
|
|
return False
|
|
|
|
if not check_column(column2_values):
|
|
print(alpha_id, "不合法")
|
|
return False
|
|
|
|
return True
|
|
|
|
|
|
def get_alpha_pnl_legal(s, alpha_id: str) -> bool:
|
|
not_legal_id = []
|
|
pnl = wait_get(s, "https://api.worldquantbrain.com/alphas/" + alpha_id + "/recordsets/pnl").json()
|
|
records = pnl["records"]
|
|
|
|
if not records:
|
|
return False
|
|
|
|
date_list = []
|
|
for record in records:
|
|
try:
|
|
date_obj = datetime.datetime.strptime(record[0], '%Y-%m-%d').date()
|
|
date_list.append(date_obj)
|
|
except Exception:
|
|
return False
|
|
|
|
min_date = min(date_list)
|
|
max_date = max(date_list)
|
|
total_days = (max_date - min_date).days
|
|
if total_days < 2920:
|
|
return False
|
|
|
|
zero_streak_threshold = 5 * 252
|
|
col1_zeros = [record[1] == 0 for record in records]
|
|
|
|
def max_consecutive_zeros(arr):
|
|
max_streak = current_streak = 0
|
|
for val in arr:
|
|
current_streak = current_streak + 1 if val else 0
|
|
max_streak = max(max_streak, current_streak)
|
|
return max_streak
|
|
|
|
col1_max_zero_streak = max_consecutive_zeros(col1_zeros)
|
|
|
|
if col1_max_zero_streak >= zero_streak_threshold:
|
|
print(f"{alpha_id} 不合法:存在连续{zero_streak_threshold // 252}年零值")
|
|
not_legal_id.append(str(alpha_id))
|
|
return False
|
|
|
|
if not check_consecutive_non_zero_values(alpha_id, records):
|
|
return False
|
|
|
|
return True
|
|
|
|
|
|
def mute(s, alpha_id):
|
|
url = "https://api.worldquantbrain.com/alphas/" + alpha_id
|
|
data = {
|
|
"hidden": True
|
|
}
|
|
response = s.patch(url, json=data)
|
|
|
|
|
|
def main():
|
|
fo_tracker, s = get_alphas('12-01', '12-31', 1, 0.5, 'USA', 1000, 'submit')
|
|
f_num = len(fo_tracker)
|
|
print(f_num, "个alpha 进行pnl合法检测,请耐心等待")
|
|
count = 0
|
|
print(len(fo_tracker))
|
|
for i in fo_tracker[::-1][0:]:
|
|
if count % 25 == 0:
|
|
print('===========', count, '===========')
|
|
count += 1
|
|
if get_alpha_pnl_legal(s, i[0]) == False:
|
|
print(i[0], '已经隐藏')
|
|
mute(s, i[0])
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|
|
|