import time
|
import datetime
|
import decimal
|
import logging
|
import threading
|
from gm.api import *
|
|
import basic_methods
|
|
# 赋值账户ID
|
account_id = 'aaee2221-839c-11ee-a7cd-00163e022aa6'
|
# 设置token
|
set_token("6c1dbe95191fb77cced9d805cb9c853805551ddb")
|
|
# 为当日新增加持仓代码创建一个初始集合
|
global_addition_position_symbols = set()
|
|
# 初始化数据的全局化函数
|
def init_data():
|
logging.info("初始化数据开始")
|
global today_date, Pre_trading_day, Double_Pre_trading_day, Next_trading_day
|
# 设置token
|
set_token("6c1dbe95191fb77cced9d805cb9c853805551ddb")
|
# 今日时间初始化
|
now = datetime.datetime.now() # 获取本机时间
|
print(f"本机时间::{now}")
|
today_date = now.strftime('%Y-%m-%d') # 获取今日日期参数
|
print(f"今日日期{today_date}")
|
Pre_trading_day = get_previous_trading_date(exchange='SHSE', date=today_date) # 获取前一个交易日
|
Double_Pre_trading_day = get_previous_trading_date(exchange='SHSE', date=Pre_trading_day) # 获取上上一个交易日
|
Next_trading_day = get_next_trading_date(exchange='SHSE', date=today_date) # 获取下一个交易日
|
print(f"前一个交易日{Pre_trading_day}")
|
print(f"上上一个交易日{Double_Pre_trading_day}")
|
print(f"下一个交易日{Next_trading_day}")
|
|
|
|
|
# 给全局context 赋初始值 下文有用
|
global_context = None
|
# 第一步:初始化context函数,数据订阅
|
def init(context):
|
global global_context # 在函数内部的一些初始化函数就把他直接全局化了
|
global_context = context
|
init_data()
|
# print(f"global_context==={global_context.account(account_id = account_id).positions()}")
|
|
# 初始化仓位管理,主线逻辑才会运行
|
# position_management()
|
|
# 初始化get_subscribe_data方法函数,下单买逻辑才会运行中。。。【核心主线程,随时考虑其启动顺序】>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
|
# threading.Thread(target=lambda: get_subscribe_data(), daemon=True).start()
|
|
subscribe(symbols='SZSE.000333', frequency='tick', count=5, unsubscribe_previous=True)
|
# time.sleep(5)
|
# print(f"test===={test}")
|
|
# account_finance = context.account(account_id = 'aaee2221-839c-11ee-a7cd-00163e022aa6').cash
|
# print(f"账户对象列表==={account_finance}")
|
# print(f"资金初始时间==={account_finance.created_at}")
|
# print(f"资金变更时间==={account_finance.updated_at}")
|
|
# print(f"总资金==={account_finance.nav}")
|
# print(f"可用资金==={account_finance.available}")
|
# print(f"持仓占用资金==={account_finance.frozen}")
|
# print(f"冻结资金==={account_finance.order_frozen}")
|
# print(f"盈亏===={account_finance.pnl}")
|
# print(f"持仓浮动盈亏==={account_finance.fpnl}")
|
# print(f"持仓市值==={account_finance.market_value}")
|
# print(f"资金余额==={account_finance.balance}")
|
# print(f"累计出入金额==={account_finance.cum_inout}")
|
# print(f"累计交易金额==={account_finance.cum_trade}")
|
# print(f"累计盈亏==={account_finance.cum_pnl}")
|
# print(f"累计委托==={account_finance.cum_commission}")
|
# print(f"最后一笔交易==={account_finance.last_trade}")
|
# print(f"最后一笔委托==={account_finance.last_commission}")
|
# print(f"最后一笔出入金额==={account_finance.last_inout}")
|
# print(f"允许保释??==={account_finance.enable_bail}")
|
# print(f"纯浮动盈亏??==={account_finance.fpnl_diluted}")
|
# 保持开启 , 为了实现永不完成这堆初始化线程 ,因为一旦完成,整体获取current数据变慢为15S+
|
while True: # 不得擅动!!!
|
time.sleep(10)
|
|
|
|
|
# 获取tick数据
|
def on_tick(context, tick):
|
print(f"tick==={tick}")
|
pass
|
print(f"tick==={tick}")
|
__process(tick)
|
|
|
# 初始化 subscribe_datas 数据
|
# subscribe_datas = None
|
# 获取subscribe_data数据 。
|
def get_subscribe_data():
|
set_token("6c1dbe95191fb77cced9d805cb9c853805551ddb")
|
logging.info(f"get_subscribe_data进入")
|
while True:
|
# logging.info(f"运行中...")
|
# print(f"运行中...")
|
# 获取当前时间
|
# now = time.time()
|
try:
|
now_start = time.time()
|
# print(f"now_start=={now_start}")
|
subscribe_datas = subscribe('SHSE.603839,SHSE.6003839,SHSE.600805', frequency='tick', count=1, unsubscribe_previous=False)
|
now_end = time.time()
|
# print(f"now_end=={now_end}")
|
now_start_to_end = now_end - now_start
|
for subscribe_data in subscribe_datas:
|
# print(f"subscribe_data==={subscribe_data}")
|
try:
|
__process(subscribe_data)
|
except Exception as e:
|
logging.exception(e)
|
# basic_info = basic_info_symbols_dict.get(subscribe_data['symbol'])
|
print("异常:", subscribe_data)
|
|
print(f"now_start_to_end==={round(now_start_to_end, 2)} 秒")
|
except Exception as e:
|
logging.exception(e)
|
|
|
def __process(subscribe_data):
|
symbol = subscribe_data['symbol']
|
print(f"symbol===={symbol}")
|
|
# 为持仓代码创建一个初始集合
|
global_position_symbols = set()
|
|
# 仓位管理策略(核心逻辑流程:先卖后买,止盈止损)
|
# 如果有持仓,那么就看开盘价是否为涨停价(是则不卖,炸板则卖),开盘价是否为当日涨幅>5%(是则不卖,走跌则卖),否则开盘走跌振幅大于1.5%则卖。
|
def position_management():
|
# 仓位管理及查询函数
|
def position_query():
|
Account_positions = global_context.account(account_id = account_id).positions() # 查询当前账户全部持仓
|
# print(f"Account_positions==={Account_positions}")
|
for d in Account_positions:
|
global_position_symbols.add(d['symbol'])
|
print(
|
f"仓位管理前持仓===============================================================【{global_position_symbols}】")
|
print(
|
f"仓位管理前持仓数量===============================================================【{len(global_position_symbols)}】")
|
for d in Account_positions:
|
symbol = d['symbol']
|
symbol_code = symbol.split('.')[1] # 将symbol转为纯数字编号
|
available_now = d['available_now']
|
# price = d['price'] #当前行情价,,,非最新价,没有实际意义不要用!!!
|
vwap = d['vwap']
|
volume = d['volume']
|
volume_today = d['volume_today']
|
volume_yesterday = volume - volume_today
|
new_price = current(symbol, fields='price')[0]['price']
|
# print(symbol,available_now, price, vwap)
|
instruments = get_instruments(symbols=symbol, exchanges=None, sec_types=None, names=None,
|
fields="symbol,sec_name,pre_close,upper_limit",
|
df=False)
|
if available_now != 0: # 如果可用资金不等于0 昨日收盘价获取到非0值时(不知名原因导致有些票会获取到0值导致后续公式报错,阻止intraday_growth函数正常运行)
|
# print(f"持仓可用股{symbol}")
|
history_data = history(symbol=symbol, frequency='1d', start_time=Double_Pre_trading_day,
|
end_time=Pre_trading_day, fields='open, close, low, high, eob',
|
adjust=ADJUST_PREV, df=False)
|
# print(f"len(history_data)==={len(history_data)}history_data========={history_data} ")
|
print(
|
f"【{instruments[0]['sec_name']}】上个交易日 最高{history_data[1]['high']},收盘{history_data[1]['close']}")
|
# 获取昨日涨停价 目前函数中的pre_close应该传入前天的收盘价,而非昨天的
|
yesterday_limit_up_price = basic_methods.limit_up_price(history_data[0]['close'])
|
today_limit_up_price = basic_methods.limit_up_price(history_data[1]['close'])
|
# print(f'涨停价算对了吗?{yesterday_top_price}')
|
if history_data[0]['close'] == 0:
|
print(f"{symbol}的修改后的history_data的昨日收盘价也为000000000000000000")
|
today_growth = basic_methods.intraday_growth(new_price, history_data[1]['close'])
|
# 如果持仓股 昨日未涨停 并且 今日最新价不等于今日涨停价 并且 今日涨幅小于3%
|
if abs(yesterday_limit_up_price - float(decimal.Decimal(history_data[1]['close']))) < 0.001:
|
print(
|
f"昨日涨停 不卖!【{instruments[0]['sec_name']}】它的今日涨幅为{today_growth}。它的最新价:{new_price},它的昨日收盘价:{history_data[1]['close']},它的昨日涨停价{yesterday_limit_up_price}")
|
elif today_limit_up_price == new_price:
|
print(
|
f"今日涨停 不卖!【{instruments[0]['sec_name']}】它的今日涨幅为{today_growth}。它的最新价:{new_price},它的昨日收盘价:{history_data[1]['close']},它的昨日涨停价{yesterday_limit_up_price}")
|
elif today_growth > 2:
|
print(
|
f"开盘涨幅大于2% 不卖!【{instruments[0]['sec_name']}】它的今日涨幅为{today_growth}。它的最新价:{new_price},它的昨日收盘价:{history_data[1]['close']},它的昨日涨停价{yesterday_limit_up_price}")
|
else:
|
print(f"卖前持仓数量{len(global_position_symbols)}")
|
sell_order(symbol, volume_yesterday, instruments[0]['sec_name'])
|
if history_data[1]['close'] == history_data[1]['high']:
|
print(f"昨日涨停可能判断出错!!!{instruments[0]['sec_name']}")
|
print(
|
f"持仓可用今日开盘涨幅【{instruments[0]['sec_name']}】,它的今日涨幅为{today_growth}。它的最新价:{new_price},它的昨日收盘价:{history_data[1]['close']},它的昨日涨停价{yesterday_limit_up_price},它的前日收盘价:{history_data[0]['close']}")
|
# print(f"持仓股 历史数据{history_data}")
|
print(f"--------------------------------------------------------------------------------------[分割线]")
|
if available_now == 0: # 如果可用资金等于0,又在持仓中,就是今天新增持仓
|
global_addition_position_symbols.add(symbol)
|
print(f"今日新增持仓数量==【{len(global_addition_position_symbols)}】")
|
|
# 仓位管理时间定时执行函数 (默认设定为9:31)
|
def check_time():
|
# now = global_context.now # 获取当前时间
|
now = datetime.datetime.now()
|
hour = now.hour
|
minute = now.minute
|
if hour > 9 or (hour == 9 and minute >= 31):
|
print(f"开盘时间到了:{now}")
|
position_query()
|
return False # 返回False,表示结束循环
|
else:
|
return True # 返回True,表示继续循环
|
|
# 使用while循环和check_time函数检查时间,并设置固定的时间间隔
|
while check_time():
|
time.sleep(1)
|
|
# 下单卖出函数(以手数卖)
|
def sell_order(symbol, volume_yesterday, sec_name):
|
set_account_id('aaee2221-839c-11ee-a7cd-00163e022aa6')
|
print(f"命令卖掉【{sec_name}】")
|
order_volume(symbol=symbol, volume=volume_yesterday, side=OrderSide_Sell, order_type=OrderType_Market,
|
position_effect=PositionEffect_Close)
|
print(f"卖票结果提示:下单成功:【{sec_name}】")
|
# 卖票后移除持仓代码集合
|
# global_position_symbols.remove(symbol)
|
# print(f"卖后持仓数量{len(global_position_symbols)}")
|
|
|
# 下单买入函数(以价钱买)
|
def buy_order(current_data,ratio_value):
|
now = datetime.datetime.now()
|
hour = now.hour
|
minute = now.minute
|
if hour > 9 or (hour == 9 and minute >= 30):
|
set_account_id('aaee2221-839c-11ee-a7cd-00163e022aa6')
|
result = order_value(symbol=current_data['symbol'], value=ratio_value, side=OrderSide_Buy, order_type=OrderType_Market,
|
position_effect=PositionEffect_Open)
|
print(f"result===={result}")
|
print('下单成功', current_data['symbol'])
|
# global_position_symbols.add(current_data['symbol'])
|
# global_addition_position_symbols.add(current_data['symbol'])
|
# print(f"当前持仓数量:::{len(global_position_symbols)}")
|
# print(f"今日新增持仓数量:::{len(global_addition_position_symbols)}")
|
else:
|
print('未到开盘时间不允许下单', current_data['symbol'])
|
|
|
# 模式选择
|
if __name__ == '__main__':
|
'''
|
strategy_id策略ID,由系统生成
|
filename文件名,请与本文件名保持一致
|
mode实时模式:MODE_LIVE回测模式:MODE_BACKTEST
|
token绑定计算机的ID,可在系统设置-密钥管理中生成
|
backtest_start_time回测开始时间
|
backtest_end_time回测结束时间
|
backtest_adjust股票复权方式不复权:ADJUST_NONE前复权:ADJUST_PREV后复权:ADJUST_POST
|
backtest_initial_cash回测初始资金
|
backtest_commission_ratio回测佣金比例
|
backtest_slippage_ratio回测滑点比例
|
'''
|
run(
|
strategy_id='507bb60a-a919-11ee-b6ad-0ae0afd621cd',
|
filename='position_management.py',
|
mode=MODE_LIVE, # 实时模式
|
# mode=MODE_BACKTEST, #回测模式
|
token='6c1dbe95191fb77cced9d805cb9c853805551ddb',
|
backtest_start_time='2024-06-11 09:30:00',
|
backtest_end_time='2024-06-11 10:00:00',
|
backtest_adjust=ADJUST_PREV,
|
backtest_initial_cash=500000, # 实时模式测试状态下帐户金额由掘金客户端所连接的账户绑定,所以在客户端去充值就可以了(虚拟充值)
|
backtest_commission_ratio=0.0001,
|
backtest_slippage_ratio=0.0001)
|