Compare commits

...

88 Commits

Author SHA1 Message Date
aaron
afd9820a94 update 2024-12-07 16:26:43 +08:00
aaron
959b13e2af no message 2024-11-30 22:11:48 +08:00
aaron
a5375c2edd 1 2024-11-20 01:12:37 +08:00
aaron
6829b2a2c8 no message 2024-11-15 22:59:22 +08:00
aaron
5529278254 no message 2024-11-15 22:28:29 +08:00
aaron
150d25e7a2 1 2024-11-15 22:28:21 +08:00
aaron
44ffcfdcca no message 2024-11-14 17:31:51 +08:00
aaron
cd5fcc2882 1 2024-11-14 17:26:22 +08:00
aaron
5f9788ba90 1 2024-11-14 15:28:48 +08:00
aaron
1d0e259a3d 1 2024-11-14 14:30:29 +08:00
aaron
09e524fd18 1 2024-11-14 14:13:06 +08:00
aaron
e7ccad634c 1 2024-11-14 13:55:35 +08:00
aaron
671d8d956a 1 2024-11-14 13:48:15 +08:00
aaron
594750273e 1 2024-11-14 13:45:55 +08:00
aaron
c619cf3275 update 2024-11-14 13:41:55 +08:00
aaron
192454d476 1 2024-11-11 14:39:13 +08:00
aaron
99b8d07c81 1 2024-11-11 14:38:40 +08:00
aaron
d467c9be90 update 2024-11-11 11:28:25 +08:00
aaron
d69261446e 1 2024-10-06 10:10:56 +08:00
aaron
e93ec6516c up 2024-10-06 00:00:34 +08:00
aaron
fdb3423f29 1 2024-09-25 22:34:25 +08:00
aaron
2c359e42a8 1 2024-09-22 22:42:12 +08:00
aaron
a9477ea187 1 2024-09-22 20:26:34 +08:00
aaron
0b34231b54 update 2024-09-22 17:01:06 +08:00
aaron
f6bc443785 1 2024-09-22 11:31:04 +08:00
aaron
90b7bea4e8 1 2024-09-22 09:34:23 +08:00
aaron
f575c665af 1 2024-09-21 22:25:45 +08:00
aaron
14e943cf2a 1 2024-09-21 22:24:49 +08:00
aaron
5c7103fe03 1 2024-09-21 13:38:15 +08:00
aaron
26153a8341 11 2024-09-20 23:52:52 +08:00
aaron
ee7d8f6a58 1 2024-09-20 23:50:42 +08:00
aaron
2e1f709fd0 1 2024-09-20 23:16:37 +08:00
aaron
9e8bb4387c 1 2024-09-20 15:20:50 +08:00
aaron
736f3bf59b 1 2024-09-19 14:29:15 +08:00
aaron
830b9f93d3 no message 2024-09-19 14:29:07 +08:00
aaron
16808eceba 1 2024-09-19 10:43:38 +08:00
aaron
d385863e12 1 2024-09-19 10:09:51 +08:00
aaron
c16a54fb0d 1 2024-09-19 10:09:05 +08:00
aaron
d45d415eac no message 2024-09-19 00:42:55 +08:00
aaron
9d309a38d2 11 2024-09-18 17:51:12 +08:00
aaron
da3c2836c0 update 2024-09-18 16:17:22 +08:00
aaron
f7cac309fc update 2024-08-04 00:22:59 +08:00
aaron
9b6e0931cb 1 2024-07-30 11:45:28 +08:00
aaron
85a7b73f36 1 2024-07-29 12:05:00 +08:00
aaron
7b34e6cd4a 1 2024-07-28 11:20:27 +08:00
aaron
fbbf48b8f1 1 2024-07-27 10:40:58 +08:00
aaron
ee14d2249f 1 2024-07-27 10:30:15 +08:00
aaron
2a6ee8a6b9 1 2024-07-27 10:26:46 +08:00
aaron
74f782454f 1 2024-07-27 10:25:24 +08:00
aaron
c1f2b1727a 1 2024-07-27 10:22:00 +08:00
aaron
3552dd8918 1 2024-07-27 08:58:55 +08:00
aaron
39e3814c69 1 2024-07-27 08:57:11 +08:00
aaron
47aba3bc64 update 2024-07-26 12:11:20 +08:00
aaron
44b18a33aa 1 2024-07-25 22:59:20 +08:00
aaron
89fb681d02 1 2024-07-25 16:32:21 +08:00
aaron
9a23417e84 1 2024-07-25 00:21:23 +08:00
aaron
b3826f99a5 no message 2024-07-25 00:12:11 +08:00
aaron
16ee95d585 update 2024-07-25 00:12:02 +08:00
aaron
48668406f2 1 2024-07-24 17:14:51 +08:00
aaron
69dac8e5c2 update 2024-07-24 14:47:41 +08:00
aaron
56679a2b81 update 2024-07-24 14:40:50 +08:00
aaron
471cf10a02 1 2024-07-24 14:35:10 +08:00
aaron
1629c4e943 up 2024-07-24 14:32:38 +08:00
aaron
51d5ebb450 update 2024-07-24 14:31:12 +08:00
aaron
373f8c96ff update 2024-07-24 14:29:25 +08:00
aaron
73caaffef8 1 2024-06-08 10:28:51 +08:00
aaron
6a7d1253c3 1 2024-06-07 22:39:48 +08:00
aaron
645318bfc6 1 2024-06-07 22:34:41 +08:00
aaron
7a544b3bed 1 2024-06-07 21:22:48 +08:00
aaron
8e058603ff 1 2024-06-07 11:09:54 +08:00
aaron
94ca608033 1 2024-06-07 10:56:02 +08:00
aaron
e2c8ee1594 1 2024-06-07 10:55:50 +08:00
aaron
b8180a843b 12 2024-06-07 09:41:43 +08:00
aaron
8995266ee1 1 2024-06-06 22:50:34 +08:00
aaron
721968b85d 1 2024-06-06 22:48:51 +08:00
aaron
6decd1b4db 1 2024-06-06 21:13:58 +08:00
aaron
7b1a20567f 12 2024-06-06 21:09:51 +08:00
aaron
0dd5ca80a3 1 2024-06-06 21:09:43 +08:00
aaron
66ce3a5e36 12 2024-06-06 21:07:48 +08:00
aaron
1e607675d3 1 2024-06-06 19:58:10 +08:00
aaron
d4857350c9 1 2024-06-06 19:56:57 +08:00
aaron
bf63933285 1 2024-06-06 19:38:28 +08:00
aaron
89d274e1c5 first 2024-06-06 19:18:26 +08:00
aaron
c16615ee87 update 2024-04-23 22:28:19 +08:00
aazhou
876eb90190 try 2023-07-17 22:19:21 +08:00
aazhou
9ed369fdcf add timezone. 2023-07-04 00:09:37 +08:00
JayRen
a790c459ee Merge remote-tracking branch 'origin/master'
# Conflicts:
#	signals/macd.py
2023-07-03 22:56:53 +08:00
JayRen
d356bf86c0 updated signals - MACD message 2023-07-03 22:56:24 +08:00
22 changed files with 644 additions and 598 deletions

View File

@ -1,7 +1,6 @@
FROM dockerproxy.com/veejar/python-ta-lib
ENV PYTHONIOENCODING=utf-8
ENV TIME_ZONE Asia/Shanghai
ENV TZ Asia/Shanghai
WORKDIR /opt/
COPY ["./", "/opt/"]

24
bn.py
View File

@ -1,24 +0,0 @@
from binance.spot import Spot
from binance.cm_futures import CMFutures
cm = CMFutures()
# Get klines
def klines(symbol, interval, limit=1000):
lines = cm.klines(symbol,interval, limit=limit)
return lines
def ticker_price(symbol):
prices = cm.ticker_price(symbol)
return prices[0]['price'] if len(prices)>0 else 0
# Get Symbols
def symbols():
info = cm.exchange_info()
symbols = []
for s in info['symbols']:
if s['symbol'].endswith('_PERP'):
symbols.append(s['symbol'])
return symbols

106
datasource/crypto.py Normal file
View File

@ -0,0 +1,106 @@
import requests
from binance.spot import Spot
import pandas as pd
from binance.um_futures import UMFutures
import urllib3
api_key = "HCpeel8g6fsTK2630b7BvGBcS09Z3qfXkLVcAY2JkpaiMm1J6DWRvoQZBQlElDJg"
api_secret= "TySs6onlHOTrGzV8fMdDxLKTWWYnQ4rCHVAmjrcHby17acKflmo7xVTWVsbqtxe7"
client = Spot(api_key, api_secret)
future_client = UMFutures(api_key, api_secret)
# 获取市值前top的币种
def _get_top_coins_by_market_cap(top):
coingecko_url = "https://api.coingecko.com/api/v3/coins/markets"
params = {
'vs_currency': 'usd',
'order': 'market_cap_desc',
'per_page': top,
'page': 1
}
urllib3.disable_warnings(category=urllib3.exceptions.InsecureRequestWarning)
response = requests.get(coingecko_url, params=params, verify=False)
coins = response.json()
return coins
# 获取Binance上的USDT交易对信息
def _get_binance_usdt_pairs():
url = "https://api.binance.com/api/v3/exchangeInfo"
urllib3.disable_warnings(category=urllib3.exceptions.InsecureRequestWarning)
response = requests.get(url, verify=False)
data = response.json()
usdt_pairs = [symbol['symbol'] for symbol in data['symbols'] if (symbol['quoteAsset'] == 'USDT' and symbol['status'] == 'TRADING')]
return usdt_pairs
def get_top_binance_usdt_pairs(top):
# 获取市值前10的币种
top_coins = _get_top_coins_by_market_cap(top)
# 获取Binance上的USDT交易对
usdt_pairs = _get_binance_usdt_pairs()
# 筛选出前10币种中与USDT有交易对的币种
top_pairs = []
for coin in top_coins:
coin_symbol = coin['symbol'].upper()
pair = f"{coin_symbol}USDT"
if pair in usdt_pairs:
top_pairs.append(pair)
return top_pairs
## 获取所有现货交易对
def get_symbols():
data = client.exchange_info()["symbols"]
# 创建DataFrame
columns = ['symbol', 'status', 'baseAsset', 'quoteAsset']
df = pd.DataFrame(data, columns=columns)
df = df[(df['status'] == 'TRADING') & (df['quoteAsset'] == 'USDT')]
return df['symbol']
def get_future_symbols():
data = future_client.exchange_info()["symbols"]
# 创建DataFrame
columns = ['symbol', 'status','contractType', 'baseAsset', 'quoteAsset']
df = pd.DataFrame(data, columns=columns)
# 过滤出交易对
df = df[(df['status'] == 'TRADING') & (df['contractType'] == 'PERPETUAL')]
return df['symbol']
## 根据交易对和周期获取数据集
def get_klines(symbol,interval, future = False,limit=1000):
# 获取 k 线数据
data = {}
if future == True:
data = future_client.klines(symbol, interval, limit=limit)
else:
data = client.klines(symbol, interval,limit=limit)
# 将数据转换为DataFrame
columns = ['timestamp', 'open', 'high', 'low', 'close', 'volume',
'close_time', 'quote_asset_volume', 'number_of_trades',
'taker_buy_base_asset_volume', 'taker_buy_quote_asset_volume', 'ignore']
df = pd.DataFrame(data, columns=columns)
# 转化成 float
df['open'] = df['open'].astype('float64')
df['high'] = df['high'].astype('float64')
df['low'] = df['low'].astype('float64')
df['close'] = df['close'].astype('float64')
df['volume'] = df['volume'].astype('float64')
# 将时间戳转换为日期时间格式
df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms', utc=True).map(lambda x: x.tz_convert('Asia/Shanghai'))
df['close_time'] = pd.to_datetime(df['close_time'], unit='ms', utc=True).map(lambda x: x.tz_convert('Asia/Shanghai'))
return df

323
db.py
View File

@ -1,323 +0,0 @@
#数据库工具
import datetime
import threading
import time
import traceback
import warnings
from contextlib import contextmanager
from functools import wraps
from urllib.parse import urlparse, parse_qsl
import pymysql
from dbutils.pooled_db import PooledDB
warnings.filterwarnings("ignore")
from setting import dbUrl
def __parseresult_to_dict(parsed):
#解析连接字符串
path_parts = parsed.path[1:].split('?')
query = parsed.query
connect_kwargs = {'db': path_parts[0]}
if parsed.username:
connect_kwargs['user'] = parsed.username
if parsed.password:
connect_kwargs['password'] = parsed.password
if parsed.hostname:
connect_kwargs['host'] = parsed.hostname
if parsed.port:
connect_kwargs['port'] = parsed.port
# Adjust parameters for MySQL.
if 'password' in connect_kwargs:
connect_kwargs['passwd'] = connect_kwargs.pop('password')
# Get additional connection args from the query string
qs_args = parse_qsl(query, keep_blank_values=True)
for key, value in qs_args:
if value.lower() == 'false':
value = False
elif value.lower() == 'true':
value = True
elif value.isdigit():
value = int(value)
elif '.' in value and all(p.isdigit() for p in value.split('.', 1)):
try:
value = float(value)
except ValueError:
pass
elif value.lower() in ('null', 'none'):
value = None
connect_kwargs[key] = value
if 'maxsize' in connect_kwargs:
connect_kwargs['maxconnections'] = connect_kwargs.pop('maxsize')
return connect_kwargs
def __create_pool(url):
#创建连接池
parsed = urlparse(url)
connect_kwargs = __parseresult_to_dict(parsed)
return PooledDB(pymysql, 1, **connect_kwargs)
# 数据库连接
global setting, transaction_map, pool
if "transaction_map" not in globals():
global transaction_map
transaction_map = {}
if "pool" not in globals():
global pool
pool = __create_pool(dbUrl)
def __get_connection():
#获取数据库链接
tid = threading.get_ident()
if tid in transaction_map:
return transaction_map.get(tid)
else:
return pool.connection()
def __close_connection(conn):
#归还数据库链接
tid = threading.get_ident()
if tid in transaction_map:
return
else:
conn.close()
@contextmanager
def dbp():
#with 数据库方法块
f = __get_connection()
yield f
__close_connection(f)
def execute_sql(sql,params=None):
#执行sql
with dbp() as db:
c = db.cursor()
c.execute(sql,params)
db.commit()
c.close()
def execute_sql_list(sqls):
#批量执行sql语句
with dbp() as db:
c = db.cursor()
for sql in sqls:
c.execute(sql)
db.commit()
c.close()
def __get_obj_list_sql(obj_list, table, replace=True):
#获取对象插入sql以及对应参数
if obj_list:
obj = obj_list[0]
keys=list(map(lambda x: f"`{x}`",obj.keys()))
values = list(map(lambda x:"%s",obj.keys()))
if replace:
sql = f"""replace INTO `{table}` ({",".join(keys)}) VALUES ({",".join(values)})"""
else:
sql = f"""insert INTO `{table}` ({",".join(keys)}) VALUES ({",".join(values)})"""
params = []
for obj in obj_list:
params.append(tuple(obj.values()))
return sql, params
else:
return "", []
def __get_obj_update_sql(obj, table, key):
#获取对象插入sql以及对应参数
key_sql=f"where {key}='{obj[key]}'"
del obj[key]
keys=list(map(lambda x: f"`{x}`=%s",obj.keys()))
sql = f"""update `{table}` set {",".join(keys)} """ + key_sql
params =tuple(obj.values())
return sql, params
def sql_to_dict(sql,params=None):
#查询sql输出dict 列表
with dbp() as db:
c = db.cursor()
c.execute(sql,params)
ncols = len(c.description)
colnames = [c.description[i][0] for i in range(ncols)]
db_list = c.fetchall()
ret_list = []
for row in db_list:
d = Map()
for i in range(ncols):
if isinstance(row[i],bytes) and len(row[i])==1:
d[colnames[i]] = True if row[i] == b'\x01' else False
else:
d[colnames[i]] = row[i]
ret_list.append(d)
c.close()
return ret_list
def start_transaction():
#开始事务
conn = __get_connection()
conn.autocommit = False
tid = threading.get_ident()
transaction_map[tid] = conn
return tid
def end_transaction(rockback=False):
#结束事务
tid = threading.get_ident()
conn = transaction_map.pop(tid)
try:
if rockback:
conn.rollback()
else:
conn.commit()
finally:
conn.close()
@contextmanager
def transaction_code():
#with 事务方法块
f = start_transaction()
try:
yield f
end_transaction()
except Exception:
traceback.print_exc()
end_transaction(True)
# 事务
def transaction(target_function):
#事务注解
@wraps(target_function)
def wrapper(*args, **kwargs):
start_transaction()
ret = target_function(*args, **kwargs)
end_transaction()
return ret
return wrapper
def insert(obj, table):
#插入对象
(sql, params) = __get_obj_list_sql([obj], table)
with dbp() as db:
c = db.cursor()
c.execute(sql, params[0])
db.commit()
lid=c.lastrowid
c.close()
return lid
def update(obj, table,key="id"):
#插入对象
(sql, params) = __get_obj_update_sql(obj, table,key)
with dbp() as db:
c = db.cursor()
c.execute(sql, params)
db.commit()
c.close()
def inserts(obj_list, table):
#批量插入对象
if obj_list:
(sql, params) = __get_obj_list_sql(obj_list, table)
with dbp() as db:
c = db.cursor()
c.executemany(sql, params)
db.commit()
c.close()
def get(table,id,idstr="id"):
if isinstance(id,str):id=f"'{id}'"
db_data=sql_to_dict(f"select * from {table} where {idstr}={id}")
if db_data:
return db_data[0]
return None
def get_list(table,where=None):
if not where:return sql_to_dict(f"select * from {table}")
return sql_to_dict(f"select * from {table} where {where}")
class Map(dict):
"""
Example:
m = Map({'first_name': 'Eduardo'}, last_name='Pool', age=24, sports=['Soccer'])
"""
def __init__(self, *args, **kwargs):
super(Map, self).__init__(*args, **kwargs)
for arg in args:
if isinstance(arg, dict):
for k, v in arg.items():
self[k] = v
if kwargs:
for k, v in kwargs.items():
self[k] = v
def __getattr__(self, attr):
return self.get(attr)
def __setattr__(self, key, value):
self.__setitem__(key, value)
def __setitem__(self, key, value):
super(Map, self).__setitem__(key, value)
self.__dict__.update({key: value})
def __delattr__(self, item):
self.__delitem__(item)
def __delitem__(self, key):
super(Map, self).__delitem__(key)
del self.__dict__[key]
def __update_setting():
global setting
s = sql_to_dict("select name,value from setting")
for i in s:
setting[i["name"]] = i["value"]
def __update_setting_thread():
while True:
__update_setting()
time.sleep(5)
# 系统设置
if "setting" not in vars():
setting = Map()
__update_setting()
threading.Thread(target=__update_setting_thread, daemon=True).start()
def get_table_desc(table):
datas=sql_to_dict(f"show full fields from `{table}`")
ret_data=[]
for v in datas:
ret_data.append(Map({"name":v.Field,"type":v.Type,"commnet":v.Comment}))
return ret_data

19
dingding.py Normal file
View File

@ -0,0 +1,19 @@
import requests
import setting
import urllib3
url = 'https://oapi.dingtalk.com/robot/send?access_token=2278b723cd363bb6f85592c743b59b166e70b9e02a275bb5cedbc33b53a5cbdc'
# 发送消息
def send_message(text, isAtAll = False):
formData = {
"msgtype": "text",
"text": {
"content": text
},
"at": {
"isAtAll": isAtAll
}
}
urllib3.disable_warnings(category=urllib3.exceptions.InsecureRequestWarning)
print(requests.post(url, json=formData, verify=False).json())

10
discord_sender.py Normal file
View File

@ -0,0 +1,10 @@
from discord_webhook import DiscordWebhook, DiscordEmbed
def send_message(url,title,content):
webhook = DiscordWebhook(url)
embed = DiscordEmbed(title=title, description=content, color="03b2f8")
webhook.add_embed(embed)
response = webhook.execute()

66
main.py
View File

@ -1,32 +1,58 @@
import schedule
import bn
import setting
import time
import signals.ema_arrangement as maa
import signals.macd as macd
import monitors.large_transfer as lt
import dingding
import monitors.jin10_cal as jin10
from monitors import macd_boll,vol_up
# from plombery import task, get_logger, Trigger, register_pipeline
symbols = bn.symbols()
#vegas
# schedule.every().hour.at(":00").do(vegas.run_crypto, interval = '1h')
# times = ["00:00", "04:00", "08:00", "12:00", "16:00", "20:00"]
# for t in times:
# schedule.every().day.at(t).do(vegas.run_crypto, interval = '4h')
for s in symbols:
#15m
schedule.every(15).minutes.do(maa.run, symbol=s, interval='15m')
schedule.every(15).minutes.do(macd.run, symbol=s, interval='15m')
#1h
schedule.every(1).hours.do(maa.run, symbol=s, interval='1h')
schedule.every(1).hours.do(macd.run, symbol=s, interval='1h')
#vegas_cross
# schedule.every().hour.at(":00").do(vegas_cross.run_crypto, interval = '1h')
# times = ["00:00", "04:00", "08:00", "12:00", "16:00", "20:00"]
# for t in times:
# schedule.every().day.at(t).do(vegas_cross.run_crypto, interval = '4h')
#4h
schedule.every(4).hours.do(maa.run, symbol=s, interval='4h')
schedule.every(4).hours.do(macd.run, symbol=s, interval='4h')
# register_pipeline(tasks=[vol_up.run_crypto('15')], triggers=[Trigger()])
# 监控
schedule.every(setting.whaleAlert_minutes).minutes.do(lt.run)
print(f'Running... ChatID: {setting.chat_id}')
#vol
schedule.every(5).minutes.do(vol_up.run_crypto, interval = '5m')
schedule.every().hour.at(":00").do(vol_up.run_crypto, interval = '15m')
schedule.every().hour.at(":15").do(vol_up.run_crypto, interval = '15m')
schedule.every().hour.at(":30").do(vol_up.run_crypto, interval = '15m')
schedule.every().hour.at(":45").do(vol_up.run_crypto, interval = '15m')
schedule.every().hour.at(":00").do(vol_up.run_crypto, interval = '1h')
#macd_boll
schedule.every().hour.at(":00").do(macd_boll.run_crypto, interval = '15m')
schedule.every().hour.at(":15").do(macd_boll.run_crypto, interval = '15m')
schedule.every().hour.at(":30").do(macd_boll.run_crypto, interval = '15m')
schedule.every().hour.at(":45").do(macd_boll.run_crypto, interval = '15m')
schedule.every().hour.at(":00").do(macd_boll.run_crypto, interval = '1h')
times = ["00:00", "04:00", "08:00", "12:00", "16:00", "20:00"]
for t in times:
schedule.every().day.at(t).do(macd_boll.run_crypto, interval = '4h')
#jin10
schedule.every().day.at("09:00").do(jin10.run)
version = 'V1.4'
text = f'☕️ Signals running... {version} !'
print(text)
dingding.send_message(text)
while True:
schedule.run_pending()
time.sleep(1)

72
monitors/jin10_cal.py Normal file
View File

@ -0,0 +1,72 @@
import requests
import datetime
import time
import discord_sender,dingding
def run():
print('金 10 数据数据日历数据抓取...')
addtion_day = 1
items = []
while(addtion_day <= 7):
data_day = datetime.datetime.now() + datetime.timedelta(days=addtion_day)
addtion_day = addtion_day + 1
result = _get_jin10_cal_by_day(data_day.year, data_day.month, data_day.day)
items.extend(result)
time.sleep(1)
if len(items) > 0:
content = ""
for item in items:
print(item)
content += _build_content(item)
print(content)
dingding.send_message(content)
url = 'https://discord.com/api/webhooks/1287027684370681939/fzinKKoNK6KXoLNdj1wttSDtIGio-VHijaYzZInoajHHu-PZyZXVpWDxM6_XrxCtPrPY'
discord_sender.send_message(url, '【最近重要数据公布时间】',content)
def _build_content(item):
content = f"{item['name']} {item['country']} {item['time_period']}\r\n"
if item['previous'] != None:
content += f"前值: {item['previous']}\r\n"
if item['consensus'] != None:
content += f"预测值: {item['consensus']}\r\n"
content += f"重要星级:"
for s in range(item['star']):
content+=""
pub_date = datetime.datetime.strptime(item['pub_time'],'%Y-%m-%dT%H:%M:%S.%fZ') + datetime.timedelta(hours=8)
content += f"\r\n公布时间: {pub_date.strftime('%Y-%m-%d %H:%M:%S')}\r\n\r\n"
return content
def _fill_number(number):
if number<10:
return "0" + str(number)
return number
def _get_jin10_cal_by_day(year,month, day):
url = f"https://cdn-rili.jin10.com/data/{year}/{_fill_number(month)}{_fill_number(day)}/economics.json"
print(url)
data = requests.get(url).json()
items = []
for item in data:
if item['star'] >= 4:
items.append(item)
return items

View File

@ -1,50 +0,0 @@
import requests
import setting
from datetime import datetime, timedelta
import time
import tg
import traceback
import logging
import json
def run():
try:
start_time = datetime.now() - timedelta(minutes=setting.whaleAlert_minutes)
start_ts = int(start_time.timestamp())
url = f'https://api.whale-alert.io/v1/transactions?api_key={setting.whaleAlert_apikey}&start={start_ts}&min_value={setting.whaleAlert_max_limit}'
headers = {'Accept': 'application/json'}
resp = requests.get(url, headers=headers).text
# 判断是否为JSON格式
if json.dumps(resp) == False:
print(resp)
return
data = json.loads(resp)
print(data)
if data['result'] == "success":
if 'transactions' in data:
data = data['transactions']
for ts in data:
if ts['to']['owner_type'] == 'exchange':
amount = int(ts['amount'])
amount_usd = int(ts['amount_usd'])
amount_format = f'{int(amount_usd):,d}'
amount_usd_format = f'{int(amount_usd):,d}'
content = f"🚨大额转入提醒🚨\r\n\r\n {amount_format} #{ts['symbol']} ({amount_usd_format} USD) 从 {ts['from']['owner']} 转入 #{ts['to']['owner']}"
print(content)
tg.send_message(setting.chat_id, content)
else:
print(data)
tg.send_message(setting.chat_id, data['message'])
except:
logging.error(traceback.format_exc())

79
monitors/macd_boll.py Normal file
View File

@ -0,0 +1,79 @@
import talib
import numpy as np
import time,setting
import telegram_sender
from datasource import crypto
import dingding
import discord_sender
# crossover 函数:检测上穿信号
def crossover(series1, series2):
return (series1 > series2) & (series1.shift(1) <= series2.shift(1))
# crossunder 函数:检测下穿信号
def crossunder(series1, series2):
return (series1 < series2) & (series1.shift(1) >= series2.shift(1))
## 检查信号
def stratergy_run(symbol, interval, df, debug):
macd_fast_length = 12
macd_slow_length = 26
macd_signal_length = 9
bollinger_length = 20
bollinger_mult = 2.0
# 计算EMA 144 200
fast_ema = talib.EMA(df['close'], timeperiod=144)
slow_ema = talib.EMA(df['close'], timeperiod=200)
# 计算 MACD
macd, macd_signal, macd_hist = talib.MACD(df['close'], fastperiod=macd_fast_length, slowperiod=macd_slow_length, signalperiod=macd_signal_length)
# 计算布林带
upperband, middleband, lowerband = talib.BBANDS(df['close'], timeperiod=bollinger_length, nbdevup=bollinger_mult, nbdevdn=bollinger_mult, matype=0)
# 生成交易信号
long_condition = (macd.shift(1) <= 0) & (macd > 0) & (df['high'] < upperband) & ((df['close'] > fast_ema) | (df['close'] > slow_ema))
short_condition = (macd.shift(1) >= 0) & (macd < 0) & (df['low'] > lowerband) & ((df['close'] < fast_ema) | (df['close'] < slow_ema))
df['Long_Signal'] = np.where(long_condition, True, False)
df['Short_Signal'] = np.where(short_condition,True, False)
latest = df.iloc[-2]
print(f"{symbol} - {interval}】 is checked!")
direction = ""
if latest['Short_Signal'] == True:
direction = ''
if latest['Long_Signal'] == True:
direction = ''
if direction != "":
message = '🦄Signals Notificaiton🦄\r\n\r\n'
message += f"策略:【MACD+BOLL策略V1.1】\r\n"
message += f"品种: {symbol}\r\n"
message += f"周期: {interval}\r\n"
message += f"信号: 【{direction}\r\n"
message += f"收盘价: {latest['close']}\r\n"
if debug == False:
# url = 'https://discordapp.com/api/webhooks/1286585288986198048/iQ-yr26ViW45GM48ql8rPu70Iumqcmn_XXAmxAcKGeiQBmTQoDPeq-TmlChvIHkw_HJ-'
# discord_sender.send_message(url,'🦄信号提醒🦄',message)
dingding.send_message(message)
print(f"{symbol} - {interval}】 is singal fired!")
else:
print(message)
def run_crypto(interval, debug=False):
print('MACD+BOLL is running...')
time.sleep(5)
for s in setting.symbols:
df = crypto.get_klines(s, interval, True)
stratergy_run(s,interval, df, debug)
time.sleep(1)

63
monitors/move.py Normal file
View File

@ -0,0 +1,63 @@
import talib
import time,setting
import telegram_sender
from datasource import crypto
import dingding
import discord_sender
import setting
# crossover 函数:检测上穿信号
def crossover(series1, series2):
return (series1 > series2) and (series1.shift(1) <= series2.shift(1))
# crossunder 函数:检测下穿信号
def crossunder(series1, series2):
return (series1 < series2) and (series1.shift(1) >= series2.shift(1))
## 检查信号
def stratergy_run(symbol, interval, df, debug):
maxDifference = 0.005
## 计算 ema
df['ema5'] = talib.EMA(df['close'], timeperiod=5)
df['ema10'] = talib.EMA(df['close'], timeperiod=10)
df['ema30'] = talib.EMA(df['close'], timeperiod=30)
df['ema144'] = talib.EMA(df['close'], timeperiod=144)
df['shortDiff'] = abs(df['ema5'] - df['ema10']) / df['ema10']
df['midDiff'] = abs(df['ema10'] - df['ema30']) / df['ema30']
df['longDiff'] = abs(df['ema30'] - df['ema144']) / df['ema144']
df['priceCheck'] = ((df['longDiff'] <= maxDifference) & (df['midDiff'] <= maxDifference) & (df['shortDiff'] <= maxDifference))
df['isLongArrangement'] = ((df['ema5'] > df['ema10']) & (df['ema10'] > df['ema30']) & (df['ema30'] > df['ema144']))
df['isShortArrangement'] = ((df['ema5'] < df['ema10']) & (df['ema10'] < df['ema30']) & (df['ema30'] < df['ema144']))
d1 = df.iloc[-1]
d2 = df.iloc[-2]
d3 = df.iloc[-3]
maxDiff = max(d1['shortDiff'], d1['midDiff'], d1['longDiff'])
minDiff = min(d1['shortDiff'], d1['midDiff'], d1['longDiff'])
isbullish = d1['isLongArrangement'] == True and d2['isLongArrangement'] == True and d3['isLongArrangement'] == False
isBear = d1['isShortArrangement'] == True and d2['isShortArrangement'] == True and d3['isShortArrangement'] == False
print(f"{symbol} - {interval} bullish: {isbullish} | bear : {isBear} | LongArrangement: {d1['isLongArrangement']} | ShortArrangement: {d1['isShortArrangement']}")
if(isbullish | isBear):
message = f"策略:【均线排列信号】\r\n"
message += f"品种: {symbol}\r\n"
message += f"周期: {interval}\r\n"
message += f"信号: 【{'' if isbullish else ''}\r\n"
message += f"收盘价: {d1['close']}\r\n"
url = 'https://discordapp.com/api/webhooks/1285867836454998077/JNAFUyur_ygOJIh6C4beUAVYMpm1TZf4IEeMn8Q1p0TglO1Hjyiu2LQqiU5AxVovWyiO'
discord_sender.send_message(url,'🦄信号提醒🦄',message)
def run_crypto(interval, debug=False):
for s in setting.symbols:
df = crypto.get_klines(s, interval)
stratergy_run(s,interval, df, debug)
time.sleep(1)

73
monitors/vegas.py Normal file
View File

@ -0,0 +1,73 @@
import talib
import numpy as np
import time,setting
import telegram_sender
from datasource import crypto
import dingding
import discord_sender
# crossover 函数:检测上穿信号
def crossover(series1, series2):
return (series1 > series2) & (series1.shift(1) <= series2.shift(1))
# crossunder 函数:检测下穿信号
def crossunder(series1, series2):
return (series1 < series2) & (series1.shift(1) >= series2.shift(1))
## 检查信号
def stratergy_run(symbol, interval, df, debug):
## 计算 ema
df['ema13'] = talib.EMA(df['close'], timeperiod=13)
df['ema144'] = talib.EMA(df['close'], timeperiod=144)
df['ema169'] = talib.EMA(df['close'], timeperiod=169)
df['ema576'] = talib.EMA(df['close'], timeperiod=576)
df['ema676'] = talib.EMA(df['close'], timeperiod=676)
maxline = np.maximum(df['ema144'], df['ema169'])
minline = np.minimum(df['ema144'], df['ema169'])
shortArragement = df['ema13'] < minline
longArrangement = df['ema13'] > maxline
confuse = (df['ema13'] >= minline) & (df['ema13'] <= maxline)
crossRatio = 0.2
shortA = crossunder(df['ema13'], minline)
shortB = shortArragement & crossunder(df['close'], minline) & (((minline - df['close']) / df.apply(lambda x: abs(x['open'] - x['close']), axis=1)) > crossRatio)
df['shortResut'] = (shortA | shortB) & (confuse == False)
longA = crossover(df['ema13'], maxline)
longB = longArrangement & crossover(df['close'], maxline) & (((df['close'] - maxline) / df.apply(lambda x: abs(x['open'] - x['close']), axis=1)) > crossRatio)
df['longResut'] = (longA | longB) & (confuse == False)
latest = df.iloc[-1]
direction = ""
if latest['shortResut']==True:
direction = ''
if latest['longResut']==True:
direction = ''
message = f"策略:【Vegas反转策略】\r\n"
message += f"品种: {symbol}\r\n"
message += f"周期: {interval}\r\n"
message += f"信号: 【{direction}\r\n"
message += f"收盘价: {latest['close']}\r\n"
print(f"{symbol} - {interval}】 is checked!")
if direction != "":
if debug == False:
url = 'https://discordapp.com/api/webhooks/1285867836454998077/JNAFUyur_ygOJIh6C4beUAVYMpm1TZf4IEeMn8Q1p0TglO1Hjyiu2LQqiU5AxVovWyiO'
discord_sender.send_message(url,'🦄信号提醒🦄',message)
print(f"{symbol} - {interval}】 is singal fired!")
else:
print(message)
def run_crypto(interval, debug=False):
for s in setting.symbols:
df = crypto.get_klines(s, interval)
stratergy_run(s,interval, df, debug)
time.sleep(1)

65
monitors/vegas_cross.py Normal file
View File

@ -0,0 +1,65 @@
import talib
import numpy as np
import time,setting
import telegram_sender
from datasource import crypto
import dingding
import discord_sender
import setting
# crossover 函数:检测上穿信号
def crossover(series1, series2):
return (series1 > series2) & (series1.shift(1) <= series2.shift(1))
# crossunder 函数:检测下穿信号
def crossunder(series1, series2):
return (series1 < series2) & (series1.shift(1) >= series2.shift(1))
## 检查信号
def stratergy_run(symbol, interval, df, debug):
## 计算 ema
df['ema144'] = talib.EMA(df['close'], timeperiod=144)
df['ema169'] = talib.EMA(df['close'], timeperiod=169)
df['ema576'] = talib.EMA(df['close'], timeperiod=576)
df['ema676'] = talib.EMA(df['close'], timeperiod=676)
max_low_line = np.maximum(df['ema144'], df['ema169'])
min_low_line = np.minimum(df['ema144'], df['ema169'])
max_high_line = np.maximum(df['ema576'], df['ema676'])
min_high_line = np.minimum(df['ema576'], df['ema676'])
df['longSignal'] = crossover(min_low_line, max_high_line)
df['shortSignal'] = crossunder(max_low_line, min_high_line)
latest = df.iloc[-1]
direction = ""
if latest['shortSignal']==True:
direction = ''
if latest['longSignal']==True:
direction = ''
message = f"策略:【Vegas金叉死叉策略】\r\n"
message += f"品种: {symbol}\r\n"
message += f"周期: {interval}\r\n"
message += f"信号: 【{direction}\r\n"
message += f"收盘价: {latest['close']}\r\n"
print(f"{symbol} - {interval}】 is checked!")
if direction != "":
if debug == False:
url = 'https://discordapp.com/api/webhooks/1285867836454998077/JNAFUyur_ygOJIh6C4beUAVYMpm1TZf4IEeMn8Q1p0TglO1Hjyiu2LQqiU5AxVovWyiO'
discord_sender.send_message(url,'🦄信号提醒🦄',message)
print(f"{symbol} - {interval}】 is singal fired!")
else:
print(message)
def run_crypto(interval, debug=False):
for s in setting.symbols:
df = crypto.get_klines(s, interval,True)
stratergy_run(s,interval, df, debug)
time.sleep(1)

37
monitors/vol_up.py Normal file
View File

@ -0,0 +1,37 @@
# 突然放量策略
import numpy as np
from datasource import crypto
import time, dingding
def stratergy_run(symbol, interval, df, debug):
# 计算过去 30 根 K 线的平均交易量
average_volume = df["volume"].iloc[-31:-1].mean() # 倒数第 31 到倒数第 2 根的平均
# 获取当前(最后一根,即第 500 根)交易量
current_volume = df["volume"].iloc[-1]
timestamp = df['timestamp'].iloc[-1]
rate = current_volume / average_volume
rate_limit = 10
if rate > rate_limit:
message = "📢Signals Notificaiton📢\r\n\r\n"
message += f"{symbol}{interval} 出现放量 {round(rate, 2)}\r\n\r\n"
message += f"{timestamp}"
if debug == False:
dingding.send_message(message)
print(f"{symbol} - {interval}】 is singal fired!")
else:
print(message)
def run_crypto(interval, debug=False):
print(f"Vols-up strategy {interval} is running...")
symbols = crypto.get_future_symbols()
for s in symbols:
df = crypto.get_klines(s, interval, True,limit=50)
stratergy_run(s,interval, df, debug)
time.sleep(1)

View File

@ -1,11 +1,10 @@
binance==0.3
binance_connector==3.1.0
DBUtils==3.0.2
mplfinance==0.12.9b7
numpy==1.23.4
pandas==1.5.1
PyMySQL==1.0.2
requests==2.28.1
schedule==1.1.0
TA_Lib==0.4.26
binance-futures-connector==3.3.1
binance
binance_connector
binance-futures-connector
numpy==1.26.4
pandas
requests
schedule
tweepy
discord_webhook
redis

View File

@ -1,8 +1,5 @@
import os
dbUrl = os.getenv("DB_URL", "mysql://tradinguser:BciA3^owC3UFlC7q@wpoolsjp.rwlb.singapore.rds.aliyuncs.com:3306/tradingdata?charset=utf8mb4&maxsize=50")
# telegram bot key
telegram_bot_key='5863718864:AAFijN65_SbbGQ0WDBggzKJw2SIcZVTVrPw'
@ -10,15 +7,8 @@ telegram_bot_key='5863718864:AAFijN65_SbbGQ0WDBggzKJw2SIcZVTVrPw'
chat_id = os.getenv("TQ_CHAT_ID", "@cyber4trading")
#oklink
oklink_host = 'https://www.oklink.com'
oklink_apikey='ca822b3f-2e1e-479c-8649-c1f9b62a740d'
oklink_api_headers = {
'Ok-Access-Key' : oklink_apikey
}
symbols = ['BTCUSDT',"ETHUSDT",'LTCUSDT','DOGEUSDT','FTMUSDT','FILUSDT','OPUSDT','SOLUSDT','BNBUSDT','BCHUSDT','ETCUSDT','ARUSDT',"REEFUSDT","BONDUSDT","VIDTUSDT","UNFIUSDT","PEOPLEUSDT","ORDIUSDT"]
#whaleAlert
whaleAlert_minutes=1
whaleAlert_apikey='gPkElMPR8Hpe5LxjKisR4YSFzxRxMLj6'
whaleAlert_max_limit = os.getenv('TQ_WHALEALERT_MAX_USD_AMOUNT',5000 * 10000)
#dingding bot
singal_bot_url = 'https://oapi.dingtalk.com/robot/send?access_token=2278b723cd363bb6f85592c743b59b166e70b9e02a275bb5cedbc33b53a5cbdc'

View File

@ -1,57 +0,0 @@
import talib
import numpy as np
import bn
import tg
import datetime
import setting
import db
import signals.signal_builder as signal_builder
flags = {}
def check_ema_arrange(data):
# 提取收盘价
close_prices = np.array([float(entry[4]) for entry in data])
# 计算移动平均线
ema7 = talib.EMA(close_prices, timeperiod=7)
ema30 = talib.EMA(close_prices, timeperiod=30)
ema100 = talib.EMA(close_prices, timeperiod=100)
ema200 = talib.EMA(close_prices, timeperiod=200)
bullish = ema7[-1] > ema30[-1] > ema100[-1] > ema200[-1]
bearish = ema7[-1] < ema30[-1] < ema100[-1] < ema200[-1]
return bullish, bearish
def run(symbol, interval):
# 获取kline数据
data = bn.klines(symbol, interval)
ticker_price = bn.ticker_price(symbol)
bullish, bearish = check_ema_arrange(data)
flag_name = symbol + '_' + interval
text = ""
data = {}
if bullish and (flag_name not in flags or flags[flag_name] == False):
flags[flag_name] = True
text = signal_builder.signal_text(symbol, interval, "EMA排列","【多】")
data = {"type" : 1, "symbol": symbol, "interval" : interval, "signal": 1}
if bearish and (flag_name not in flags or flags[flag_name] == True):
flags[flag_name] = False
text = signal_builder.signal_text(symbol, interval, "EMA排列","【空】")
data = {"type" : 1, "symbol": symbol, "interval" : interval, "signal": 3}
if text != "":
signals = db.get_list('signals', f'symbol="{symbol}" and `interval`="{interval}"')
for s in signals:
print(s)
db.execute_sql(f'delete from signals where `id`={s["id"]}')
db.insert(data, 'signals')
print(text)
tg.send_message(setting.chat_id, text)

View File

@ -1,76 +0,0 @@
import talib
import numpy as np
import bn
import tg
import datetime
import setting
import db
import signals.signal_builder as signal_builder
def check_macd(data):
close_prices = np.array([float(entry[4]) for entry in data])
# 自定义参数
fast_period = 12
slow_period = 26
signal_period = 9
print(close_prices[-1], close_prices[-2], close_prices[-3], close_prices[-4])
# 计算MACD指标 macd - DIF; macdsignal - DEA; macdhist- 柱状线
macd, macd_signal, macd_hist = talib.MACD(close_prices, fastperiod=fast_period, slowperiod=slow_period,
signalperiod=signal_period)
print("MACD:", round(macd[-1], 2))
print("Signal:", round(macd_signal[-1], 2))
print("Histogram:", round(macd_hist[-1], 2))
print("----------")
print("MACD:", round(macd[-2], 2))
print("Signal:", round(macd_signal[-2], 2))
print("Histogram:", round(macd_hist[-2], 2))
return macd, macd_signal, macd_hist
def generate_signals(macd, macd_signal, macd_hist):
# 1: 多 DIF > 0 and DEA>0 and MACD>0
if macd[-1] > 0 and macd_signal[-1] > 0 and macd_hist[-1] > 0:
signal = 1
# 2: 强多 DIF > 0 and DEA>0 and DIF>DEA AND MACD>0
elif macd[-1] > 0 and macd_signal[-1] > 0 and macd[-1] > macd_signal[-1] and macd_hist[-1] > 0:
signal = 2
# 3
elif macd[-1] < 0 and macd_signal[-1] < 0 and macd[-1] < macd_signal[-1]:
signal = 3
# 4: 强空
elif macd[-1] < 0 and macd_signal[-1] < 0 and macd[-1] < macd_signal[-1] and macd_hist[-1] < 0:
signal = 2
else:
signal = 0
return signal
def run(symbol, interval):
# 获取kline数据
data = bn.klines(symbol, interval)
macd, macd_signal, macd_hist = check_macd(data)
signal = generate_signals(macd, macd_signal, macd_hist)
print(signal)
text = ""
data = {}
if signal == 1 or signal == 2:
text = signal_builder.signal_text(symbol, interval, "MACD","【多】")
data = {"type": 2, "symbol": symbol, "interval": interval, "signal": signal}
if signal == 3 or signal == 4:
text = signal_builder.signal_text(symbol, interval, "MACD","【空】")
data = {"type": 2, "symbol": symbol, "interval": interval, "signal": signal}
if text != "":
signals = db.get_list('signals', f'symbol="{symbol}" and `interval`="{interval}"')
for s in signals:
print(s)
db.execute_sql(f'delete from signals where `id`={s["id"]}')
db.insert(data, 'signals')
print(text)
tg.send_message(setting.chat_id, text)

View File

@ -1,10 +0,0 @@
import monitors.large_transfer as lt
import bn
import signals.ema_arrangement as maa
import signals.macd as macd
symbols = bn.symbols()
for s in symbols:
macd.run(s, '15m')

6
strategy_vol.py Normal file
View File

@ -0,0 +1,6 @@
import sys
from monitors import vol_up
if __name__ == "__main__":
args = sys.argv
vol_up.run_crypto(args[1])

View File

@ -1,5 +1,6 @@
import requests
import setting
import urllib3
# 发送消息
def send_message(chat_id, text):
@ -8,4 +9,5 @@ def send_message(chat_id, text):
"chat_id" : chat_id,
"text" : text
}
requests.post(url, data= formData)
urllib3.disable_warnings(category=urllib3.exceptions.InsecureRequestWarning)
requests.post(url, data= formData, verify=False)

62
test.py
View File

@ -1,14 +1,54 @@
import bn
import pandas as pd
import mplfinance as mpf
import datetime as dt
import monitors.large_transfer as lt
from binance.spot import Spot
import signals.ema_arrangement as maa
from binance.cm_futures import CMFutures
import requests
import datasource.crypto
from monitors import move
from datasource import crypto
import talib
import discord_sender
from monitors import vegas_cross, jin10_cal,vol_up
from datasource import crypto
from monitors import macd_boll
import datasource
from binance.um_futures import UMFutures
import redis,dingding
maa.run('MANAUSD_PERP', '1h')
# print(len(bn.symbols()))
# vol_up.run_crypto('1h')
# print(bn.ticker_price('BTCUSD_PERP'))
# r = redis.Redis(host='45.76.104.85', port=6379, db=0 ,password="redis_ihkXTj")
# r.set('r_symbols', "test")
# print(r.get('r_symbols'))
print(datasource.crypto.get_future_symbols())
# macd_boll.run_crypto('15m', debug=True)
# jin10_cal.run()
# print(crypto._get_top_coins_by_market_cap(20))
# vegas_cross.run_crypto('1h')
# key = 'QSZvYevTytwi8CJEkiUqqlZRQBOjIa23BoB8wFwTSY26GBAFkViTExex2mFNJ0ij'
# secret = '1eGO4aeICAxPRXQzw2lQBc0QAkIKn6WiCV4cRLnUwnJulzixYFkoBeho5ZzsKTbn'
# client = UMFutures(key=key, secret=secret)
# # print(client.exchange_info())
# # data = client.funding_rate('BTCUSD_PERP', limit=1)
# print(client.balance())
# fundingRate = float(data[0]['fundingRate']) * 100
# text = f"币种: {data[0]['symbol']}\r\n资金费率: {fundingRate} %"
# mUrl = "https://discordapp.com/api/webhooks/1285898004641091605/DwIh9yZvrU6TwelVmJr96XBdpFTEEpeFD8GsZpH7rBdwT4UwVyZTrtdmBzS4ae0Ta7PH"
# discord_sender.send_message(mUrl, '消息内容',text)
# dingding.send_message('信号 测试')