From 481be44cf5befc0d00f168a7d1f2ae72b59e1473 Mon Sep 17 00:00:00 2001 From: aaron <> Date: Tue, 10 Jun 2025 15:52:20 +0800 Subject: [PATCH] update --- .../__pycache__/crypto_agent.cpython-313.pyc | Bin 20204 -> 20877 bytes cryptoai/agents/crypto_agent.py | 2 +- cryptoai/tasks/token_selector.py | 172 ++++++++++++++++++ docker-compose.yml | 2 +- requirements.txt | 1 + test.py | 19 +- 6 files changed, 177 insertions(+), 19 deletions(-) create mode 100644 cryptoai/tasks/token_selector.py diff --git a/cryptoai/agents/__pycache__/crypto_agent.cpython-313.pyc b/cryptoai/agents/__pycache__/crypto_agent.cpython-313.pyc index 8080a570fe0e232e5a1d3edcb25db349ef81ff8d..1eb923d17c743274f836b62de5f0c4bcce6e8f3a 100644 GIT binary patch delta 3208 zcmaJ@eNa@_6~A|P-!8kb%d#J^EU+wJ3k%AJ2nZ?>1QhvjaNTN#QSx9PxMA7d+_xxL zr`YKqv6C7NijnCTdFGi}o}Q*DAFP3$bKmhIC_(~hQ^X{T${*6EkM=K%%s zN8jxJ?s?~&d+s^+o_o&w^I3fK2iWjHuh${=T>RsfeJxv07;N~hi^bo>l^*0t?kLz+ zND7^Z(J388+g!xuL^hO8ogX$)A_v>FWxP}?jEHjwu)vR=4We^ia-8xYrThlaY7AR)75bQI~ARa^;mAPmT z&#$-i?oOvCOdsH8`m}jt$-NmC6Fb}{Hb_bSU_>DM`GBMqBRq-pi4h`k0sn|ULNA%U zictssmD#@K`Jdi9^-6``BjLz6Sqrqbb!GjrxL%Vsmn;`V}gdS*h4EDZ_7Sqw*7 z9;P6@DQ0m`7EY$eOqJJDs^Y2UV+W5Nylu3`Z0$3y8C$G}kEQotHx9%zvR*!P;?P`1 z{cJ{kJU1&Zo|8A1Q!$%U5qA{F?K#Y@4eZ)X$5n|^`gHoPiN_CDBV*k?&~Sr6AGQ)_2~+$|HtTQ)nn$ZCFcQB=v}wKy_zXuYF8|M<8@=>t&Gf< z51l+jzcyzq`n9p>p9zjB{iio!Wh?(fY-hW6Mb)frS%uzTrE9BEzF(W#R;ip;yIQLh z(^a~*)!g*@{I(MAY7S=fRfmd6ujXT>d9{QC&T1uaDmlg>yO^~BCB;u!qOtTn7pjr>Catft%hYqAXlzsPOpJJ zS8Pr;G#R>^Jb6Jj(qqLvrdDQC;sydCQMmVnJ!BjGqWD_+e#RzaAkz?GAVhqkTTPni zjgn#9M4Q|VYPjsAfPUTmTdTZ#klbVyKo3Aa4V0E74+9wnsG+ZxR!wv>Qquax&|rv+ z@DXAHQ5rBU@-1ZTMea6zL~b{7xhFfA+?~2~BH$4;BT-6PynW;uFa$?IV6P>0n1omX zU?7A3$u6 zept3w;YihQ$G7dS@01_c+_G0pX?|m0cU%*<<<8mG&f3<}#`1JrL%&jfGF#o@M8B*w zF#O1=>*SOlm8Nwf<;RF)G=0*Tjt|kSihS&*jTJ5S-D^0u#%>dwbXOTd$;gSkxRCWc z`jZMztH{_S!oaO0>w%WH{sJ&m^BZ&yxN;%Zi~itHKv>vHQN;uh4GU$UvR=IwvryXU zYn8ROxT9>=QGH~~3)}B&QAR-`1sOAr7>F?A*;_nNct+fi=wIF=Jyj+b0!n&b+=F90B1@*V?8EsXiah$uTJnS`-$ zh&9D!7UeUPtV6;IE^C`Sn9^pN}HUta2RqZ|BGgZwzd}H zlhJ2e|EAm{AJ{eUX$E{s>k!8KLp<@dL$fBM;fTDFq>T`MKbf{lLK;c%?yER&lPhz(PsJX~)6pz})SBj6+s z((F#Jvj=k--}598jFUU33Z}%VlJk2X%I}FmMJhefY2#A4jQfT3Lg(IGc_~=MT|zFi zK~jq2A}e5g(8r6!L(96>C;Pz(_HDruj6TW&Amiaki1(L|gnU9kEdO%hlxwPS zG~#D6Uq8E7@^|}uy_G{+8K#u9ff*VN2#q9(6$bW0;x`y1lo;ciNP83MZX)wdWcod- czJciB?%s?~P}3*K{dd&?H7@=F0m{4fU-}_Zd;kCd delta 2543 zcmZWqeQaA-6@S-$cKrR3_%lvo#|cSZKH4VEcatXB^0AUMp>^B@mBe%6*ThX?oBN!u znS?t2VHscTI1?XImqm*h8=z6J03jH(FlmEQVT+1bPat*ED4K*I?FvW(0r$LgI2~6{ zzjy9A=bn4+Ip?1Hg&p$e=ZWP#v)RD0@lV~*^7zQJ77w}d-TG&U$HN7=u(6yAn>th| z=QvukLksHCoKsKafl9XPiF-a77S`>N}4Y+G?kaEx( z>$DZfsDw6S7pcgeGv-OPA2|UAa*4FDwvbwtXf>M&YMGbB)w9$ApD<^LH=8$aso>kZ zUNxpthb4ENY76Z&JI*c&FK-R1#))E=`tuvvv&@LEoRgzYi zbNMdfnPrW*md%8F<@mRXicm}+2u&^}z|JS%1vm!n{Dw`o7l7*ZRIx<@bG*K&GG z&Q`a5etS80=vdA&a7#B>u$Jvw{duc@*V>V{b`;9I1*dn{S)X^-7hL|m63*7S$MH79 zCV$_cEdR)MeEW3H(tJzTa@%OV)O)G-9g{uh7`b-#+HCH`T&{HfmMK~&bAP4p*}mPf zj(k~1!ChJKR_=PeO?huqp}eNx^6u$52eYejST=|EY|!YLDS3}M%F%H4wD&wA$Khsq zleP;v?eOpNiqeye6f_6o6NYAAi1fkZz9zB>pZBe*=uGx~pPG~^F^n>O3CleYpnYJi z>>*olyt0bSWS1+;wfj0t59vHtbAo&e-mYmRGhnXu5)0JVK2`EXj*D=o^zfF~k^OmX zFAwQXm+Mp=Tlt}JN`Rq~GUyiqYGcF*j|N%0+%hf`Q8KgXgL40%=%Mk@VQrrAB}X=TXkK;L zY@Q;wJryrlzh>R_4CFlnyPoO1XSz@xEcmJm!MfdGdp_7+s130~^hOBWJMtx;X57#H z>ad034ZmT6SKkoq;{)m&1DXjQUTAfbufh*ogQN@O*5S@GYPOj&!s>|n;r21xreTuV z(t3s`dN|I=1-J-dEro~fw(#s4W78yqbqj+(Zhq#@*5yC_818Ic=?$<(!xnHakYl&=bHj(u+Gu90)s>{&RQd(*=1%v@-YXN`QTE3A((W21tKE@a>Da*)RqFLbyw z775)#K&R-d2onrsRZ5b1Y(g@BE|o~qW@PHtVk=@iK_&V$DlWq5o{+NxC1y!X##t57 zm3ZojB<+T+9>G@ZdCDmPc6++n#kTc!k&f(Rz3hG3$^PN!1>Ss_nP3qLq0uX_Fc|D8 z#^&qD{58T$2;V?>lfnNrM|vH8G}ujIaBpylpJ5uX-RjCpL)X+t%GpddW>PC+GOASG zH2og3oN-Z1OQN_EJs^wH?`IcBHpqw)8w>{h3Bqd#KSjV;(4R4owc>?@l#vwAgh~7n!c0qrEUZHs*PSO(YCHW*3Lj+Ue`CGgeDJoqcoc@9G*QLBC`= z^mPWZeO%mFNX2OUcrqhWx}MI^7vZh(imGCS(JFn1!NJ1uO$cNMMkao-+ao?>2)6~3Q*$OuhYL)!UYH34att^&|$0Rxh&rBUPE}|29gxBCVQ#S?0 pA^NbVvaW9}6<=Q!k5Lu7!|davPl4)W#{Lg}Sxf5gafr&v{tJhfj$Qx& diff --git a/cryptoai/agents/crypto_agent.py b/cryptoai/agents/crypto_agent.py index d963e23..e5f8476 100644 --- a/cryptoai/agents/crypto_agent.py +++ b/cryptoai/agents/crypto_agent.py @@ -18,7 +18,7 @@ from models.data_processor import DataProcessor from utils.config_loader import ConfigLoader from utils.dingtalk_bot import DingTalkBot from utils.discord_bot import DiscordBot -from models.analysis_result import AnalysisResultManager +from cryptoai.models.analysis_result import AnalysisResultManager from utils.db_manager import SessionLocal class CryptoAgent: diff --git a/cryptoai/tasks/token_selector.py b/cryptoai/tasks/token_selector.py new file mode 100644 index 0000000..344c6b0 --- /dev/null +++ b/cryptoai/tasks/token_selector.py @@ -0,0 +1,172 @@ +from binance.client import Client +import pandas as pd +import numpy as np +from datetime import datetime +import requests +from rich.console import Console +from rich.table import Table +from rich.panel import Panel +from rich.text import Text +from rich import box + + +# 初始化 Binance API +api_key = 'HCpeel8g6fsTK2630b7BvGBcS09Z3qfXkLVcAY2JkpaiMm1J6DWRvoQZBQlElDJg' +api_secret = 'TySs6onlHOTrGzV8fMdDxLKTWWYnQ4rCHVAmjrcHby17acKflmo7xVTWVsbqtxe7' +client = Client(api_key, api_secret) + +# 获取 24h 涨幅和成交量 +url = "https://api.binance.com/api/v3/ticker/24hr" +response = requests.get(url) +tickers = response.json() + +df = pd.DataFrame(tickers) +df = df[df['symbol'].str.endswith('USDT') & (~df['symbol'].str.contains('UP|DOWN|BULL|BEAR'))] +df['priceChangePercent'] = pd.to_numeric(df['priceChangePercent'], errors='coerce') +df['quoteVolume'] = pd.to_numeric(df['quoteVolume'], errors='coerce') + +# 初筛条件,成交量大于3000万,24h涨幅小于20% +filtered = df[(df['quoteVolume'] > 3e7) & (df['priceChangePercent'] < 20)] + +top_symbols = filtered.sort_values(by='priceChangePercent', ascending=False).head(50)['symbol'].tolist() + +# 技术指标分析函数 +def analyze_symbol(symbol, interval='1h', limit=1000): + try: + klines = client.get_klines(symbol=symbol, interval=interval, limit=limit) + df = pd.DataFrame(klines, columns=['time', 'open', 'high', 'low', 'close', 'volume', + 'close_time', 'quote_volume', 'trades', + 'taker_buy_base', 'taker_buy_quote', 'ignore']) + df['close'] = pd.to_numeric(df['close']) + df['volume'] = pd.to_numeric(df['volume']) + + # 计算指标 + df['ema20'] = df['close'].ewm(span=20).mean() + df['ema50'] = df['close'].ewm(span=50).mean() + df['ema200'] = df['close'].ewm(span=200).mean() + df['vol_ma20'] = df['volume'].rolling(20).mean() + + # 当前状态 + latest = df.iloc[-1] + + # 成交量突增 + vol_spike = latest['volume'] > 1.5 * latest['vol_ma20'] + + # 上涨趋势 + bull_trend = latest['ema20'] > latest['ema50'] > latest['ema200'] + + # 价格突破 + price_break = latest['close'] > df['close'].rolling(20).max().shift(1).iloc[-1] + + # 是否是箱体运动 + # 计算200根K线内的最高价和最低价 + high_200 = df['high'].rolling(200).max().iloc[-1] + low_200 = df['low'].rolling(200).min().iloc[-1] + # 计算当前价格与200根K线最高价和最低价的距离 + price_distance_high = (latest['close'] - high_200) / high_200 + price_distance_low = (latest['close'] - low_200) / low_200 + + # 是否是箱体运动 + box_movement = price_distance_high < 0.05 and price_distance_low < 0.05 + + score = int(vol_spike) + int(bull_trend) + int(price_break) + int(box_movement) + + return { + '币种': symbol, + '上涨趋势': '是' if bull_trend else '否', + '价格突破': '是' if price_break else '否', + '箱体运动': '是' if box_movement else '否', + '得分': score + } + + except Exception as e: + return { + '币种': symbol, + '上涨趋势': '错误', + '价格突破': '错误', + '箱体运动': '错误', + '得分': 0 + } + +if __name__ == "__main__": + # 执行分析 + results = [analyze_symbol(sym) for sym in top_symbols] + df_result = pd.DataFrame(results) + + # 只取上涨趋势为是 + df_result = df_result[df_result['上涨趋势'] == '是'] + + # 按照得分排序 + df_result = df_result.sort_values(by='得分', ascending=False) + + # 取前10个 + df_final = df_result.head(10) + + # 创建 Rich 控制台 + console = Console() + + # 创建标题面板 + title_panel = Panel( + Text("🔥 今日潜在强势币种分析 🔥", style="bold red", justify="center"), + style="bright_blue", + box=box.DOUBLE + ) + + # 创建时间信息 + time_text = Text(f"📅 分析时间:{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}", style="dim") + + # 创建漂亮的表格 + table = Table( + title="💰 币种分析结果", + show_header=True, + header_style="bold magenta", + box=box.ROUNDED, + title_style="bold cyan" + ) + + # 添加列 + table.add_column("币种", style="bold yellow", width=12) + table.add_column("上涨趋势", justify="center", width=10) + table.add_column("价格突破", justify="center", width=10) + table.add_column("箱体运动", justify="center", width=10) + table.add_column("得分", justify="center", style="bold green", width=8) + + # 添加数据行 + for _, row in df_final.iterrows(): + # 根据得分设置颜色 + if row['得分'] >= 3: + score_style = "bold green" + elif row['得分'] >= 2: + score_style = "bold yellow" + else: + score_style = "bold red" + + # 设置趋势指标的颜色 + trend_color = "green" if row['上涨趋势'] == '是' else "red" + break_color = "green" if row['价格突破'] == '是' else "red" + box_color = "green" if row['箱体运动'] == '是' else "red" + + table.add_row( + f"[bold]{row['币种']}[/bold]", + f"[{trend_color}]{row['上涨趋势']}[/{trend_color}]", + f"[{break_color}]{row['价格突破']}[/{break_color}]", + f"[{box_color}]{row['箱体运动']}[/{box_color}]", + f"[{score_style}]{row['得分']}[/{score_style}]" + ) + + # 输出结果 + console.print("\n") + console.print(title_panel) + console.print(time_text, justify="center") + console.print("\n") + console.print(table) + + # 添加说明信息 + info_panel = Panel( + Text("📊 分析说明\n• 上涨趋势:EMA20 > EMA50 > EMA200\n• 价格突破:突破20日最高价\n• 箱体运动:价格在200日高低点范围内波动\n• 得分越高代表技术面越强势", + style="dim"), + title="💡 指标说明", + border_style="blue" + ) + console.print("\n") + console.print(info_panel) \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index 116ad35..1a9d79c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -4,7 +4,7 @@ services: cryptoai-task: build: . container_name: cryptoai-task - image: cryptoai:0.0.18 + image: cryptoai:0.0.19 restart: always volumes: - ./cryptoai/data:/app/cryptoai/data diff --git a/requirements.txt b/requirements.txt index 4a88e74..0a57bef 100644 --- a/requirements.txt +++ b/requirements.txt @@ -15,6 +15,7 @@ python-multipart==0.0.9 email-validator==2.1.0 tencentcloud-sdk-python==3.0.1030 adata +tabulate # # 日志相关 # logging==0.4.9.6 # # 数据处理相关 diff --git a/test.py b/test.py index b23d29b..1379706 100644 --- a/test.py +++ b/test.py @@ -1,20 +1,5 @@ -from cryptoai.api.adata_api import AStockAPI -from cryptoai.api.binance_api import get_binance_api -import json -from time import sleep -from cryptoai.models.token import TokenManager -from cryptoai.utils.db_manager import get_db_context -from cryptoai.tasks.user import task_run from cryptoai.agents.crypto_agent import CryptoAgent if __name__ == "__main__": - CryptoAgent().start_agent() - - # data = get_binance_api().get_historical_klines( - # symbol="BTCUSDT", - # interval="1h", - # start_str="2024-01-01", - # end_str="2024-01-02", - # limit=100 - # ) - # print(data) + agent = CryptoAgent() + agent.start_agent() \ No newline at end of file