#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
from pathlib import Path
import pandas as pd
from tqsdk import TqApi, TqAuth,TqAccount
from tqsdk.ta import MA
from tqsdk.tafunc import time_to_str
from contextlib import closing
import asyncio
api = TqApi(TqAccount('期货公司','账号','密码'),auth=TqAuth("天勤账号", "密码"))
vt = 'SHFE.rb2105' #品种
Lot = 1 #默认手数
grid_step = 5 #步长
headk=['time','symbol','volume','price','direction','datetime','jia_kai']
headp = ['time','symbol','volume','price','direction','lirun','datetime','jia_ping']
fk = os.getcwd()+'\logs\KaiLog_' + vt + '.csv'
fp = os.getcwd()+'\logs\PingLog_' + vt + '.csv'
print(fk)
if os.path.isfile(fk) != True:
p=Path(os.getcwd()+'\logs')
p.mkdir(exist_ok=True) #新建目录,如果目录已存在,则不会引起错误
h=pd.DataFrame(index=[],columns=headk)
h.to_csv(fk,index=False)
if os.path.isfile(fp) != True:
p=Path(os.getcwd()+'\logs')
p.mkdir(exist_ok=True) #新建目录,如果目录已存在,则不会引起错误
h=pd.DataFrame(index=[],columns=headp)
h.to_csv(fp,index=False)
Kai_Log=pd.read_csv(fk)
Ping_Log=pd.read_csv(fp)
def Cta(api={},quote={},position={},Lots=0,grid_step=5,Kai_Log=[]):
klines = api.get_kline_serial(quote.instrument_id, 60, data_length=200)
ma = MA(klines, 100)
m = list(ma["ma"])
if quote.ask_price1 - quote.bid_price1 <= quote.price_tick :#买卖价差小于等于1跳,流动性足够,防止价差扩大包含均值而反复开平
try :
#Kai_Log['price'] = data['price'].astype('float')
if m[-1] - quote.ask_price1 >= grid_step * 2 * quote.price_tick: #技术形态满足做多条件
if position.pos_long < Lots and position.pos_short == 0: #无多单或多单不够且无空单
return 'duokai'
elif quote.bid_price1 - m[-1] >= grid_step * 2 * quote.price_tick: #技术形态满足做空条件
if position.pos_short < Lots and position.pos_long == 0: #无空单或空单不够且无多单
return 'kongkai'
if quote.bid_price1 - Kai_Log.iloc[-1].price >= grid_step * 2 * quote.price_tick: #技术形态满足止盈条件
if position.pos_long > 0 and position.pos_short == 0:#有多单且无空单(未锁仓)
return 'duoping'
elif Kai_Log.iloc[-1].price - quote.bid_price1 >= grid_step * quote.price_tick: #技术形态满足止损条件
if position.pos_long > 0 and position.pos_short == 0:#有多单且无空单(未锁仓)
return 'duoping'
if Kai_Log.iloc[-1].price - quote.ask_price1 >= grid_step * 2 * quote.price_tick: #技术形态满足止盈条件
if position.pos_short > 0 and position.pos_long == 0:#有空单且无多单(未锁仓)
return 'kongping'
elif quote.ask_price1 - Kai_Log.iloc[-1].price >= grid_step * quote.price_tick: #技术形态满足止损条件
if position.pos_short > 0 and position.pos_long == 0:#有空单且无多单(未锁仓)
return 'kongping'
except IndexError:
return #本地无开仓记录,等待开仓,若已有持仓且大于Lots
def Shoushu(Ping_Log=[],Lot=1):
try:
if Ping_Log.iloc[-1].lirun > 0:
Lots = Lot
elif Ping_Log.iloc[-2].lirun > 0:
Lots = Lot
else :
Lots = Ping_Log.iloc[-1].volume + Ping_Log.iloc[-2].volume
except IndexError:
Lots = Lot #没有平仓记录或只有一个亏损平仓记录
'''try:if Ping_Log.iloc[-1].lirun > 0:Lots = Lotelif Ping_Log.iloc[-1].lirun < 0:Lots = Ping_Log.iloc[-1].volume * 2except IndexError:Lots = Lot #没有平仓记录'''
if Lots >= 233 : Lots = 233 #限定最大开仓手数
#if Lots >= 1024 : Lots = 1024
return Lots
async def Kaiping(api='',symbol='',Kai_Log=[],Ping_Log=[],fk='',fp=''):
quote = api.get_quote(symbol)
position = api.get_position(symbol)
kai = ''
if position.pos_long + position.pos_short == 0:#无持仓
jia_kai = 'ADD'
price_kai = 0.0 #平仓时开仓价和手数清零
shoushu_kai = 0
else :#有持仓
try : #本地读取成交记录,程序中断可接着运行
jia_kai = Kai_Log.iloc[-1].jia_kai #
price_kai = Kai_Log.iloc[-1].price #平仓时开仓价和手数清零
shoushu_kai = Kai_Log.iloc[-1].volume
except IndexError: #本地无数据
raise('本地无开仓记录但有持仓,请先清空品种'+symbol+'持仓')
try :
jia_ping = Ping_Log.iloc[-1].jia_ping #
price_ping = Ping_Log.iloc[-1].price #开仓时平仓价和手数清零
shoushu_ping = Ping_Log.iloc[-1].volume
except IndexError:#无数据
jia_ping = 'ADD' #
price_ping = 0.0 #开仓时平仓价和手数清零
shoushu_ping = 0
async with api.register_update_notify([quote,position]) as update_chan:
async for _ in update_chan:
Lots = Shoushu(Ping_Log=Ping_Log,Lot=Lot)
fangxiang = Cta(api=api,quote=quote,position=position,Lots=Lots,grid_step=grid_step,Kai_Log=Kai_Log)
if fangxiang == 'duokai' :
kai_cang=api.insert_order(symbol=symbol, direction='BUY', offset='OPEN', volume=Lots-position.pos_long, limit_price=quote.ask_price1,advanced='FAK')
kai = 'open'
elif fangxiang == 'duoping' :
if position.pos_long_today == 0 : #只有昨仓
ping_zuo=api.insert_order(symbol=symbol, direction='SELL', offset='CLOSE', volume=position.pos_long_his, limit_price=quote.bid_price1,advanced='FAK')
elif position.pos_long_his == 0 : #只有今仓
ping_jin=api.insert_order(symbol=symbol, direction='SELL', offset='CLOSETODAY', volume=position.pos_long_today, limit_price=quote.bid_price1,advanced='FAK')
else :
ping_zuo=api.insert_order(symbol=symbol, direction='SELL', offset='CLOSE', volume=position.pos_long_his, limit_price=quote.bid_price1,advanced='FAK')
ping_jin=api.insert_order(symbol=symbol, direction='SELL', offset='CLOSETODAY', volume=position.pos_long_today, limit_price=quote.bid_price1,advanced='FAK')
kai = 'close'
elif fangxiang == 'kongkai' :
kai_cang=api.insert_order(symbol=symbol, direction='SELL', offset='OPEN', volume=Lots-position.pos_short, limit_price=quote.bid_price1,advanced='FAK')
kai = 'open'
elif fangxiang == 'kongping' :
if position.pos_short_today == 0 : #只有昨仓
ping_zuo=api.insert_order(symbol=symbol, direction='BUY', offset='CLOSE', volume=position.pos_short_his, limit_price=quote.ask_price1,advanced='FAK')
elif position.pos_short_his == 0 : #只有今仓
ping_jin=api.insert_order(symbol=symbol, direction='BUY', offset='CLOSETODAY', volume=position.pos_short_today, limit_price=quote.ask_price1,advanced='FAK')
else :
ping_zuo=api.insert_order(symbol=symbol, direction='BUY', offset='CLOSE', volume=position.pos_short_his, limit_price=quote.ask_price1,advanced='FAK')
ping_jin=api.insert_order(symbol=symbol, direction='BUY', offset='CLOSETODAY', volume=position.pos_short_today, limit_price=quote.ask_price1,advanced='FAK')
kai = 'close'
if kai == 'open' :#开仓时平仓价和手数清零
kai = ''
while kai_cang.status != "FINISHED":
await asyncio.sleep(0.01)
if kai_cang.volume_orign > kai_cang.volume_left : #有成交
jia_ping = 'ADD'
price_ping = 0.0
shoushu_ping = 0
price_kai = (price_kai*shoushu_kai + kai_cang.trade_price*(kai_cang.volume_orign-kai_cang.volume_left))/(shoushu_kai + kai_cang.volume_orign-kai_cang.volume_left)
shoushu_kai = shoushu_kai + kai_cang.volume_orign-kai_cang.volume_left #先按原手数算均价,再算新手数
direction = kai_cang.direction
t = kai_cang.insert_date_time
dt = time_to_str(t)
if jia_kai == 'ALTER':
tr_dic = {'time':t,'symbol':symbol,'volume':shoushu_kai,'price':price_kai,'direction':direction,'datetime':dt,'jia_kai':jia_kai}
datas = pd.DataFrame(tr_dic,index=[0])
Kai_Log.iloc[-1] = datas.iloc[0]
elif jia_kai == 'ADD':
jia_kai = 'ALTER'
tr_dic = {'time':t,'symbol':symbol,'volume':shoushu_kai,'price':price_kai,'direction':direction,'datetime':dt,'jia_kai':jia_kai}
datas = pd.DataFrame(tr_dic,index=[0])
Kai_Log = Kai_Log.append(datas) #新一笔成交追加
Kai_Log.to_csv(fk,index=False)
elif kai == 'close':#平仓时开仓价和手数清零
kai = ''
tr = False
try :
while ping_zuo.status != "FINISHED":
await asyncio.sleep(0.01)
if ping_zuo.volume_orign > ping_zuo.volume_left :
price_ping = (price_ping*shoushu_ping + ping_zuo.trade_price*(ping_zuo.volume_orign-ping_zuo.volume_left))/(shoushu_ping+ping_zuo.volume_orign-ping_zuo.volume_left)
shoushu_ping = shoushu_ping + ping_zuo.volume_orign-ping_zuo.volume_left
direction = ping_zuo.direction
t = ping_zuo.insert_date_time
dt = time_to_str(t)
tr = True #有成交
except NameError:
pass
try :
while ping_jin.status != "FINISHED":
await asyncio.sleep(0.01)
if ping_jin.volume_orign > ping_jin.volume_left :
price_ping = (price_ping*shoushu_ping + ping_jin.trade_price*(ping_jin.volume_orign-ping_jin.volume_left))/(shoushu_ping+ping_jin.volume_orign-ping_jin.volume_left)
shoushu_ping = shoushu_ping + ping_jin.volume_orign-ping_jin.volume_left
direction = ping_jin.direction
t = ping_jin.insert_date_time
dt = time_to_str(t)
tr = True #有成交
except NameError:
pass
if tr :
jia_kai = 'ADD'
price_kai = 0.0
shoushu_kai = 0
if fangxiang == 'duoping' : lirun = price_ping - Kai_Log.iloc[-1].price
elif fangxiang == 'kongping' : lirun = Kai_Log.iloc[-1].price - price_ping
if jia_ping == 'ALTER':
tr_dic = {'time':t,'symbol':symbol,'volume':shoushu_ping,'price':price_ping,'direction':direction,'lirun':lirun,'datetime':dt,'jia_ping':jia_ping}
datas = pd.DataFrame(tr_dic,index=[0])
Ping_Log.iloc[-1] = datas.iloc[0]
elif jia_ping == 'ADD' :
jia_ping = 'ALTER'
tr_dic = {'time':t,'symbol':symbol,'volume':shoushu_ping,'price':price_ping,'direction':direction,'lirun':lirun,'datetime':dt,'jia_ping':jia_ping}
datas = pd.DataFrame(tr_dic,index=[0])
Ping_Log = Ping_Log.append(datas)
Ping_Log.to_csv(fp,index=False) #如果先前未止损完,再次达到开仓条件则继续补仓恢复
api.create_task(Kaiping(api=api,symbol=vt,Kai_Log=Kai_Log,Ping_Log=Ping_Log,fk=fk,fp=fp))
while True:
api.wait_update() #