从最简单双均线策略开始
写一些币安api脚本范例吧,如果要帮写可以,例子从最简单双均线策略开始,无所谓什么策略,只要是出名的策略你不用想肯定没用。只能自己无意中发现的信号可能才会有用吧。
这里的步间距用的价格波动的百分比,这杨也能逃离下主流按K线周期为步距。
然后错误就加仓1.25倍。
简单介绍下双均线策略,属于趋势策略,单边大趋势会获利大部分利润,但是在趋势来临前,小的磨损特别多,导致总体不盈利。
策略一般分两种:趋势策略(等风来,亏吧,来一波行情我就赚了,总在等大行情)
震荡策略(波动吧,我看都不看行情不管涨跌我都赚钱,卧槽怎么超出我的震荡区间了,两个结局,一把亏完。或者等待行情回归震荡区间)
没有第三种策略了。策略只分这两种。
代码直接复制粘贴可用,以前的上古代码了,专业的别喷,业余的目标就是能跑就行。如果我现在优化一遍会好看很多但是没必要了,反正这个策略没效果。
做多信号:短周期信号在长周期上面
做空反之。
import logging
#合约模块
from binance_f import RequestClient
from binance_f import SubscriptionClient
from binance_f.constant.test import *
from binance_f.model import *
from binance_f.exception.binanceapiexception import BinanceApiException
from binance_f.base.printobject import *
##现货杠杆和所有REST请求模块
from binance.spot import Spot as Client
import pandas as pd
import threading
import numpy as np
import datetime
import time
import requests
import matplotlib.pyplot as plt
lock1 = threading.Lock()
#xx = np.load('cx7.1-10.31.npy',allow_pickle=True).tolist()
##np.save('beidan_x11.8.npy',numpy_array )
#################################################### 客户端启动区
#
g_api_key = '贴入自己的key'
g_secret_key = '贴入自己的secret'
# 启动账户数据流
request_client = RequestClient(api_key=g_api_key, secret_key=g_secret_key)
listen_key = request_client.start_user_data_stream()
# 保持数据流
#result = request_client.keep_user_data_stream()
#日志
#websock客户端启动
sub_client = SubscriptionClient(api_key=g_api_key, secret_key=g_secret_key)
client1 = Client(g_api_key, g_secret_key)#现货客户端
############################################################## 函数代码部分 ##############################################################
#交易配置
class dx: # 变量属性
symbol = 'peopleusdt' # 交易对
benji=0.
price_jd = 4 # 价格精度
sl_jd = -1 # 数量精度
jyjg = 1+0.003 # 交易间隔百分比
lrjg = 1+0.003 # 利润间隔百分比
ji= 1+0.01 #波动标准百分比
b=1.2#杠杆倍数
cwcs=0#错误次数
def jindu(x,n):#精度处理
if n>0:return round(x,n)
else:return int(x)
def k_get(url):#获取k线条
try:
k_json=requests.get(url).json()
#print(k_json)
return k_json
except Exception as e:print(e)
def get_history2(symbol,interval,limit):#读取k线数据
x=k_get('https://fapi.binance.com/fapi/v1/klines?symbol='+
symbol+'&interval='+interval+'&limit='+str(limit))
#print(x[0])
return x
def get_ye():#查询余额
bj=request_client.get_balance_v2()#查询账户余额
for i in bj:
#print(i.__dict__)
if 'USDT' == i.asset:
#print(i.__dict__)
tlbenjin1=i.balance#初始本金赋值
return tlbenjin1
def jindu_get(): # 程序初始化数据 获取交易对精度
symboljd = request_client.get_exchange_information()#更新交易对信息
for i in symboljd.symbols:
if i.symbol.lower()==tl.symbol.lower():
jg2=i.filters[0]['tickSize']
sl2=i.filters[1]['stepSize']
print(jg2,sl2)
if '.' in jg2:
jg=len(jg2.split('.')[1].split('1')[0]+'1')
else:jg=0
if '.' in sl2:
sl=len(sl2.split('.')[1])
else:sl=0
print('精度',i.symbol,jg,sl)
return jg,sl
#tl.price_jd = jg # 价格精度
#tl.sl_jd = sl # 数量精度
def cw_gx():#仓位读取
x = request_client.get_position_v2()
cijg=[0,0]
cisl=[0,0]
for i in x:
if i.symbol.lower()==tl.symbol.lower():
if i.positionAmt>0:
cisl[0]= i.positionAmt
cijg[0]=i.entryPrice
if i.positionAmt<0:
cisl[1]= abs(i.positionAmt)
cijg[1]=i.entryPrice
return cisl,cijg
def MARKET(dz,cc,sl):#市价交易 交易动作10,持仓方向10,数量
global suo,sub_client
if cc==1:suo[0]=1
if cc==0:suo[1]=1
print(dz,cc,sl)
sl=str(sl)
side=['SELL', 'BUY']
positionSide=[ 'SHORT','LONG']
print(side[dz],positionSide[cc],sl)
try:
x = request_client.post_order(symbol=tl.symbol, # 交易对
side=side[dz], # 买卖方向 SELL, BUY
ordertype='MARKET', # 交易类型
positionSide=positionSide[cc], # 在双向持仓模式下必填,且仅可选择 LONG 或 SHORT
#timeInForce='GTC',
quantity=sl, # 下单数量,使用closePosition不支持此参数
)
except Exception as e:print('下单出错')
return x
def STOP(dz,cc,jg,sl):#挂单交易 交易动作10,持仓方向10,价格,数量
global suo
if cc==1:suo[0]=1
if cc==0:suo[1]=1
print(dz,cc,jg,sl)
jg=str(jg)
sl=str(sl)
side=['SELL', 'BUY']
positionSide=[ 'SHORT','LONG']
x = request_client.post_order(symbol=tl.symbol, # 交易对
side=side[dz], # 买卖方向 SELL, BUY
ordertype='STOP_MARKET', # 交易类型
positionSide=positionSide[cc], # 在双向持仓模式下必填,且仅可选择 LONG 或 SHORT
timeInForce='GTC',
quantity=sl, # 下单数量,使用closePosition不支持此参数
#price=jg,
stopPrice=jg
)
return x
def LIMIT(dz,cc,jg,sl):#挂单交易 交易动作10,持仓方向10,价格,数量
global suo
if cc==1:suo[0]=1
if cc==0:suo[1]=1
print(dz,cc,jg,sl)
jg=str(jg)
sl=str(sl)
side=['SELL', 'BUY']
positionSide=[ 'SHORT','LONG']
##print(dz,cc,jg,sl)
x = request_client.post_order(symbol=tl.symbol, # 交易对
side=side[dz], # 买卖方向 SELL, BUY
ordertype='LIMIT', # 交易类型
positionSide=positionSide[cc], # 在双向持仓模式下必填,且仅可选择 LONG 或 SHORT
timeInForce='GTC',
quantity=sl, # 下单数量,使用closePosition不支持此参数
price=jg
)
return x.__dict__
'''
1( 现货向USDT本位合约),
2( USDT本位合约向现货)
3( 现货向币本位合约)
4( 币本位合约向现货)
'''
def huazhan(*a):#dx对象,数量,划转类型
dx,je,lx=a
client1.futures_transfer(asset=dx, amount=je, type=lx)
xintiao=1#划转事件模拟心跳
keep_id=0#计数缓存
chongqijishu=0
def fun_timer():
global timer,keep_id,xintiao,request_client,xt_socket,chongqijishu,client1
if xt_socket==1:#一分钟不在线重连
xt_socket=0
else:chonglian()#重连
xintiao+=1
xh_=xintiao#心跳缓存
try:
if xintiao>2:xintiao=1
huazhan('usdt',0.001,xintiao)
keep_id+=1
except Exception as e:
client1 = Client(g_api_key, g_secret_key)#现货客户端
xintiao =xh_
if keep_id>int(55):
chongqijishu+=1
try:request_client.keep_user_data_stream()#55分钟更新一次
except Exception as e:chonglian()#重连
keep_id=0
timer = threading.Timer(1*60, fun_timer)#分钟连接一次
timer.start()
timer = threading.Timer(1*60, fun_timer)
timer.start()
def chonglian():
global listen_key,sub_client
print('自定义重连')
#for i in sub_client.connections:i.ws.close()#关闭连接
while len(sub_client.connections)>0:del sub_client.connections[0]
request_client = RequestClient(api_key=g_api_key, secret_key=g_secret_key)
listen_key = request_client.start_user_data_stream()
sub_client.subscribe_user_data_event(listen_key, callback, error)
sub_client.subscribe_aggregate_trade_event(tl.symbol, call_symbol, error)#行情监听
def call_symbol(data_type, event):
global btcjg
if type(event)!=int :
with lock1:
btcjg=event.price#现价
bodong(event)
def error(e: 'BinanceApiException'):
print(e.error_code + e.error_message)
def callback(ws, event: 'any'):
global ddb,fsl,fjg,suo,listen_key,sub_client,xt_socket
if type(event)!=int and hasattr(event, '__dict__'):
xt_socket=1#在线检测
if event.eventType=='listenKeyExpired':#掉线监听
return ''
#print(event.__dict__)
if type(event)==orderupdate.OrderUpdate:#订单变动
if event.positionSide=='LONG':suo[0]=0
if event.positionSide=='SHORT':suo[1]=0
if type(event)==accountupdate.AccountUpdate:#资金变动,仓位变动监听
if 'type' in event.__dict__:
if event.type=='WITHDRAW' or event.type=='DEPOSIT':return '' #跳过资金资金划转的消息
#if hasattr(event, 'positions'):
#print('positions' in event.__dict__)
if 'eventTime' in event.__dict__:
t=datetime.datetime.fromtimestamp(int(event.eventTime/1000)).strftime('%Y-%m-%d %H:%M:%S')
print(t)
if 'balances' in event.__dict__ :
if len(event.balances)>0:
if event.balances[0].crossWallet>tl.benjin :
tl.benjin= event.balances[0].crossWallet #_____________更新余额
print('余额变化',event.balances[0].crossWallet)
if 'positions' in event.__dict__ :#_____________仓位更新
if len(event.positions)>0 :
if 'positionSide' in event.positions[0].__dict__:
if event.positions[0].positionSide=='LONG':
fsl[0],fjg[0]=abs(event.positions[0].amount),event.positions[0].entryPrice
if event.positions[0].positionSide=='SHORT':#空仓事件
fsl[1],fjg[1]=abs(event.positions[0].amount),event.positions[0].entryPrice
print('仓位变化',fsl,fjg)
# 交易触发 条件
#如果现在需要做空,需要看价格连续上涨不买,当价格下跌一个单位是挂单。
#需要一个定量标准
def pd1(jg):#波动定位器
global tdjl,jg_i
if len(tdjl)>200:tdjl=tdjl[len(tdjl)-200:]
while pow(tl.ji,jg_i-1)>jg:# 计算下跌次数
jg_i-=1
jg_=jindu(pow(tl.ji,jg_i),tl.price_jd)
tdjl.append(['0',jg_])
while pow(tl.ji,jg_i+1)<jg:# 计算下跌次数
jg_i+=1
jg_=jindu(pow(tl.ji,jg_i),tl.price_jd)
tdjl.append(['1',jg_])
def bodong(event):#量化波动
global tdjl,jg_i,t_suo,ZF
if t_suo+10<event.time:t_suo=event.time#时间锁
else:return ''
if len(tdjl)>200:tdjl=tdjl[len(tdjl)-200:]#切段历史数据避免内存过大
jg=event.price
jg_=jindu(pow(tl.ji,jg_i),tl.price_jd)
xh_i=0#波动发生记录器
while pow(tl.ji,jg_i-1)>jg:# 计算下跌次数
jg_i-=1
jg_=jindu(pow(tl.ji,jg_i),tl.price_jd)
tdjl.append(['0',jg_])
xh_i+=1
#print('下跌一次',jg,jg_)
while pow(tl.ji,jg_i+1)<jg:# 计算下跌次数
jg_i+=1
jg_=jindu(pow(tl.ji,jg_i),tl.price_jd)
tdjl.append(['1',jg_])#tdjl.append(['1',jg1])
xh_i+=1
#print('上涨一次',jg,jg_)
if xh_i>0:jyxh(jg_)
def sc_all_gd():#删除所有挂单
pass
def jyxh(jg_,short_window=1, medium_window=7):#交易信号处理
global suo,ddb,zyjg,ZF
if suo[0]==1 or suo[1]==1 :return ''#单线程锁,避免上次交易还未完成
l=len(tdjl)-1
#交易信号生成
df = pd.DataFrame({'price': tdjl})
# 计算均线
df['ema_short'] = df['price'].ewm(span=short_window, adjust=False).mean()
df['ema_medium'] = df['price'].ewm(span=medium_window, adjust=False).mean()
# 生成交易信号
df['signal'] = 0 # 默认无信号
df.loc[(df['ema_short'] > df['ema_medium']) , 'signal'] = 1 # 买入信号
df.loc[(df['ema_short'] < df['ema_medium']), 'signal'] = -1 # 卖出信号
#交易信号
ZF=df['signal'].iloc[-1]
print('Signal',ZF,jg_)
if ZF==1 and fsl[0]==0:
#市价买多交易
sl=jindu(tl.benjin*tl.b/jg_,tl.sl_jd )
MARKET(1,1,sl)
if ZF==-1 and fsl[1]==0:
#市价买空交易
sl=jindu(tl.benjin*tl.b/jg_,tl.sl_jd )
MARKET(0,0,sl)
if fsl[0]>0 and (ZF==-1 or ZF==0):#市价卖多
MARKET(0,1,fsl[0])
if fsl[1]>0 and (ZF==1 or ZF==0):#市价卖空
MARKET(1,0,fsl[1])
############################################################## 函数代码部分 ##############################################################
############################################################## 逻辑代码部分 ##############################################################
suo=[0,0]#多仓线程锁
t_suo=0#再加一个时间锁
ddb=[[[],[]],[[],[]]]#订单id薄
zyjg=[0,0]#卖单挂单价格记录
tdjl=[]#波动记录 格式[涨跌,价格]
jg_i=0#价格系数
ZF = 1#做单方向 负为多,正为空
fc=[[],[]]
btcjg,ethjg=0.,0.
fsl,fjg=[0.,0.],[0.,0.]#仓位数量,仓位价格
tl = dx() # 实例化
tl.price_jd,tl.sl_jd=jindu_get()#获取交易精度
tl.benjin=get_ye()#余额读取
cje=tl.benjin
fsl,fjg=cw_gx()#程序开跑前仓位检查
xt_socket=1#掉线监听
#ZF = request_client.get_mark_price(symbol=tl.symbol.lower())#做单方向 负为多,正为空
#ZF = ZF.lastFundingRate
eth = get_history2(tl.symbol.upper(), '1m', 1000) # 获取数据集用于堆积启动数据
#eth=np.load('eth.npy',allow_pickle=True).tolist()
for i in eth: # k线数据化
pd1(float(i[1]))
request_client.cancel_all_orders(tl.symbol) # 取消所有订单
if fsl[0]>0 or fsl[1]>0:#有仓位进行挂单
pass
else:#没有仓位进行市价交易
pass
#for i in tdjl:print(i)
print(tdjl[len(tdjl)-1])
sub_client.subscribe_user_data_event(listen_key, callback, error)#用户数据监听
sub_client.subscribe_aggregate_trade_event(tl.symbol, call_symbol, error)#行情监听
#threading.Timer(10,chonglian() ).start()
#MARKET(0,0,0.001)