Commit 3de16f67 by 周帅

initial commit

parents
from KYBT.BT import engine2
from KYBT.util.kySDK import *
import logging
logger = logging.getLogger(__name__)
logger.setLevel(logging.CRITICAL)
import time
from KYBT.BT.evaluator import evaluator
# ['600000','000002']
#用户输入
# "stockPicker":{'pick':True,'dateList':['2014-07-01','2014-07-05']},
# "stockPicker":{'pick':False,'dateList':None},
inputJson = \
{ "strategyID":'01',
"stockPicker":{'pick':False,'dateList':None},
"criteriaDict" : {'存货周转率':['最近一年',None,None],'主营收入同比':['最近一年',None,None],'流动资产':['最近一期',None,None]},
"portforlio": 'ZZ500',
"benchmark": 'ZZ500',
"money": 5000000,
"startDate": '2013-04-01',
"endDate": '2018-04-12',
"turnover": 10,
"tradingHabit": "OpenPrice",
"status":0
}
inputJson = \
{
"strategyID":'2',
"stockPicker":{"pick":False,"dateList":["2017-05-05"]},
"criteriaDict" : {"存货周转率":["最近一年",None,None],"主营收入同比":["最近一年",None,None],"流动资产":["最近一期",None,None]},
"portforlio": "SZ50",
"benchmark": "ZZ500",
"money": 5000000,
"startDate": "2017-04-06",
"endDate": "2018-04-12",
"turnover": 10,
"tradingHabit": "OpenPrice",
"status":0
}
starttime = time.time()
myBT = engine2.Engine(inputJson) #initialize engine
if myBT.stockPicker['pick'] == False:
myBT.backTesting()
evaluator(myBT.strategyID,myBT.BTRecords,myBT.IndexRecords,plot = False)
elif myBT.stockPicker['pick'] == True:
for day in myBT.stockPicker['dateList']:
myBT.stockPicking(day) #是选的哪一天的???
endtime = time.time()
print('it takes %0.2f seconds to finish BT'%(endtime-starttime))
# -*- coding: utf-8 -*-
"""
Created on 20180330
@author: zhoushuai
"""
'''
列名 中文名 别名 类型 单位 默认值 是否可空 说明
SecuCode 证券代码 varchar(12) FALSE
SecuAbbr 证券名称 nvarchar(40) TRUE
EndDate 报告日期 datetime FALSE
TotalAssets 总资产 numeric(18,4) 元 TRUE
AdvanceReceipts 预收款项 numeric(18,4) TRUE
EquityBelongedToPC 净资产 numeric(18,4) TRUE
PublDate 公告日期 datetime TRUE
TotalLiability 总负债 numeric(18,4) 元 TRUE
TotalCurrentLiability 流动负债 numeric(18,4) 元 TRUE
TotalCurrentAssets 流动资产 numeric(18,4) 元 TRUE
CashOrDepositInCentralBank 现金及存放中央银行款项 numeric(18,4) 元 TRUE
NetProfit 净利润 numeric(18,4) 元 TRUE
NetOperateCashFlow 经营活动产生的现金流 numeric(18,4) 元 TRUE
'''
import pandas as pd
import pyodbc
import ky
import datetime
sdk = ky.Api("http://data-api.kuaiyutech.com/api.rpc")
import logging
logger = logging.getLogger(__name__)
try:
from ..BT.financialIndicator import FinancialIndicator
logger.setLevel(logging.CRITICAL)
from ..util.kySDK import *
from .apiParent import ApiParent
except:
import sys
sys.path.insert(0, 'D:/Project/YM/BackTesting Frame/KYBT/BT')
sys.path.insert(0, 'D:/Project/YM/BackTesting Frame/KYBT/util')
print(sys.path)
from financialIndicator import FinancialIndicator
from kySDK import *
from apiParent import ApiParent
logger.setLevel(logging.WARNING)
class API(ApiParent):
def __init__(self,DSN):
super().__init__(DSN)
@staticmethod
def pdToValueObjectList(panda):
financialIndicatorList = []
for index,row in panda.iterrows():
oneFinancialIndicator = FinancialIndicator()
oneFinancialIndicator.SecuCode = row['SecuCode']
oneFinancialIndicator.SecuAbbr = row['SecuAbbr']
oneFinancialIndicator.EndDate = row['EndDate']
oneFinancialIndicator.AdvanceReceipts = float(row['AdvanceReceipts'])
oneFinancialIndicator.TotalAssets = float(row['TotalAssets'])
oneFinancialIndicator.EquityBelongedToPC = float(row['EquityBelongedToPC'])
oneFinancialIndicator.TotalLiability = float(row['TotalLiability'])
oneFinancialIndicator.TotalCurrentAssets = float(row['TotalCurrentAssets'])
oneFinancialIndicator.TotalCurrentLiability = float(row['TotalCurrentLiability'])
oneFinancialIndicator.CashOrDepositInCentralBank = float(row['CashOrDepositInCentralBank'])
oneFinancialIndicator.NetProfit = float(row['NetProfit'])
oneFinancialIndicator.NetOperateCashFlow = float(row['NetOperateCashFlow'])
financialIndicatorList.append(oneFinancialIndicator)
return financialIndicatorList
def getFinancialIndicator(self,startDate,endDate,stockList):
'''
CY_ValueDaily_Quote is daily data
stock: list, ## [600000,000002]
startDate: str, '2018-01-10'
endDate: str,'2018-03-03'
'''
#
itemString = '''
SecuCode,
SecuAbbr,
EndDate,
AdvanceReceipts,
TotalAssets,
EquityBelongedToPC,
TotalLiability,
TotalCurrentAssets,
TotalCurrentLiability,
CashOrDepositInCentralBank,
NetProfit,
NetOperateCashFlow
'''
#
if len(stockList) == 1:
stockList = '(%s)'%stockList[0]
else:
stockList = tuple(stockList)
#
query = '''
SELECT
%s
FROM
[dbo].[CY_FinacialIndicators_RP]
where
EndDate <= '%s 00:00:00:000'
AND
EndDate >= '%s 00:00:00:000'
AND SecuCode IN %s
ORDER BY
SecuAbbr DESC,
EndDate Asc
'''%(itemString,endDate,startDate,stockList)
#
#print(query)
self.cursor.execute(query)
raw = self.cursor.fetchall()
logger.info('raw :',raw)
if not raw:
logger.critical( 'CY_FinacialIndicators_RP value has no data, return None')
return None
financialIndicatorPD = self.pandaData(raw,itemString)
financialIndicatorPD.fillna(value=0, inplace=True) # to replace None with value 0
return self.pdToValueObjectList(financialIndicatorPD)
if __name__ == '__main__':
logger.warn(__file__)
myAPI = API('BTEMmidd2')
myAPI.init()
y = myAPI.getFinancialIndicator('2017-01-05','2017-06-06',['600000','000002'])
print(y)
\ No newline at end of file
# -*- coding: utf-8 -*-
"""
Created on 20180309
@author: zhoushuai
"""
'''
估值指标 (EMMIDD2.dbo.CY_ValueDaily_Quote)
PE(TTM) 最新一期/最近一年/最近三年 小于10 10~15 15~20 20~40 40~60 60~80 80~100 大于100 小于0
PB 最新一期/最近一年/最近三年 小于1 1~1.5 1.5~2 2~2.5 2.5~3.5 3.5~5 大于5
PS 最新一期/最近一年/最近三年 大于10 10~5 5~3 3~1 1~0 小于0
PE预测 最新一期/最近一年/最近三年 小于10 10~15 15~20 20~40 40~60 60~80 80~100 大于100 小于0
股息率 最新一期/最近一年/最近三年 大于5% 5%~3% 3%~1% 小于1%
市值指标 (EMMIDD2.dbo.CY_ValueDaily_Quote)
总市值 最新一期/最近一年/最近三年 巨盘 大盘 中盘 小盘 微盘
流通市值 最新一期/最近一年/最近三年 巨盘 大盘 中盘 小盘 微盘
有效流通市值 最新一期/最近一年/最近三年 巨盘 大盘 中盘 小盘 微盘
大于1000亿 500~1000亿 200~500亿 50~200亿 小于50亿
最新一期:这个季度和上个季度相比
最近一年:今年和去年相比
最近三年:今年和前年相比
watch this out
Tradedate ReportedPeriod
600000 浦发银行 2017-12-27 00:00:00.000 2017-09-30 00:00:00.000 1.45000000
600000 浦发银行 2017-12-28 00:00:00.000 2017-09-30 00:00:00.000 1.45000000
600000 浦发银行 2017-12-29 00:00:00.000 2017-09-30 00:00:00.000 1.45000000
600000 浦发银行 2018-01-02 00:00:00.000 2017-12-31 00:00:00.000 1.84000000
600000 浦发银行 2018-01-03 00:00:00.000 2017-12-31 00:00:00.000 1.84000000
600000 浦发银行 2018-01-04 00:00:00.000 2017-12-31 00:00:00.000 1.84000000
2018-01-02 is the most recently updated date, get the data of this day,
方大炭素10-30号公布财报,这一天是财报的
TradeDate ReportedPeriod PE1
600516 方大炭素 2017-10-26 00:00:00.000 2017-06-30 00:00:00.000 .23024118 106.1764 59.8503 7.5299
600516 方大炭素 2017-10-27 00:00:00.000 2017-06-30 00:00:00.000 1.16400000 103.4796 11.8980 7.3386
600516 方大炭素 2017-10-30 00:00:00.000 2017-09-30 00:00:00.000 1.16400000 24.9367 18.5979 6.0679
600516 方大炭素 2017-10-31 00:00:00.000 2017-09-30 00:00:00.000 1.16400000 25.9524 19.3553 6.3150
600516 方大炭素 2017-11-01 00:00:00.000 2017-09-30 00:00:00.000 1.16400000 25.8366 19.2690 6.2868
原来9-30号是最新的一期,那我就只要用ReportedPeried的第一个03-31,06-30,09-30,12-31
PE(TTM)最近三年小于10
简单的来处理,就取三个时间点就好了,因为净利润一年只可能知道4次,那么准确的PE其实也只有4个点的值而已。
因为不可能知道企业每一天的净利,所以平时滚动的PE其实也是大家的不准确估计吧
'''
import pandas as pd
import pyodbc
import ky
import datetime
sdk = ky.Api("http://data-api.kuaiyutech.com/api.rpc")
import logging
logger = logging.getLogger(__name__)
try:
from ..BT.value import Value
from ..BT.index import Index
logger.setLevel(logging.CRITICAL)
from ..util.kySDK import *
from .apiParent import ApiParent
except:
import sys
sys.path.insert(0, 'D:/Project/YM/BackTesting Frame/KYBT/BT')
sys.path.insert(0, 'D:/Project/YM/BackTesting Frame/KYBT/util')
print(sys.path)
from value import Value
from index import Index
from kySDK import *
from apiParent import ApiParent
logger.setLevel(logging.WARNING)
class API(ApiParent):
def __init__(self,DSN):
super().__init__(DSN)
@staticmethod
def pdToValueObjectList(panda):
valueList = []
for index,row in panda.iterrows():
oneValue = Value()
oneValue.SecuCode = row['SecuCode']
oneValue.SecuAbbr = row['SecuAbbr']
oneValue.TradeDate = row['TradeDate']
oneValue.ReportPeriod = row['ReportPeriod']
oneValue.PE1 = float(row['PE1'])
oneValue.PB = float(row['PB'])
oneValue.PS = float(row['PS'])
oneValue.ClosePrice = float(row['ClosePrice'])
oneValue.RMBShares = float(row['RMBShares'])
oneValue.ValidShares = float(row['ValidShares'])
oneValue.MarketValue = float(row['MarketValue'])
valueList.append(oneValue)
return valueList
def getSpotValue(self,startDate,endDate,stockList):
'''
CY_ValueDaily_Quote is daily data
stock: list, ## [600000,000002]
startDate: str, '2018-01-10'
endDate: str,'2018-03-03'
'''
#
itemString = '''
SecuCode,
SecuAbbr,
TradeDate,
ReportPeriod,
EPS,
PE1,
PE2,
PB,
PS,
Dividend1Y,
MarketValue,
ClosePrice,
ValidShares,
RMBShares,
Bshares'''
#
if len(stockList) == 1:
stockList = '(%s)'%stockList[0]
else:
stockList = tuple(stockList)
#
query = '''
SELECT
%s
FROM
[dbo].[CY_ValueDaily_Quote]
where
TradeDate <= '%s 00:00:00:000'
AND
TradeDate >= '%s 00:00:00:000'
AND SecuCode IN %s
ORDER BY
SecuAbbr DESC,
TradeDate Asc
'''%(itemString,endDate,startDate,stockList)
#
#print(query)
self.cursor.execute(query)
raw = self.cursor.fetchall()
logger.info('raw :',raw)
if not raw:
logger.critical( 'CY_ValueDaily_Quote value has no data, return None')
return None
valuePD = self.pandaData(raw,itemString)
valuePD.fillna(value=0, inplace=True) # to replace None with value 0
return self.pdToValueObjectList(valuePD)
if __name__ == '__main__':
logger.warn(__file__)
myAPI = API('BTEMmidd2')
myAPI.init()
y = myAPI.getSpotValue('2017-05-05','2017-06-06',['600000'])
print(y)
\ No newline at end of file
import pyodbc
import logging
import pandas as pd
logger = logging.getLogger(__name__)
logger.setLevel(logging.CRITICAL)
import functools
import warnings
import datetime
import sys
import logging
logger = logging.getLogger(__name__)
try:
from ..emClasses import *
logger.setLevel(logging.CRITICAL)
from ..util.kySDK import *
from ..dataTable import DataTable
except:
import sys
#D:\Project\益盟\回测框架\KYBT\BT
sys.path.insert(0, 'D:/Project/YM/BackTesting Frame/KYBT/BT')
sys.path.insert(0, 'D:/Project/YM/BackTesting Frame/KYBT/util')
#print(sys.path)
from emClasses import *
from dataTable import DataTable
from kySDK import *
logger.setLevel(logging.WARNING)
class ApiParent():
'''
parent of all apis
myAPI = APIPARENT('BTMarketTrade')
myAPI.init()
or
myAPI = APIPARENT('BTMarketTrade')
with myAPI():
do something
'''
# '2009以后不考虑,数据好像有问题'
FinancialReportDate = {'Mar':'03-31','Jun':'06-30','Sep':'09-30','Dec':'12-31'}
def __init__(self):
self.DSN = 'BTMarketTrade'
def init(self):
try:
self.cnxn = pyodbc.connect(DSN = self.DSN,UID="SLReadOnly",PWD="gBNfZ9zPCzVD")
self.cursor = self.cnxn.cursor()
except:
raise 'connection failed'
def __enter__(self): # with
self.init()
def __exit__(self,*args): # with
self.cnxn.close()
self.cnxn = None
@staticmethod
def getNeededTable(inputJson):
tableList = ["EM_QUOTE_STOCK_DAILY"] #
for key in inputJson['criteriaDict']:
if key in DataTable:
tableList.append(DataTable[key][1]) # 把需要用到的数据表加进去
else:
raise ValueError('%s is not in the available table'%key)
#print('需要用到的数据表: ', tableList)
return tableList
def pdToObjList(self,panda,objName,itemID):
'''
dictObj: dict('date':[objList],'date':[objList],...)
for example:
{'2017-01-26': [<stock.Stock object at 0x0857FA70>, <stock.Stock object at 0x0857FB30>],
'2017-01-25': [<stock.Stock object at 0x0857FB10>, <stock.Stock object at 0x0857FAB0>],
'''
if objName in ['Stock','ValueDaily','Index']:
date = 'TradeDate'
else:
date = 'EndDate'
itemList = self.modifyItemString(itemID)
dateList = [str(x)[:10] for x in set(panda[date])]
dateList.sort(reverse = True)
dictObj = dict()
for oneDate in dateList:
pandaSection = panda[panda[date] == oneDate]
objList = []
for index,row in pandaSection.iterrows():
exec("oneObj = %s()"%objName)
for item in itemList:
if item in ['TradeDate','EndDate']:
exec("oneObj.%s = str(row['%s'])[:10]"%(item,item))
elif item in ['SecuCode','SecuAbbr','SecuMarket','PublDate','TradeStatus']:
exec("oneObj.%s = str(row['%s'])"%(item,item))
elif item in ['LLimitUpTime']:
exec("oneObj.%s = str(row['%s'])[:10]"%(item,item))
else:
#print(item,row[item])
exec("oneObj.%s = float(row['%s'])"%(item,item))
exec("objList.append(oneObj)")
dictObj[oneDate] = objList
#print(dictObj[oneDate][-1].TradeDate)
#print('dictObj: ',dictObj)
return dictObj
def findTableColumns(self,tableName,itemString):
query = "SELECT %s FROM sys.columns WHERE object_id = OBJECT_ID('dbo.%s')"%(itemString,tableName)
self.cursor.execute(query)
logger.warn('findTableColumns:query: ',query)
columnData = self.cursor.fetchall()
if not columnData:
logger.warn( '%s has no data, return None'%tableName )
return None
self.columnName = [x[1] for x in columnData]
return self.columnName
@staticmethod
def findObj(attr,value,objList):
#print('findObj',attr,value,objList)
objListTemp = list()
for x in objList:
for y in value:
#print(y, ' aaaaaaaaaa ',str(eval('x.%s'%attr)))
if y in str(eval('x.%s'%attr)) :
#print(y, ' aaaaaaaaaa ',str(eval('x.%s'%attr)))
objListTemp.append(x)
return objListTemp
@staticmethod
def modifyItemString(itemString):
'''
itemString = '\n SecuCode,SecuAbbr,SecuMarket,TradeDate,TradeStatus,\n PreClosePrice'
'''
listContainer = []
#print(itemString)
for x in itemString.split(','):
if x.startswith('\n'):
listContainer.append(x[2:].strip())
else:
listContainer.append(x)
return listContainer
def pandaData(self,rawData,itemString):
PDcontainer = []
for x in rawData:
tempData = [y for y in x]
PDcontainer.append(tempData)
#print('tempData',tempData,type(tempData))
#print('PDcontainer:',PDcontainer)
myPD = pd.DataFrame(PDcontainer)
#print('myPD,itemString:',myPD,itemString)
myPD.columns = self.modifyItemString(itemString)
logger.info(myPD[:10])
return myPD
#########################################################################################
########################### take care of date ############################################
def getTradingDays(self,startDate,endDate):
'''
获得交易日,如果HS300,SZ50,ZZ500当天任何一家有交易,就认为当天是交易日
'''
itemString = 'SecuCode,TradeDate'
index = ('000300','000905','000016')
query = '''
SELECT
%s
FROM
embase2.[dbo].[EM_QUOTE_INDEX_DAILY]
WHERE
SecuCode in %s
AND
TradeDate >= '%s 00:00:00.000'
AND TradeDate <= '%s 00:00:00.000'
ORDER BY TradeDate ASC
'''%(itemString,index,startDate,endDate)
#print(query)
self.cursor.execute(query)
raw = self.cursor.fetchall()
logger.info('raw :',raw)
if not raw:
logger.critical( 'index market value|trading days| has no data, return None')
return None
indexPD = self.pandaData(raw,itemString)
indexPD.fillna(value=0, inplace=True) # to replace None with value 0
dateList = [str(x)[:10] for x in indexPD['TradeDate'].tolist()]
dateList = list(set(dateList))
dateList.sort()
today = datetime.datetime.strftime(datetime.datetime.today(),'%Y-%m-%d')
for x in list(dateList):
if x >= today:
#print('future date',x)
dateList.remove(x)
return dateList
def getToday(self):
return str(datetime.datetime.today())[:10]
def getYesterday(self):
end = datetime.datetime.today()
start = end - datetime.timedelta(1)
return str(start)[:10]
def getNdayBefore(self,date,N):
end = datetime.datetime.strptime(date,'%Y-%m-%d')
start = end - datetime.timedelta(N)
return str(start)[:10]
def getMostRecentTrading(self):
end = datetime.datetime.today()
start = end - datetime.timedelta(70)
end = datetime.datetime.strftime(end,'%Y-%m-%d')
start = datetime.datetime.strftime(start,'%Y-%m-%d')
return self.getTradingDays(end,start)[-1]
def getMostRecentTradingDay(self,then):
'''
比如说想找 then = '2015-06-05' 这天之前的最近一个交易日
'''
end = datetime.datetime.strptime(then,'%Y-%m-%d')
start = end - datetime.timedelta(70)
end = datetime.datetime.strftime(end,'%Y-%m-%d')
start = datetime.datetime.strftime(start,'%Y-%m-%d')
return self.getTradingDays(end,start)[-1]
@staticmethod
def deprecated(func):
"""This is a decorator which can be used to mark functions
as deprecated. It will result in a warning being emitted
when the function is used."""
@functools.wraps(func)
def new_func(*args, **kwargs):
warnings.simplefilter('always', DeprecationWarning) # turn off filter
warnings.warn("Call to deprecated function {}.".format(func.__name__),
category=DeprecationWarning,
stacklevel=2)
warnings.simplefilter('default', DeprecationWarning) # reset filter
return func(*args, **kwargs)
return new_func
if __name__ == '__main__':
myAPI = ApiParent()
myAPI.init()
myAPI.getTradingDays()
\ No newline at end of file
# -*- coding: utf-8 -*-
"""
Created on 20180309
@author: zhoushuai
"""
import pandas as pd
import pyodbc
import ky
sdk = ky.Api("http://data-api.kuaiyutech.com/api.rpc")
import logging
logger = logging.getLogger(__name__)
try:
from ..BT.stock import Stock
from ..BT.index import Index
logger.setLevel(logging.CRITICAL)
from ..util.kySDK import *
from .apiParent import ApiParent
except:
import sys
#D:\Project\益盟\回测框架\KYBT\BT
sys.path.insert(0, 'D:/Project/YM/BackTesting Frame/KYBT/BT')
sys.path.insert(0, 'D:/Project/YM/BackTesting Frame/KYBT/util')
print(sys.path)
from stock import Stock
from index import Index
from kySDK import *
from apiParent import ApiParent
logger.setLevel(logging.WARNING)
class API(ApiParent):
def __init__(self,DSN):
super().__init__(DSN)
def getGrowthRateOperatingRevenue(self,date,stock,option,range):
'''
主营业务收入增长率
date: str '2017-01-01'
stock: list ## [600000,000002]
range float, ## 大于30%, 30%~20%, 20%~15%, 15%~10%, 10%~7.5%, 7.5%~5%, 5%~2.5%, 2.5%~0, 小于0,
option 'recent period'|'recent year'|'recent three year' ## 最近一期,最近一年,最近三年
'''
itemString = 'SecuCode,SecuAbbr,TradeDate,TradeStatus,PreClosePrice,OpenPrice,ClosePrice,HighPrice,LowPrice,TurnoverVolume,TurnoverValue,ChangeRatio'
query = "SELECT %s FROM [dbo].[CY_FinacialRatio_RP] where SecuCode = %s ORDER BY EndDate DESC "
#print(query)
self.cursor.execute(query)
raw = self.cursor.fetchall()
logger.info('raw :',raw)
if not raw:
logger.critical( 'index market value has no data, return None')
return None
indexPD = self.pandaData(raw,itemString)
indexPD.fillna(value=0, inplace=True) # to replace None with value 0
return self.pdToIndexObjectList(indexPD)
if __name__ == '__main__':
logger.warn(__file__)
myAPI = API('BTEMmidd2')
myAPI.init()
y = myAPI.getGrowthRateOperatingRevenue('2017-05-05','600000','recent period',0.3,)
print(y)
\ No newline at end of file
import sys
sys.path.insert(0, 'D:/Project/益盟/回测框架/KYBT/util')
from kySDK import *
"""
print(getMostRecentTradingDayFromKy())
itemString = '''SecuCode,
SecuAbbr,SecuMarket,TradeDate,TradeStatus,PreClosePrice,
OpenPrice,ClosePrice,HighPrice,LowPrice,TurnoverVolume,TurnoverValue,TurnoverDeals,Amplitude,ChangeRatio,
FlowShares,FlowMarketValue,TotalEquity,IssueEquity,TotalValue,RecordID,RiseOrDown'''
index = 'SHSE.000016'
index = 'SHSE.000001'
stockPool = tuple(stockCode[-6:] for stockCode in getIndexPoolFromKy(index))
query = '''
SELECT %s
FROM
[dbo].[EM_QUOTE_STOCK_DAILY]
WHERE
TradeDate = '%s 00:00:00.000'
AND
SecuCode IN %s
'''%(itemString,getMostRecentTradingDayFromKy(),stockPool)
print(query)
"""
def myfun(x):
print(sum(x))
myfun([1,2,3])
class myclass():
a = 1
def myfunc(self):
print(self.a)
c = myclass()
c.myfunc()
# -*- coding: utf-8 -*-
"""
Created on 20180311
@author: Matthew
"""
from .position import Position
import logging
import numpy as np
logger = logging.getLogger(__name__)
logger.setLevel(logging.CRITICAL)
class Account():
def __str__(self):
s = 'class account: you can buy, hold, and dump all stocks in this class'
return s
def __init__(self,cash,tradingHabit):
'''
tradingHabit: 'OpenPrice'|'ClosePrice'| OpenPrice is prefered
'''
self.initialCash = cash
self.__cash = cash
self.positionList = []
self.__totalValue = cash #
self.__positionListValue = 0 #
self.tradingHabit = tradingHabit
self.runningDays = 0
def printMe(self):
logger.warn(' --------- my account status -----------')
logger.warn(' account--initialCash: %0.2f'%self.initialCash)
logger.warn(' account--cash: %0.2f'%self.cash)
logger.warn(' account--positionListValue: %0.2f'%self.positionListValue)
logger.warn(' account--totalValue: %0.2f'%self.totalValue)
logger.warn(' account--len of positionList: %d'%len(self.positionList))
#print('account--Name of positionList',[x.SecuCode for x in self.positionList])
logger.warn(' ---------------------------------------')
@property
def cash(self):
return self.__cash
@cash.setter
def cash(self,value):
if value < -1:
raise ValueError('cash below -1 is not possible')
self.__cash = value
@property
def totalValue(self):
return self.__totalValue
@totalValue.setter
def totalValue(self,value):
if value < -1:
raise ValueError('totalValue below -1 is not possible')
self.__totalValue = value
@property
def positionListValue(self):
return self.__positionListValue
@positionListValue.setter
def positionListValue(self,value):
if value < -1:
raise ValueError('positionListValue below -1 is not possible, can be below 0 slightly because of the rounding')
self.__positionListValue = value
def isempty(self):
if len(self.positionList) > 0:
return False
else:
return True
def buy(self,stock,evenCash):
'''
excecute the buy action, evenCash is total cash / stock #
'''
#print('buy')
#print('buy','stock.TradeStatus',stock.TradeStatus,stock.SecuCode)
price = stock.OpenPrice if self.tradingHabit == 'OpenPrice' else stock.ClosePrice
boughtAmount = np.floor(evenCash/price/100)*100
#print('evenCash: %d, price: %0.2f, boughtAmount: %s, boughtValue: %d'%(evenCash,price,boughtAmount,price*boughtAmount))
#print('boughtAmount:%d'%boughtAmount)
if boughtAmount <= 0:
#print('not enough evenCash,evenCash: %d,price %0.2f, boughtAmount:%d'%(evenCash,price,boughtAmount))
return None
#create Position Object
stockPosition = Position(stock,boughtAmount,price)
#print('SecuCode,price,amount,value,',stockPosition.SecuCode,stockPosition.boughtPrice,stockPosition.boughtAmount,stockPosition.positionValue)
#update positionList
self.positionList.append(stockPosition)
#print('self.positionList: ',self.positionList)
self.cash -= price * boughtAmount
#print('self.cash:',self.cash)
#updata positionValue
self.positionListValue += price * boughtAmount
#update totalValue
self.totalValue = self.positionListValue + self.cash
#print('totalValue: %d'%self.totalValue)
#self.runningDays += 1
def countrunningDays(self):
self.runningDays += 1
def getPositionList(self):
return self.positionList
def getnetValue(self):
return self.getTotalValue()/self.initialCash
def getTotalValue(self):
return self.totalValue
def updatePositionListValue(self):
#print('updatePositionListValue')
#print(x.positionValue for x in self.positionList)
#value = 0
for x in self.positionList:
#print(x.SecuCode,x.positionValue)
if x.positionValue == None: # 君正集团 20130704 没有bar
x.positionValue = 0
#value += x.positionValue
#return value
return sum(x.positionValue for x in self.positionList)
def getPositionListvalue(self):
return self.positionListValue
def sellAvailableForSell(self,NameList):
'''
dump all available position
'''
self.initialCash = self.cash
#print('sellAvailableForSell') # print here means execute once in that loop
for stockName in NameList:
for position in self.positionList:
if position.SecuCode == stockName:
#print('stockName: %s, position.positionValue: %s, positionListValue: %s, len(positionList): %d'\
#%(stockName,position.positionValue,self.positionListValue,len(self.positionList)))
self.initialCash += position.positionValue
self.cash += position.positionValue
self.positionListValue -= position.positionValue
self.positionList.remove(position)
#self.runningDays += 1
def sell(self,stock):
'''
sell individual stock
'''
for position in self.positionList:
if position.SecuCode == stock.SecuCode:
self.positionList.remove(position) # don't need to empty position object, python will clean the cache after certain while
def held(self,day,updatedStock):
'''
update position's market value in the positionList
'''
#logger.warning('held')
myList = [x.SecuCode for x in updatedStock]
if not myList:
return 'no positions to hold 1 '
#print('myList: ',myList,[x.ClosePrice for x in updatedStock])
if updatedStock is None:
print('no position to hold 2')
return 'No data for %s'%day
for position in self.positionList:
for stock in updatedStock:
if position.SecuCode == stock.SecuCode:
#print('match',position.SecuCode,position.SecuCode)
position.remainInAccount(stock,2) # method1 or method2 in position.py
self.positionListValue = self.updatePositionListValue()
self.totalValue = self.positionListValue + self.cash
# -*- coding: utf-8 -*-
"""
Created on 2018408
@author: Matthew
"""
# 首先找到所有需要用到的表
# 所有的指标中文、英文名、数据表名称
DataTable = \
{
"存货周转率":["InventoryTurnover","CY_FinacialRatio_RP"],
"应收账款周转率":["AccountsReceivableTurnover","CY_FinacialRatio_RP"],
"固定资产周转率":["FixedAssetsTurnover","CY_FinacialRatio_RP"],
"主营收入同比":["OperatingRevenueYoY","CY_FinacialRatio_RP"],
"归属于母公司股东的扣除非经常性损益后的净利润同比":['DeductNetProfitYoY',"CY_FinacialRatio_RP"],
"总资产":["TotalAssets","CY_FinacialIndicators_RP"],
"预收款项":["AdvanceReceipts","CY_FinacialIndicators_RP"],
"净资产":["EquityBelongedToPC","CY_FinacialIndicators_RP"],
"总负债":["TotalLiability","CY_FinacialIndicators_RP"],
"流动负债":["TotalCurrentLiability","CY_FinacialIndicators_RP"],
"流动资产":["TotalCurrentAssets","CY_FinacialIndicators_RP"],
"现金及存放中央银行款项":["CashOrDepositInCentralBank","CY_FinacialIndicators_RP"],
"净利润":["NetProfit","CY_FinacialIndicators_RP"],
"经营活动产生的现金流":["NetOperateCashFlow","CY_FinacialIndicators_RP"],
"最新流通A股":["RMBShares","CY_ValueDaily_Quote"],
"最新有效流通股":["ValidShares","CY_ValueDaily_Quote"],
"最新总市值":["MarketValue","CY_ValueDaily_Quote"],
"市盈率(TTM)":["PE1","CY_ValueDaily_Quote"],
"市销率":["PB","CY_ValueDaily_Quote"],
"市净率":["PS","CY_ValueDaily_Quote"],
}
def findTable(criteria):
for key in DataTable:
if key == criteria:
DataTable[key]
'''
created by: matt 2018-03-30
EMMIDD2.dbo.CY_FinacialIndicators_RP
列名 中文名 别名 类型 单位 默认值 是否可空 说明
SecuCode 证券代码 varchar(12) FALSE
SecuAbbr 证券名称 nvarchar(40) TRUE
EndDate 报告日期 datetime FALSE
TotalAssets 总资产 numeric(18,4) 元 TRUE
AdvanceReceipts 预收款项 numeric(18,4) TRUE
EquityBelongedToPC 净资产 numeric(18,4) TRUE
PublDate 公告日期 datetime TRUE
TotalLiability 总负债 numeric(18,4) 元 TRUE
TotalCurrentLiability 流动负债 numeric(18,4) 元 TRUE
TotalCurrentAssets 流动资产 numeric(18,4) 元 TRUE
CashOrDepositInCentralBank 现金及存放中央银行款项 numeric(18,4) 元 TRUE
NetProfit 净利润 numeric(18,4) 元 TRUE
NetOperateCashFlow 经营活动产生的现金流 numeric(18,4) 元 TRUE
'''
class FinancialIndicator():
def __init__(self):
pass
'''
def __init__(self,SecuCode,SecuAbbr,TradeDate,ReportPeriod,PE1,PB,PS,ClosePrice,RMBShares,Bshares,ValidShares,MarketValue):
self.SecuCode = SecuCode
self.SecuAbbr = SecuAbbr
self.EndDate = EndDate
self.PublDate = PublDate
self.TotalCurrentAssets = TotalCurrentAssets
self.TotalAssets = TotalAssets
self.AdvanceReceipts = AdvanceReceipts
self.EquityBelongedToPC = EquityBelongedToPC
self.CashOrDepositInCentralBank = CashOrDepositInCentralBank
self.TotalLiability = TotalLiability
self.TotalCurrentLiability = TotalCurrentLiability
self.NetProfit = NetProfit
self.NetOperateCashFlow = NetOperateCashFlow
'''
def printMe(self):
print(self.SecuCode,self.SecuAbbr,self.EndDate)
\ No newline at end of file
'''
created by: matt 2018-03-30
EMMIDD2.dbo.CY_FinacialRatio_RP
SecuCode 证券代码 varchar(12) FALSE
SecuAbbr 证券名称 nvarchar(40) TRUE
EndDate 报告日期 datetime FALSE
PublDate 公告日期 datetime TRUE
InventoryTurnover 存货周转率 numeric(18,4) 次 TRUE
AccountsReceivableTurnover 应收账款周转率 numeric(18,4) 次 TRUE
FixedAssetsTurnover 固定资产周转率 numeric(18,4) 次 TRUE
OperatingRevenueYoY 主营收入同比 numeric(18,4) TRUE
DeductNetProfitYoY 归属于母公司股东的扣除非经常性损益后的净利润同比 numeric(18,4) TRUE
'''
class FinancialRatioRP():
def __init__(self):
pass
'''
def __init__(self,SecuCode,SecuAbbr,TradeDate,ReportPeriod,PE1,PB,PS,ClosePrice,RMBShares,Bshares,ValidShares,MarketValue):
self.SecuCode = SecuCode
self.SecuAbbr = SecuAbbr
self.EndDate = EndDate
self.PublDate = PublDate
self.InventoryTurnover = InventoryTurnover
self.AccountsReceivableTurnover = AccountsReceivableTurnover
self.FixedAssetsTurnover = FixedAssetsTurnover
self.OperatingRevenueYoY = OperatingRevenueYoY
self.DeductNetProfitYoY = DeductNetProfitYoY
'''
def printMe(self):
print(self.SecuCode,self.SecuAbbr,self.EndDate,self.DeductNetProfitYoY)
\ No newline at end of file
'''
created by: matt 2018-03-15
'''
'''
列名 中文名 别名 类型 单位 默认值 是否可空 说明
SecuCode 证券代码 varchar(10) FALSE
SecuAbbr 证券简称 nvarchar(40) TRUE
TradeDate 交易日期 datetime FALSE
TradeStatus 交易状态 char(1) TRUE
PreClosePrice 昨收 numeric(20,4) 元 TRUE
OpenPrice 今开盘 numeric(20,4) 元 TRUE
ClosePrice 今收盘 numeric(20,4) 元 TRUE
HighPrice 最高价 numeric(20,4) 元 TRUE
LowPrice 最低价 numeric(20,4) 元 TRUE
TurnoverVolume 成交量 numeric(20,4) 手 TRUE
TurnoverValue 成交额 numeric(20,4) 元 TRUE
TurnoverDeals 成交笔数 numeric(20,4) 笔 TRUE
ChangeRatio 日涨跌幅 numeric(20,4) % TRUE
'''
class Index():
def __init__(self):
pass
'''
def __init__(self,SecuCode,SecuAbbr,SecuMarket,TradeDate,TradeStatus,PreClosePrice,OpenPrice,ClosePrice,HighPrice,
LowPrice,TurnoverVolume,TurnoverValue,TurnoverDeals,Amplitude,ChangeRatio,FlowShares,FlowMarketValue,TotalEquity,IssueEquity,
TotalValue,RecordID,RiseOrDown):
self.SecuCode = SecuCode
self.SecuAbbr = SecuAbbr
self.TradeDate = TradeDate
self.TradeStatus = TradeStatus
self.PreClosePrice = PreClosePrice
self.OpenPrice = OpenPrice
self.ClosePrice = ClosePrice
self.HighPrice = HighPrice
self.LowPrice = LowPrice
self.TurnoverVolume = TurnoverVolume
self.TurnoverValue = TurnoverValue
self.TurnoverDeals = TurnoverDeals
self.ChangeRatio = ChangeRatio
'''
def printMe(self):
print(self.SecuCode,self.SecuAbbr,self.TradeDate)
\ No newline at end of file
'''
created by: matt 2018-03-11
'''
'''
列名 中文名 别名 类型 单位 默认值 是否可空 说明
SecuCode 证券代码 varchar(10) FALSE
SecuAbbr 证券简称 nvarchar(40) TRUE
SecuMarket 证券市场 varchar(12) TRUE
TradeDate 交易日期 datetime FALSE
TradeStatus 交易状态 char(1) TRUE
PreClosePrice 昨收 numeric(20,4) 元 TRUE
OpenPrice 今开盘 numeric(20,4) 元 TRUE
ClosePrice 今收盘 numeric(20,4) 元 TRUE
HighPrice 最高价 numeric(20,4) 元 TRUE
LowPrice 最低价 numeric(20,4) 元 TRUE
TurnoverVolume 成交量 numeric(20,4) 手 TRUE
TurnoverValue 成交额 numeric(20,4) 元 TRUE
TurnoverDeals 成交笔数 numeric(20,4) 笔 TRUE
Amplitude 振幅 numeric(20,4) % TRUE
ChangeRatio 日涨跌幅 numeric(20,4) % TRUE
FlowShares 流通股本 numeric(30,4) TRUE
FlowMarketValue 流通市值 numeric(30,4) TRUE
TotalEquity 公司总股本 numeric(20,4) TRUE
IssueEquity 发行总股本 numeric(30,4) TRUE
TotalValue 总市值 numeric(30,4) TRUE
RecordID 记录ID uniqueidentifier (newid()) TRUE
RiseOrDown 涨跌标示 varchar(2) TRUE 1:涨停 -1:跌停 0:无涨跌停
'''
class Stock():
def __init__(self):
pass
'''
def __init__(self,SecuCode,SecuAbbr,SecuMarket,TradeDate,TradeStatus,PreClosePrice,OpenPrice,ClosePrice,HighPrice,
LowPrice,TurnoverVolume,TurnoverValue,TurnoverDeals,Amplitude,ChangeRatio,FlowShares,FlowMarketValue,TotalEquity,IssueEquity,
TotalValue,RecordID,LLimitUpTime,RiseOrDown):
self.SecuCode = SecuCode
self.SecuAbbr = SecuAbbr
self.SecuMarket = SecuMarket
self.TradeDate = TradeDate
self.TradeStatus = TradeStatus
self.PreClosePrice = PreClosePrice
self.OpenPrice = OpenPrice
self.ClosePrice = ClosePrice
self.HighPrice = HighPrice
self.LowPrice = LowPrice
self.TurnoverVolume = TurnoverVolume
self.TurnoverVal = TurnoverValue
self.TurnoverDeals = TurnoverDeals
self.Amplitude = Amplitude
self.ChangeRatio = ChangeRatio
self.FlowShares = FlowShares
self.FlowMarketValue = FlowMarketValue
self.TotalEquity = TotalEquity
self.IssueEquity = IssueEquity
self.TotalValue = TotalValue
self.RecordID = RecordID
self.LLimitUpTime = LLimitUpTime
self.RiseOrDown = RiseOrDown
'''
def printMe(self):
print('this is stock!')
#print(self.SecuCode,self.SecuAbbr,self.TradeDate)
\ No newline at end of file
'''
created by: matt 2018-03-11
EMMIDD2.dbo.CY_ValueDaily_Quote
列名 中文名 别名 类型 单位 默认值 是否可空 说明
SecuCode 证券代码 varchar(12) FALSE
SecuAbbr 证券名称 nvarchar(40) TRUE
ReportPeriod 报告期 datetime TRUE
TradeDate 交易日期 datetime FALSE
PE1 市盈率(TTM) numeric(14,4) 倍 TRUE 市盈率(TTM)
PB 市净率 numeric(14,4) 倍 TRUE
PS 市销率 numeric(14,4) 倍 TRUE
ClosePrice 最新收盘价 numeric(12,4) 元 TRUE
RMBShares 最新流通A股 numeric(18,4) 万股 TRUE
ValidShares 最新有效流通股 numeric(18,4) 万股 TRUE 扣除了非有效流通股数据
MarketValue 最新总市值 numeric(18,4) 元 TRUE
'''
class ValueDaily():
def __init__(self):
pass
'''
def __init__(self,SecuCode,SecuAbbr,TradeDate,ReportPeriod,PE1,PB,PS,ClosePrice,RMBShares,Bshares,ValidShares,MarketValue):
self.SecuCode = SecuCode
self.SecuAbbr = SecuAbbr
self.TradeDate = TradeDate
self.ReportPeriod = ReportPeriod
self.PE1 = PE1
self.PB = PB
self.PS = PS
self.ClosePrice = ClosePrice
self.RMBShares = RMBShares
self.ValidShares = ValidShares
self.MarketValue = MarketValue
'''
def printMe(self):
print(self.SecuCode,self.SecuAbbr,self.TradeDate)
\ No newline at end of file
######################################################################################################################
'''
列名 中文名 别名 类型 单位 默认值 是否可空 说明
SecuCode 证券代码 varchar(10) FALSE
SecuAbbr 证券简称 nvarchar(40) TRUE
SecuMarket 证券市场 varchar(12) TRUE
TradeDate 交易日期 datetime FALSE
TradeStatus 交易状态 char(1) TRUE
PreClosePrice 昨收 numeric(20,4) 元 TRUE
OpenPrice 今开盘 numeric(20,4) 元 TRUE
ClosePrice 今收盘 numeric(20,4) 元 TRUE
HighPrice 最高价 numeric(20,4) 元 TRUE
LowPrice 最低价 numeric(20,4) 元 TRUE
TurnoverVolume 成交量 numeric(20,4) 手 TRUE
TurnoverValue 成交额 numeric(20,4) 元 TRUE
TurnoverDeals 成交笔数 numeric(20,4) 笔 TRUE
Amplitude 振幅 numeric(20,4) % TRUE
ChangeRatio 日涨跌幅 numeric(20,4) % TRUE
FlowShares 流通股本 numeric(30,4) TRUE
FlowMarketValue 流通市值 numeric(30,4) TRUE
TotalEquity 公司总股本 numeric(20,4) TRUE
IssueEquity 发行总股本 numeric(30,4) TRUE
TotalValue 总市值 numeric(30,4) TRUE
RecordID 记录ID uniqueidentifier (newid()) TRUE
RiseOrDown 涨跌标示 varchar(2) TRUE 1:涨停 -1:跌停 0:无涨跌停
'''
class Stock():
def __init__(self):
pass
'''
def __init__(self,SecuCode,SecuAbbr,SecuMarket,TradeDate,TradeStatus,PreClosePrice,OpenPrice,ClosePrice,HighPrice,
LowPrice,TurnoverVolume,TurnoverValue,TurnoverDeals,Amplitude,ChangeRatio,FlowShares,FlowMarketValue,TotalEquity,IssueEquity,
TotalValue,RecordID,LLimitUpTime,RiseOrDown):
self.SecuCode = SecuCode
self.SecuAbbr = SecuAbbr
self.SecuMarket = SecuMarket
self.TradeDate = TradeDate
self.TradeStatus = TradeStatus
self.PreClosePrice = PreClosePrice
self.OpenPrice = OpenPrice
self.ClosePrice = ClosePrice
self.HighPrice = HighPrice
self.LowPrice = LowPrice
self.TurnoverVolume = TurnoverVolume
self.TurnoverVal = TurnoverValue
self.TurnoverDeals = TurnoverDeals
self.Amplitude = Amplitude
self.ChangeRatio = ChangeRatio
self.FlowShares = FlowShares
self.FlowMarketValue = FlowMarketValue
self.TotalEquity = TotalEquity
self.IssueEquity = IssueEquity
self.TotalValue = TotalValue
self.RecordID = RecordID
self.LLimitUpTime = LLimitUpTime
self.RiseOrDown = RiseOrDown
'''
def printMe(self):
print('this is stock!')
print(self.SecuCode,self.SecuAbbr,self.TradeDate)
########################################################################################################################
'''
EMMIDD2.dbo.CY_ValueDaily_Quote
列名 中文名 别名 类型 单位 默认值 是否可空 说明
SecuCode 证券代码 varchar(12) FALSE
SecuAbbr 证券名称 nvarchar(40) TRUE
ReportPeriod 报告期 datetime TRUE
TradeDate 交易日期 datetime FALSE
PE1 市盈率(TTM) numeric(14,4) 倍 TRUE 市盈率(TTM)
PB 市净率 numeric(14,4) 倍 TRUE
PS 市销率 numeric(14,4) 倍 TRUE
ClosePrice 最新收盘价 numeric(12,4) 元 TRUE
RMBShares 最新流通A股 numeric(18,4) 万股 TRUE
ValidShares 最新有效流通股 numeric(18,4) 万股 TRUE 扣除了非有效流通股数据
MarketValue 最新总市值 numeric(18,4) 元 TRUE
'''
class ValueDaily():
def __init__(self):
pass
'''
def __init__(self,SecuCode,SecuAbbr,TradeDate,ReportPeriod,PE1,PB,PS,ClosePrice,RMBShares,Bshares,ValidShares,MarketValue):
self.SecuCode = SecuCode
self.SecuAbbr = SecuAbbr
self.TradeDate = TradeDate
self.ReportPeriod = ReportPeriod
self.PE1 = PE1
self.PB = PB
self.PS = PS
self.ClosePrice = ClosePrice
self.RMBShares = RMBShares
self.ValidShares = ValidShares
self.MarketValue = MarketValue
'''
def printMe(self):
print(self.SecuCode,self.SecuAbbr,self.TradeDate)
###########################################################################################################################################
'''
列名 中文名 别名 类型 单位 默认值 是否可空 说明
SecuCode 证券代码 varchar(10) FALSE
SecuAbbr 证券简称 nvarchar(40) TRUE
TradeDate 交易日期 datetime FALSE
TradeStatus 交易状态 char(1) TRUE
PreClosePrice 昨收 numeric(20,4) 元 TRUE
OpenPrice 今开盘 numeric(20,4) 元 TRUE
ClosePrice 今收盘 numeric(20,4) 元 TRUE
HighPrice 最高价 numeric(20,4) 元 TRUE
LowPrice 最低价 numeric(20,4) 元 TRUE
TurnoverVolume 成交量 numeric(20,4) 手 TRUE
TurnoverValue 成交额 numeric(20,4) 元 TRUE
TurnoverDeals 成交笔数 numeric(20,4) 笔 TRUE
ChangeRatio 日涨跌幅 numeric(20,4) % TRUE
'''
class Index():
def __init__(self):
pass
'''
def __init__(self,SecuCode,SecuAbbr,SecuMarket,TradeDate,TradeStatus,PreClosePrice,OpenPrice,ClosePrice,HighPrice,
LowPrice,TurnoverVolume,TurnoverValue,TurnoverDeals,Amplitude,ChangeRatio,FlowShares,FlowMarketValue,TotalEquity,IssueEquity,
TotalValue,RecordID,RiseOrDown):
self.SecuCode = SecuCode
self.SecuAbbr = SecuAbbr
self.TradeDate = TradeDate
self.TradeStatus = TradeStatus
self.PreClosePrice = PreClosePrice
self.OpenPrice = OpenPrice
self.ClosePrice = ClosePrice
self.HighPrice = HighPrice
self.LowPrice = LowPrice
self.TurnoverVolume = TurnoverVolume
self.TurnoverValue = TurnoverValue
self.TurnoverDeals = TurnoverDeals
self.ChangeRatio = ChangeRatio
'''
def printMe(self):
print(self.SecuCode,self.SecuAbbr,self.TradeDate)
###########################################################################################################################################
'''
EMMIDD2.dbo.CY_FinacialRatio_RP
SecuCode 证券代码 varchar(12) FALSE
SecuAbbr 证券名称 nvarchar(40) TRUE
EndDate 报告日期 datetime FALSE
PublDate 公告日期 datetime TRUE
InventoryTurnover 存货周转率 numeric(18,4) 次 TRUE
AccountsReceivableTurnover 应收账款周转率 numeric(18,4) 次 TRUE
FixedAssetsTurnover 固定资产周转率 numeric(18,4) 次 TRUE
OperatingRevenueYoY 主营收入同比 numeric(18,4) TRUE
DeductNetProfitYoY 归属于母公司股东的扣除非经常性损益后的净利润同比 numeric(18,4) TRUE
'''
class FinancialRatioRP():
def __init__(self):
pass
'''
def __init__(self,SecuCode,SecuAbbr,TradeDate,ReportPeriod,PE1,PB,PS,ClosePrice,RMBShares,Bshares,ValidShares,MarketValue):
self.SecuCode = SecuCode
self.SecuAbbr = SecuAbbr
self.EndDate = EndDate
self.PublDate = PublDate
self.InventoryTurnover = InventoryTurnover
self.AccountsReceivableTurnover = AccountsReceivableTurnover
self.FixedAssetsTurnover = FixedAssetsTurnover
self.OperatingRevenueYoY = OperatingRevenueYoY
self.DeductNetProfitYoY = DeductNetProfitYoY
'''
def printMe(self):
print(self.SecuCode,self.SecuAbbr,self.EndDate,self.DeductNetProfitYoY)
##########################################################################################################################
'''
EMMIDD2.dbo.CY_FinacialIndicators_RP
列名 中文名 别名 类型 单位 默认值 是否可空 说明
SecuCode 证券代码 varchar(12) FALSE
SecuAbbr 证券名称 nvarchar(40) TRUE
EndDate 报告日期 datetime FALSE
TotalAssets 总资产 numeric(18,4) 元 TRUE
AdvanceReceipts 预收款项 numeric(18,4) TRUE
EquityBelongedToPC 净资产 numeric(18,4) TRUE
PublDate 公告日期 datetime TRUE
TotalLiability 总负债 numeric(18,4) 元 TRUE
TotalCurrentLiability 流动负债 numeric(18,4) 元 TRUE
TotalCurrentAssets 流动资产 numeric(18,4) 元 TRUE
CashOrDepositInCentralBank 现金及存放中央银行款项 numeric(18,4) 元 TRUE
NetProfit 净利润 numeric(18,4) 元 TRUE
NetOperateCashFlow 经营活动产生的现金流 numeric(18,4) 元 TRUE
'''
class FinancialIndicator():
def __init__(self):
pass
'''
def __init__(self,SecuCode,SecuAbbr,TradeDate,ReportPeriod,PE1,PB,PS,ClosePrice,RMBShares,Bshares,ValidShares,MarketValue):
self.SecuCode = SecuCode
self.SecuAbbr = SecuAbbr
self.EndDate = EndDate
self.PublDate = PublDate
self.TotalCurrentAssets = TotalCurrentAssets
self.TotalAssets = TotalAssets
self.AdvanceReceipts = AdvanceReceipts
self.EquityBelongedToPC = EquityBelongedToPC
self.CashOrDepositInCentralBank = CashOrDepositInCentralBank
self.TotalLiability = TotalLiability
self.TotalCurrentLiability = TotalCurrentLiability
self.NetProfit = NetProfit
self.NetOperateCashFlow = NetOperateCashFlow
'''
def printMe(self):
print(self.SecuCode,self.SecuAbbr,self.EndDate)
# -*- coding: utf-8 -*-
"""
Created on 20180313
@author: Matthew
"""
import numpy as np
from matplotlib import pyplot as plt
import datetime
import matplotlib.pyplot as plt
from pylab import mpl
mpl.rcParams['font.sans-serif'] = ['SimHei']
#mpl.rcParams['font.sans-serif'] = ['Microsoft YaHei'] # 指定默认字体:解决plot不能显示中文问题
mpl.rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题
def anualizedreturn(netvalue):
'''
年化收益
'''
myreturn = ( netvalue[-1] - netvalue[0] ) / netvalue[0]
annualReturn = str( round( ((1+myreturn)**(250/len(netvalue)) - 1) * 100 , 2)) + '%'
print( '年化收益为 %s'%annualReturn)
return annualReturn
def growthPercent(netvalue):
'''
策略涨幅
'''
print('期间涨幅为 ' + str( round( ( netvalue[-1] - netvalue[0] ) / netvalue[0] * 100 , 2)) + '%')
return str( round( ( netvalue[-1] - netvalue[0] ) / netvalue[0] * 100 , 2)) + '%'
def maxdrawdown(netvalue):
i = np.argmax( (np.maximum.accumulate(netvalue) - netvalue ) / np.maximum.accumulate(netvalue) ) # end of the period
#print('i:', i)
j = np.argmax( netvalue[:i] )
drawdown = ( 1 - netvalue[i] / netvalue[j] )
print('最大回撤为 ' + str(round(drawdown*100,2)) + '%')
return str(round(drawdown*100,2)) + '%'
def maxdrawdown2(netvalue):
'''
我的方法更实用
最大回撤,当前点,历史最高点,
如果当前点在历史最高点以下,算出之间的降幅,只保留最大的那个降幅
如果当前点在历史最高点以上,不做任何计算,
'''
index = 0
drawdown = 0
for dot in netvalue:
highestDot = max(netvalue[:index]) if index is not 0 else netvalue[0]
if dot >= highestDot:
index += 1
continue
elif dot < highestDot and (dot - highestDot)/highestDot < drawdown:
drawdown = (dot - highestDot)/highestDot
index += 1
print('最大回撤为 ' + str(round(drawdown*100,2)) + '%')
return str(round(drawdown*100,2)) + '%'
def evaluator(strategyID,BTRecords,indexRecords,plot):
'''
indexRecords: list of index objs
self.BTRecords[oneDay] = dict()
self.BTRecords[oneDay]['positionList'] = positionList
self.BTRecords[oneDay]['totalValue'] = totalValue
self.BTRecords[oneDay]['cash'] = cash
self.BTRecords[oneDay]['positionListValue'] = positionListValue
'''
BTtradingDays = []
totalValue = []
cash = []
positionListValue = []
for day,value in BTRecords.items():
BTtradingDays.append(day)
totalValue.append(value['totalValue'])
cash.append(value['cash'])
positionListValue.append(value['positionListValue'])
BTNetvalue = [x/totalValue[0] for x in totalValue]
cashNetValue = [x/cash[0] for x in cash]
# positionvalue is 0 initially
positionListNetValue = [x/cash[0] for x in positionListValue]
print('\n策略评价:')
growthPercent(BTNetvalue)
anualizedreturn(BTNetvalue)
maxdrawdown2(BTNetvalue)
print('\n同期指数评价:')
#print(type(indexRecords),indexRecords)
indexNetvalue = [x.ClosePrice/indexRecords[0].ClosePrice for x in indexRecords]
indexDate = [x.TradeDate for x in indexRecords]
growthPercent(indexNetvalue)
anualizedreturn(indexNetvalue)
maxdrawdown2(indexNetvalue)
'''
print('len(BTtradingDays): ',len(BTtradingDays),BTtradingDays[:5])
print('len(BTNetvalue): ',len(BTNetvalue))
print('len(indexDate): ',len(indexDate),indexDate[:5])
print('len(indexNetvalue): ',len(indexNetvalue))
print('difference in days: ', set(indexDate) - set(BTtradingDays))
'''
'''
print('\n写入文件:')
with open('./Strategy Records/strategy_%s.txt'%strategyID,'a+') as f:
f.write('--------' + '策略评估' + '----------\n')
f.write('期间涨幅: %s\n'%growthPercent(BTNetvalue))
f.write('年化收益: %s\n'%anualizedreturn(BTNetvalue))
f.write('最大回撤: %s\n'%maxdrawdown2(BTNetvalue))
f.write('--------' + '指数对比' + '----------\n')
f.write('期间涨幅: %s\n'%growthPercent(indexNetvalue))
f.write('年化收益: %s\n'%anualizedreturn(indexNetvalue))
f.write('最大回撤: %s\n'%maxdrawdown2(indexNetvalue))
'''
if plot == True:
dates = [datetime.datetime.strptime(x,'%Y-%m-%d') for x in BTtradingDays]
#print('%0.0f %0.0f %0.0f %0.0f %0.0f'%(len(dates),len(BTNetvalue),len(cashNetValue),len(positionListNetValue),len(indexNetvalue)))
plt.plot(dates,BTNetvalue,'r-',dates,cashNetValue,'g-',dates,positionListNetValue,'y.',dates,indexNetvalue,'b--',)
plt.ylabel('净值')
plt.xlabel('时间')
plt.axis('tight')
plt.legend(['策略','现金','持仓','指数'])
plt.grid()
plt.show()
if __name__ == '__main__':
netvalue = [1,0.5,1,2,3,1]
netvalue = [1,1,1.01,1.03,0.4,100,10]
#maxdrawdown(netvalue)
maxdrawdown2(netvalue)
# -*- coding: utf-8 -*-
"""
Created on 20180313
@author: Matthew
"""
from numpy import prod
class Position():
'''
each stock that was being bought has a position,
one stock is matched with one position,
account can have 0 to multiple positions,
one stock can remain in position for 5 days, so this position has a recored of this stock object of 5 days
it is easier this way to calculate the real growth or drop-down over a certain period.
after sold it, position is cleared, position is not in account as well
'''
def __init__(self,stock,boughtAmount,price):
self.stock = stock
self.TradeDate = stock.TradeDate
self.boughtAmount = boughtAmount
self.SecuCode = stock.SecuCode
self.boughtPrice = price
self.initialValue = boughtAmount * price
self.positionValue = self.initialValue
self.TradeStatus = stock.TradeStatus
self.PreClosePrice = stock.PreClosePrice
self.ClosePrice = stock.ClosePrice
self.RiseOrDown = stock.RiseOrDown
#entering account
self.isinAccount = True
self.remainRecord = [stock]
def leaveAccount(self):
self.isinAccont = False
self.remainRecord.clear()
def remainInAccount(self,stock,method):
'''
method 1|2 to update the Real positionValue using method 1 or 2
'''
self.remainRecord.append(stock)
#print([x.SecuCode for x in self.remainRecord])
#print([x.ClosePrice for x in self.remainRecord])
#print([type(x.TradeStatus) for x in self.remainRecord])
#print([x.PreClosePrice for x in self.remainRecord])
if method == 1:
self.updatePositionValueMethod1()
elif method == 2:
self.updatePositionValueMethod2()
def updatePositionValueMethod1(self):
'''
买入的价格是买入的总市值除以买入时候的股本,用当前总市值除以买入时候的股本,就得到今日的价格,
当然这个价格和实际的而价格肯定不一样,但是要算涨幅的话是绰绰有余了。
参考浦发银行
同花顺的价格:
除权
2015-05-05 17.08
2018-03-15 12.38
前复权
2015-05-05 10.09
2018-03-15 12.39
实际涨幅为 (12.39-10.09)/10.09 = 22.79%
益盟的复权价格:
2015-05-05 FClosePrice 119.4343
2018-03-15 FClosePrice 127.8294
涨幅是 7.029%
Method 1
2015-05-05 总股本 18653471488.0000 总市值 318601293015.0000
2018-03-15 总股本 29352079872.0000 总市值 363672269614.0000
按照Method1 涨幅为 (318601293015.0000/18653471488.0000 - 363672269614.0000/18653471488.0000) 除以 363672269614.0000/18653471488.0000
= ( 318601293015.0000 - 363672269614.0000 ) / 363672269614.0000
= 14.14%
可以看出 this is obviously Wrong.... 涨幅不是总市值的涨幅
比较准确的算法:Method2
可以知道每日的涨幅,用(Close-PreClose)PreClose,然后用买入价格*(1+涨幅)*(1+涨幅).... 算出今日的价格,然后算出整个事件窗口的涨幅,
记得要剔除无法交易的日子。这样算出来的涨幅是6.14%
记得今日的涨幅是昨收和今收的涨幅,而不是今收和今收的涨幅,所以涨幅一定是某日收盘价和基准日的昨收价格比较
'''
initial = self.remainRecord[0]
current = self.remainRecord[-1]
initialPrice = initial.TotalValue/initial.TotalEquity
currentPrice = current.TotalValue/initial.TotalEquity
#print('initialPrice.TotalValue,initialPrice.TotalEquity',initial.TotalValue,' ',initial.TotalEquity)
#print('current.TotalValue,current.TotalEquity',current.TotalValue,' ',current.TotalEquity)
#print('initialPrice,currentPrice',initialPrice,' ',currentPrice)
growth = (currentPrice - initialPrice) / initialPrice
#print('method 1 growth', growth)
self.positionValue = self.positionValue * ( 1 + growth)
def updatePositionValueMethod2(self):
'''
[12,11,13,6] just sum the changeRatio of each day, don't need to consider 除权 issue
假设所有的涨幅都按照( 今收-昨收/昨收) 来算,其实现实可能不是这样,如果今开买入,涨幅显然就不同了
'''
changeReal = []
for x in self.remainRecord[:-1]: #
#print(type(x),x.__dict__)
if x.TradeStatus == '1':
if x.PreClosePrice == 0:
changeReal.append( 1 + x.ChangeRatio )
else:
changeReal.append( 1 + (x.ClosePrice - x.PreClosePrice)/x.PreClosePrice )
#print('changeReal',changeReal)
#print([x.ChangeRatio for x in self.remainRecord])
#print('method 2 growth', growth)
#记得今日的涨幅是昨收和今收的涨幅,而不是今收和今收的涨幅,所以涨幅一定是某日收盘价和基准日的昨收价格比较
#print('changeReal',changeReal)
#print('prod(changeReal)', prod(changeReal),' len: ',len(changeReal))
self.positionValue = self.initialValue * prod(changeReal)
def updatePositionValue(self,stock,tradingHabit):
self.positionValue = self.boughtAmount * stock.OpenPrice if tradingHabit == 'OpenPrice' else self.boughtAmount * stock.ClosePrice
def getPositionValue(self):
return self.positionValue
def findRightDate(oneDay,option):
'''
根据oneDay和option找出最近的一期(几期)财报
option = '最近三年','最近一年','最近一期'
比如
oneDay = '2014-12-30'
option = '最近三年'
则返回 ['2013-12-31','2012-12-31','2011-12-30']
'''
reportDateList = ['03-31','06-30','09-30','12-31']
#fisrtYear = oneDay[:4]
#recentMonthDay = oneDay[5:]
#recentReportDate = recentYear + '-' + [x for x in reportDateList if oneDay[5:] > x][0]
if option == '最近三年':
if '12-31' not in oneDay:
firstYear = str(eval('int(oneDay[:4]) - 1')) + '-' + '12-31'
secondYear = str(eval('int(oneDay[:4]) - 2')) + '-' + '12-31'
thirdYear = str(eval('int(oneDay[:4]) - 3')) + '-' + '12-31'
fourthYear = str(eval('int(oneDay[:4]) - 4')) + '-' + '12-31' # 多加一年,保险起见
else:
firstYear = oneDay
secondYear = str(eval('int(firstYear[:4]) - 1')) + '-' + '12-31'
thirdYear = str(eval('int(firstYear[:4]) - 2')) + '-' + '12-31'
fourthYear = str(eval('int(firstYear[:4]) - 3')) + '-' + '12-31'
return [firstYear,secondYear,thirdYear,fourthYear]
elif option == '最近一年':
if '12-31' not in oneDay:
firstYear = str(eval('int(oneDay[:4]) - 1')) + '-' + '12-31'
secondYear = str(eval('int(oneDay[:4]) - 2')) + '-' + '12-31'
else:
firstYear = oneDay
secondYear = str(eval('int(firstYear[:4]) - 1')) + '-' + [x for x in reportDateList if firstYear[5:] > x][0]
return [firstYear,secondYear]
elif option == '最近一期':
if oneDay[5:] not in reportDateList:
if oneDay[5:] < reportDateList[0]: #'01-02' < '03-31'
firstYear = str(eval('int(oneDay[:4]) - 1'))
firstPeriod = firstYear + '-' + reportDateList[-1]
secondPeriod = firstYear + '-' + reportDateList[-2]
elif oneDay[5:] < reportDateList[1]: #'04-05' < '06-30'
firstYear = oneDay[:4]
firstPeriod = firstYear + '-' + reportDateList[0]
secondPeriod = str(eval('int(firstYear) - 1'))+ '-' + reportDateList[3]
else:
firstYear = oneDay[:4]
#print('test: ',[x for x in reportDateList if oneDay[5:] > x])
firstPeriod = firstYear + '-' + [x for x in reportDateList if oneDay[5:] > x][-1]
secondPeriod = firstYear + '-' + [x for x in reportDateList if oneDay[5:] > x][-2]
else: #oneDay = '2015-03-31' or '2016-12-31'
if oneDay[5:] == '03-31':
firstPeriod = oneDay
secondPeriod = str(eval('int(oneDay[:4]) - 1')) + '-' + '12-31'
else:
firstPeriod = oneDay
secondPeriod = oneDay[:4] + '-' + [x for x in reportDateList if oneDay[5:] > x][-1]
return [firstPeriod,secondPeriod]
else:
raise ValueError('输入要是最近一期,最近一年,最近三年,请检查Json的输入')
oneDay = '2015-12-31'
option = '最近一年'
print(findRightDate(oneDay,option))
KYBT: KuaiYuBackTesting
交易时候用真实价格交易,算涨幅可以
0直接每日的涨跌幅相加,很方便,这是粗略的,可以看看有多粗略,
1用昨日的收盘价和涨跌幅算出今日的收盘价(假设今日除权了)
2算相应时间段的后复权涨幅
3买入的价格是买入的总市值除以买入时候的股本,用当前总市值除以买入时候的股本,就得到今日的价格,当然这个价格和实际的而价格肯定不一样,但是要算涨幅的话是绰绰有余了。
need to know the index pool that makes up the index
1\ 测试工具 任务调度 模拟很多人跑 3月25日之前(周日)弄好,4月之前确保益盟好了,我们立马就好
1\account PrintMe
2\cash < 0, @property
3\calculate zhangfu
1\ the redis server\clientAPI server\Robot should be on at the very first
4 处理停牌无法卖出,涨停无法买入,跌停无法卖出
5 benchmark
6 持仓分析
7 Method1 has issue
8 开盘前跌停无法卖出,但是还没有考虑若之后打开跌停,可以卖出的情况。 涨停买入也一样
9 假设所有的涨幅都按照( 今收-昨收/昨收) 来算 updatePositionValueMethod2
10 @Property 把能用的地儿都用到
11 周线、年线运行、
12 没有考虑手续费
13 一个股票要卖 就全卖
14 用进程有用,线程没用
15 财报用publish date 不用{'Jan':'01-01','Apr':'04-01','Jul':'07-01','Oct':'10-01'} 而是用和这些基准最接近的那个publish date
16 每一个表分成一个类
17
CY_FinacialRatio_RP 我武生物 为例 上市是2014年1月21日(1月21日开始有K线)
18 添加交易记录
19 获取交易日期的得用YM数据库的
20 一次性读取所有的数据,放在内存里面,把内存当数据库,以后机器人读取就只需要读取内存的数据了,这样就飞快
21 merge API into oneAPI
22 finish objecting SQL, then create a strategy
23 整个运作流程写好,API写好,数据库格式说清楚,和益盟对接
24 当天卖掉就立即买入,净值不应该有尖头波动,调仓动作(先卖再买)是在同一时刻完成的,
25 改变程序的运行方式,不要每次读数据;而是一次性根据用户Json读取数据,
26 股票分红的当天,股价会相应的降低的;当日实际开盘价 + 分红/股数 = 当日不分红开盘价
27 learn APIstar mother fuck!
28 account 把marketValueAPI 删除掉
29 选股要针对日期来选,加上此功能
30 补充所有的指标 dataTable里面
31 在engine2 DateList 最近三年
32 261 bulk['EM_QUOTE_INDEX_DAILY'] = self.getIndexData('HS300',startDate,endDate)
33 20130704 君正集团没有bar,数据缺失 在account简单处理了 x.positionValue = 0
34 校验Json 在clientApi那里
35 需要检查之前是否跑过此策略
36 根据Json来确定唯一的编码
37 裸API 断线重连
则应该把上市之日前的财报数据都删掉 以pubDate为准
endDate pubDate
2017-12-31 00:00:00.000 2018-03-15 00:00:00.000
2017-09-30 00:00:00.000 2017-10-26 00:00:00.000
2017-06-30 00:00:00.000 2017-08-08 00:00:00.000
2017-03-31 00:00:00.000 2017-04-26 00:00:00.000
2016-12-31 00:00:00.000 2018-03-15 00:00:00.000 有问题
2016-12-31 00:00:00.000 2017-02-09 12:00:00.000
2016-09-30 00:00:00.000 2017-10-26 00:00:00.000
2016-06-30 00:00:00.000 2017-08-08 00:00:00.000
2016-03-31 00:00:00.000 2017-04-26 00:00:00.000
2015-12-31 00:00:00.000 2017-04-26 00:00:00.000 有问题
2015-12-31 00:00:00.000 2016-02-26 12:00:00.000
2015-09-30 00:00:00.000 2016-10-28 00:00:00.000
2015-06-30 00:00:00.000 2016-08-26 00:00:00.000
2015-03-31 00:00:00.000 2016-04-22 00:00:00.000
2014-12-31 00:00:00.000 2016-04-08 00:00:00.000 有问题
2014-09-30 00:00:00.000 2015-10-30 00:00:00.000
2014-06-30 00:00:00.000 2015-08-12 00:00:00.000
2014-03-31 00:00:00.000 2015-04-23 00:00:00.000
2013-12-31 00:00:00.000 2014-04-18 00:00:00.000
2013-12-31 00:00:00.000 2014-01-20 00:00:00.000
2013-06-30 00:00:00.000 2013-12-31 00:00:00.000
2012-12-31 00:00:00.000 2013-12-31 00:00:00.000
2011-12-31 00:00:00.000 2013-12-31 00:00:00.000
2010-12-31 00:00:00.000 2013-12-31 00:00:00.000
2009-12-31 00:00:00.000 2012-05-04 00:00:00.000
这些有问题的数据怎么办?艹 没法用,得用原始三表中的公布日期,那么暂时就用标准日期来运行吧、下一个版本再完善。
ISSUE
因为获取的成分股都是最新一期的,那么用这些成分股去取历史中的股票,就可能不存在。
比如上证50的最新的成分股有江苏银行,但是历史上取不到这只股票,因为那时候还没有发行。
所以取50只股票,有可能取不满50只。 比如某一天之前没有江苏银行,交易的时候没有,某一天起,突然有了,
那也不能凭空把江苏银行加入到持仓中,所以held需要持仓中的票来held,
请求的字段:
请求的字段:
{
"strategy_id": 45534, //必须
"start":0, //必须,表示请求从第几个周期开始的数据
"end":0 //可选,表示请求区间的结束下标
}
返回的字段:
{
"strategy_id":'544234',
"status":0, //0表示数据未生成,1表示数据生成中,2表示数据已经生成完毕
"length":10332, //本策略的总周期数,用于画出x轴长度
"start": "0", //数据开始标记
"end": "50", //数据结束标记
"data":[ //根据请求的起始和结束下表,返回区间的数据
{
"x":"1999-01-03",
"y":{
"pot..":0.4,
"cash":0.3,
...
}
},
{
"x":"1999-01-04",
"y":{
"pot..":0.4,
"cash":0.3,
...
},
},
...
]
}
\ No newline at end of file
https://guorn.com/stock?category=stock
https://guorn.com/stock?category=stock
https://www.fundsmart.com.cn/stock/screener
# encoding: utf-8
from threading import Thread
import time
import datetime
import redis
import sys
'''
from .server.redisConfig import redisConf,jsonList
from .BT import engine2
from .util.kySDK import *
from .BT.evaluator import evaluator
'''
import os
#sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
#print(sys.path)
from .server.redisConfig import redisConf,jsonList
from .BT.engine2 import Engine
from .util.kySDK import *
from .BT.evaluator import evaluator
import logging
logger = logging.getLogger(__name__)
logger.setLevel(logging.CRITICAL)
import multiprocessing as mp
class BTRobot():
def __init__(self):
self.r = redis.StrictRedis(host=redisConf['host'], port=redisConf['port'], db=0)
self.robotNum = 0
def cleanQueue(self):
print('先清空队列,队列长度为: %d'%self.r.llen(jsonList))
while self.r.llen(jsonList) != 0:
self.r.rpop(jsonList)
def process_task(self):
# 从队列中取参数
while True:
try:
params = self.r.brpop(jsonList)
params = eval(params[1].decode())
print('params',type(params),params)
myBT = Engine(params) #initialize engine
if myBT.stockPicker['pick'] == False:
myBT.backTesting()
evaluator(myBT.strategyID,myBT.BTRecords,myBT.IndexRecords,plot = False)
elif myBT.stockPicker['pick'] == True:
for day in myBT.stockPicker['dateList']:
myBT.stockPicking(day) #是选的哪一天的???
except Exception as e:
print(e)
def turnOn(self,processNum):
self.cleanQueue()
print('开启 %d 个机器人'%processNum)
processes = [mp.Process(target=self.process_task()) for x in range(processNum)]
# Run processes
for p in processes:
p.start()
# Exit the completed processes
for p in processes:
p.join()
if __name__ == '__main__':
myRobot = BTRobot()
myRobot.turnOn(20)
# encoding: utf-8
from apistar import Route, App
import redis
from .redisConfig import redisConf,jsonList
from apistar import http
import pyodbc
r = redis.StrictRedis(host=redisConf['host'], port=redisConf['port'])
import json
"""
API 设计
========================================================
"""
# API 接收用户选股参数 post
class clientAPI():
DBcnxn = pyodbc.connect(DSN = 'TEST')
DBcursor = DBcnxn.cursor()
def __init__(self):
pass
class CORSMiddleware(App):
"""Add 跨域访问 Cross-origin resource sharing headers to every request."""
def __init__(self, origin='*', **kwargs):
super().__init__(**kwargs)
self.origin = origin
def __call__(self, environ, start_response):
def add_cors_headers(status, headers, exc_info=None):
headers = http.Headers(headers)
headers.add("Access-Control-Allow-Origin", self.origin) # 跨域访问
headers.add("Access-Control-Allow-Headers", "Origin, Content-Type, Authorization")
headers.add("Access-Control-Allow-Credentials", "true")
headers.add("Access-Control-Allow-Methods", "GET , POST, OPTIONS") # 跨域访问
return start_response(status, headers.to_list())
if environ.get("REQUEST_METHOD") == "OPTIONS": # 跨域访问
#add_cors_headers("200 OK", [("Access-Control-Allow-Origin", "*"),("Access-Control-Allow-Methods","GET, PUT, POST, DELETE")])
add_cors_headers("200 OK", [("Best-NBA-player","LeBron James")])
return [b'200 OK']
return super().__call__(environ, add_cors_headers)
def checkDict(self,mydict):
# 需要检查策略ID的唯一性,和数据库中的所有策略对照
print('\ncheckDict: ',type(mydict),mydict)
findStrategyIDCommand = 'select DISTINCT(strategyID) from BT.[dbo].BTrecords'
self.DBcursor.execute(findStrategyIDCommand)
raw1 = self.DBcursor.fetchall()
#print('checkDict',type([x[0] for x in raw1]),[x[0] for x in raw1])
if mydict['strategyID'] in [x[0] for x in raw1]:
print('已经跑过的策略')
def strategyParams(self,request: http.Request)-> http.JSONResponse: #post
"""接收策略参数"""
print('-----------------------------------接收策略参数------------------------------------------------')
print('\n...',type(request.body.decode('utf-8')),request.body.decode('utf-8'))
print('end')
mydict = json.loads(request.body.decode('utf-8'))
#print('type of mydict',type(mydict))
with open('./postedID.txt','a+') as f:
f.write(mydict['strategyID'])
f.write('\n')
if isinstance(mydict,str):
mydict = json.loads(mydict)
#checkDict(mydict)
r.lpush(jsonList, str(mydict)) # myJson is the type of str
#headers = {'Access-Control-Allow-origin':'*','Access-Control-Allow-Methods': 'GET, POST, OPTIONS'} # 跨域访问
return http.JSONResponse(mydict,status_code=200, headers={})
#return str(mydict)
# API2 获取策略的运行结果 get
def strategyResults(self,strategyID,start,end = 0):
'''
end 可选
"""返回策略运行结果"""
0 strategyID VARCHAR(255),
1 status VARCHAR(255)),
2 startDate VARCHAR(255),
3 endDate VARCHAR(255),
4 length VARCHAR(255),
5 btdate VARCHAR(255),
6 positionList VARCHAR(255),
7 cash VARCHAR(255),
8 positionListValue VARCHAR(255),
9 totalValue VARCHAR(255),
10 tradingDayAPI VARCHAR(8000);
请求的字段:
{
"strategy_id": 45534, //必须
"start":0, //必须,表示请求从第几个周期开始的数据
"end":0 //可选,表示请求区间的结束下标
}
'''
qur = "select top 1 * from BT.[dbo].BTrecords where strategyID = '%s' "%(strategyID)
#print(qur)
self.DBcursor.execute(qur)
raw1 = self.DBcursor.fetchall()
if len(eval(str(raw1))) == 0:
return http.JSONResponse(json.dumps(None),status_code=200, headers={})
for l in eval(str(raw1)):
length = l[4]
startDate = l[2]
endDate = l[3]
status = l[1]
tradingDates = eval(l[10])
start = int(start)
end = int(end)
length = int(length)
if start <= 0:
pickStartDate = startDate
elif start < length:
pickStartDate = tradingDates[start]
else:
pickStartDate = endDate
if end <= 0:
pickEndDate = endDate
elif end < length:
pickEndDate = tradingDates[end]
else:
pickEndDate = endDate
#items = 'btdate,positionList,cash,positionListValue,totalValue,strategyID'
query = "select * from BT.[dbo].BTrecords where strategyID = '%s' and btdate >= '%s' and btdate <= '%s' order by btdate"%(
strategyID,pickStartDate,pickEndDate)
#print(query)
self.DBcursor.execute(query)
#DBcursor.execute('select * from BTrecords')
raw = self.DBcursor.fetchall()
dataList = list()
for ll in eval(str(raw)):
tempDict = dict()
tempDict['btdate'] = ll[5]
tempDict['positionList'] = ll[6]
tempDict['cash'] = ll[7]
tempDict['positionListValue'] = ll[8]
tempDict['totalValue'] = ll[9]
dataList.append(tempDict)
end = start + len(dataList) # tell user how much data will be sent
mydict = dict()
mydict['strategy_id'] = list()
mydict['status'] = status
mydict['length'] = length
mydict['start'] = start
mydict['end'] = end
mydict['data'] = dataList
#headers = {'Access-Control-Allow-origin':'*','Access-Control-Allow-Methods': 'GET, POST, OPTIONS'} # 跨域访问
return http.JSONResponse(mydict,status_code=200, headers={})
#return json.dumps(mydict,ensure_ascii=False)
def serve(self):
routes = [
Route('/p', "POST", self.strategyParams),
Route('/g', "GET", self.strategyResults),
]
#app = App(routes=routes)
#app = App(routes=routes, event_hooks=event_hooks)+
app = self.CORSMiddleware(
origin='*',
routes=routes,
)
app.serve('0.0.0.0',8080,use_debugger=True,use_reloader=True)
if __name__ == "__main__":
myserver = clientAPI()
myserver.serve()
# encoding: utf-8
from apistar import Route, App
import redis
from redisConfig import redisConf,jsonList
from apistar import http
import pyodbc
r = redis.StrictRedis(host=redisConf['host'], port=redisConf['port'])
import json
#from apistar.frameworks.wsgi import WSGIApp as App
#from wsgicors import CORS
#class CORSApp(App):
# def __call__(self, environ, start_response):
# cors = CORS(super().__call__, headers='*', methods='*', maxage='180', origin='*')
# return cors(environ, start_response)
"""
API 设计
========================================================
"""
global DBcnxn,DBcursor
DBcnxn = pyodbc.connect(DSN = 'TEST')
DBcursor = DBcnxn.cursor()
# API 接收用户选股参数 post
class CORSMiddleware(App):
"""Add Cross-origin resource sharing headers to every request."""
def __init__(self, origin='*', **kwargs):
super().__init__(**kwargs)
self.origin = origin
def __call__(self, environ, start_response):
def add_cors_headers(status, headers, exc_info=None):
headers = http.Headers(headers)
headers.add("Access-Control-Allow-Origin", self.origin)
headers.add("Access-Control-Allow-Headers", "Origin, Content-Type, Authorization")
headers.add("Access-Control-Allow-Credentials", "true")
headers.add("Access-Control-Allow-Methods", "GET , POST, OPTIONS")
return start_response(status, headers.to_list())
if environ.get("REQUEST_METHOD") == "OPTIONS":
#add_cors_headers("200 OK", [("Access-Control-Allow-Origin", "*"),("Access-Control-Allow-Methods","GET, PUT, POST, DELETE")])
add_cors_headers("200 OK", [("Best-NBA-player","James")])
return [b'200 OK']
return super().__call__(environ, add_cors_headers)
class CustomHeadersHook():
def on_response(self, response: http.Response):
response.headers['Access-Control-Allow-origin'] = '*'
response.headers['Access-Control-Allow-Method'] = 'POST,GET,OPTIONS'
return response
#def on_request(self, request: http.Request):
# request.headers['Access-Control-Allow-origin'] = '*'
event_hooks = [CustomHeadersHook()]
def checkDict(mydict):
# 需要检查策略ID的唯一性,和数据库中的所有策略对照
print('\ncheckDict: ',type(mydict),mydict)
findStrategyIDCommand = 'select DISTINCT(strategyID) from BT.[dbo].BTrecords'
DBcursor.execute(findStrategyIDCommand)
raw1 = DBcursor.fetchall()
#print('checkDict',type([x[0] for x in raw1]),[x[0] for x in raw1])
if mydict['strategyID'] in [x[0] for x in raw1]:
print('已经跑过的策略')
def strategy_params(request: http.Request)-> http.JSONResponse: #post
"""接收策略参数"""
print('-----------------------------------接收策略参数------------------------------------------------')
print('\n...',type(request.body.decode('utf-8')),request.body.decode('utf-8'))
print('end')
mydict = json.loads(request.body.decode('utf-8'))
#print('type of mydict',type(mydict))
with open('./postedID.txt','a+') as f:
f.write(mydict['strategyID'])
f.write('\n')
if isinstance(mydict,str):
mydict = json.loads(mydict)
#checkDict(mydict)
r.lpush(jsonList, str(mydict)) # myJson is the type of str
#headers = {'Access-Control-Allow-origin':'*','Access-Control-Allow-Methods': 'GET, POST, OPTIONS'} # 跨域访问
return http.JSONResponse(mydict,status_code=200, headers={})
#return str(mydict)
# API2 获取策略的运行结果 get
def strategy_results(strategyID,start,end = 0):
'''
end 可选
"""返回策略运行结果"""
0 strategyID VARCHAR(255),
1 status VARCHAR(255)),
2 startDate VARCHAR(255),
3 endDate VARCHAR(255),
4 length VARCHAR(255),
5 btdate VARCHAR(255),
6 positionList VARCHAR(255),
7 cash VARCHAR(255),
8 positionListValue VARCHAR(255),
9 totalValue VARCHAR(255),
10 tradingDayAPI VARCHAR(8000);
请求的字段:
{
"strategy_id": 45534, //必须
"start":0, //必须,表示请求从第几个周期开始的数据
"end":0 //可选,表示请求区间的结束下标
}
'''
qur = "select top 1 * from BT.[dbo].BTrecords where strategyID = '%s' "%(strategyID)
#print(qur)
DBcursor.execute(qur)
raw1 = DBcursor.fetchall()
if len(eval(str(raw1))) == 0:
return http.JSONResponse(json.dumps(None),status_code=200, headers={})
for l in eval(str(raw1)):
length = l[4]
startDate = l[2]
endDate = l[3]
status = l[1]
tradingDates = eval(l[10])
start = int(start)
end = int(end)
length = int(length)
if start <= 0:
pickStartDate = startDate
elif start < length:
pickStartDate = tradingDates[start]
else:
pickStartDate = endDate
if end <= 0:
pickEndDate = endDate
elif end < length:
pickEndDate = tradingDates[end]
else:
pickEndDate = endDate
#items = 'btdate,positionList,cash,positionListValue,totalValue,strategyID'
query = "select * from BT.[dbo].BTrecords where strategyID = '%s' and btdate >= '%s' and btdate <= '%s' order by btdate"%(
strategyID,pickStartDate,pickEndDate)
#print(query)
DBcursor.execute(query)
#DBcursor.execute('select * from BTrecords')
raw = DBcursor.fetchall()
dataList = list()
for ll in eval(str(raw)):
tempDict = dict()
tempDict['btdate'] = ll[5]
tempDict['positionList'] = ll[6]
tempDict['cash'] = ll[7]
tempDict['positionListValue'] = ll[8]
tempDict['totalValue'] = ll[9]
dataList.append(tempDict)
end = start + len(dataList) # tell user how much data will be sent
mydict = dict()
mydict['strategy_id'] = list()
mydict['status'] = status
mydict['length'] = length
mydict['start'] = start
mydict['end'] = end
mydict['data'] = dataList
headers = {'Access-Control-Allow-origin':'*','Access-Control-Allow-Methods': 'GET, POST, OPTIONS'} # 跨域访问
return http.JSONResponse(mydict,status_code=200, headers={})
#return json.dumps(mydict,ensure_ascii=False)
routes = [
Route('/p', "POST", strategy_params),
Route('/g', "GET", strategy_results),
]
#app = App(routes=routes)
#app = App(routes=routes, event_hooks=event_hooks)+
app = CORSMiddleware(
origin='*',
routes=routes,
)
if __name__ == "__main__":
app.serve('0.0.0.0',8080,use_debugger=True,use_reloader=True)
# 可视化回测子任务 - 并发队列、交互API、DB
## 开发环境准备
1. 安装redis数据库
windows参考:https://github.com/MicrosoftArchive/redis
2. python 3.6.2 + pip install -r requirements.txt
in console
python api.py run
\ No newline at end of file
# encoding: utf-8
redisConf = {
"host": "localhost",
"port": "6379"
}
jsonList = 'JsonList' # 队列参数列表
# encoding: utf-8
from apistar import Route, App
import redis
from redisConfig import redisConf,jsonList
from apistar import http
import pyodbc
import json
r = redis.StrictRedis(host=redisConf['host'], port=redisConf['port'])
"""
API 设计
========================================================
"""
# API 接收用户选股参数 post
def checkDict(mydict):
mydict = (mydict)
for key in mydict:
print('mmm',mydict[key]['stockPicker']['pick'],type(mydict[key]['stockPicker']['pick']))
#if mydict[key]['stockPicker']['pick'] == 'true'
#if mydict[key]['criteriaDcit']
return
def strategy_params(request: http.Request)-> http.JSONResponse:
"""接收策略参数"""
#print('-----------------------------------clientAPI------------------------------------------------')
mydict = json.loads(str(request.body.decode('utf-8')))
checkDict(mydict)
r.lpush(jsonList, str(mydict)) # myJson is the type of str
return str(mydict)
# API2 获取策略的运行结果 get
def strategy_results(strategyID):
"""返回策略运行结果"""
DBcnxn = pyodbc.connect(DSN = 'TEST',autocommit=True)
DBcursor = DBcnxn.cursor()
items = 'oneDay,positionList,cash,positionListValue,totalValue,strategyID'
DBcursor.execute('select %s from BTrecords items where strategyID = %s'%(items,strategyID))
raw = DBcursor.fetchall()
print(raw)
return raw
routes = [
Route('/p', "POST", strategy_params),
Route('/g', "GET", strategy_results),
]
app = App(routes=routes)
if __name__ == "__main__":
app.serve('0.0.0.0',8080,use_debugger=False)
import ky
sdk = ky.Api("http://data-api.kuaiyutech.com/api.rpc")
import datetime
def getIndexPoolFromKy(index):
return sdk.get_symbols_by_index(index)
if __name__ == '__main__':
pass
\ No newline at end of file
if not exists(select * from sys.databases where name = 'BT')
CREATE database BT;
IF EXISTS (SELECT * FROM BT.INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = N'BTrecords')
create table BT.BTrecords(
btdate TEXT,
positionList VARCHAR(255),
cash VARCHAR(255),
positionListValue VARCHAR(255),
totalValue VARCHAR(255),
strategyID VARCHAR(255) primary key
);
Insert into BT.BTrecords (btdate,positionList,positionListValue,totalValue,strategyID) values ('2015-05-05',1,1,1,'3')
# 这是sql创建DB,table,删除,insert的学习
import pyodbc
DBcnxn = pyodbc.connect(DSN = 'TEST',autocommit=True)
DBcursor = DBcnxn.cursor()
createDBcommand = \
'''
if not exists(select * from sys.databases where name = N'BT')
BEGIN
CREATE database BT;
END
'''
createTableCommand = """
IF NOT EXISTS (SELECT * FROM BT.INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = N'BTrecords')
begin
create table BT.[dbo].BTrecords(
btdate VARCHAR(255),
positionList VARCHAR(255),
cash VARCHAR(255),
positionListValue VARCHAR(255),
totalValue VARCHAR(255),
strategyID VARCHAR(255));
end
"""
#DBcursor.execute(createCommand)
dropTableCommand = """
IF EXISTS (SELECT * FROM BT.INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = N'BTrecords')
begin
drop table BT.[dbo].BTrecords;
end
"""
#DBcursor.execute(dropCommand)
DBcursor.execute(createDBcommand + createTableCommand )
#print(DBcursor.fetchall())
#insertCommand = "Insert into BT.[dbo].BTrecords (btdate,positionList,cash,positionListValue,totalValue,strategyID) values (%s,%0.2f,%0.2f,%0.2f,%0.2f,%s);"%\
('2015-05-05',2,1222,32,12312,'1000')
insertCommand = "INSERT INTO BT.dbo.BTrecords VALUES (%s,%0.0f,%0.2f,%0.2f,%0.2f,%s);"%('2015-05-05',2,1222,32,12312,'1000')
print(insertCommand)
DBcursor.execute(insertCommand)
DBcursor.execute('select * from BT.dbo.BTrecords')
raw = DBcursor.fetchall()
print(raw)
from KYBT import robot
import multiprocessing as mp
if __name__ == '__main__':
myRobot = robot.BTRobot()
myRobot.turnOn(20)
from KYBT.server import clientAPI
if __name__ == "__main__":
myserver = clientAPI.clientAPI()
myserver.serve()
\ No newline at end of file
5
5
306179
5
403436
90668
205596
191134
460572
972725
57305
63785
662441
128579
754058
640397
718725
816451
942501
5
5
5
from KYBT.API import marketValueAPI
import logging
logger = logging.getLogger(__name__)
logger.setLevel(logging.CRITICAL)
myAPI = marketValueAPI.API()
stockList = myAPI.getHS300Name()
for stock in stockList:
logger.critical(stock)
myAPI.getMarketValueOneStock('2015-05-05','2016-05-05',stock)
# try thread and multiprocess on YMDB
from KYBT.API import marketValueAPI
portforlio = ['600000','000002','600485'] # 'all'|'HS300'|'SZ500'|'SZ50'|['600000','000002',...]
portforlio = 'all'
stockID = '300357'
startDate = '2014-01-10'
endDate = '2018-11-01'
sdk = marketValueAPI.API()
data1 = sdk.getMarketValueOneStock(startDate,endDate,stockID)
data2 = sdk.getMarketValueOneDay(startDate,portforlio)
from multiprocessing import Pool
import os, time, random
def getData(name):
print('Run task %s (%s)...' % (name, os.getpid()))
sdk = marketValueAPI.API()
data1 = sdk.getMarketValueOneStock(startDate,endDate,stockID)
data2 = sdk.getMarketValueOneDay(startDate,portforlio)
#print(data2)
def long_time_task(name):
print('Run task %s (%s)...' % (name, os.getpid()))
start = time.time()
time.sleep(random.random() * 3)
end = time.time()
print('Task %s runs %0.2f seconds.' % (name, (end - start)))
if __name__=='__main__':
print('Parent process %s.' % os.getpid())
p = Pool()
for i in range(5):
p.apply_async(long_time_task, args=(i,))
#p.apply_async(getData, args=(i,))
print('Waiting for all subprocesses done...')
p.close()
p.join()
print('All subprocesses done.')
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册登录 后发表评论