hqchart 1.1.12687 → 1.1.12706
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/umychart.vue.js +94 -50
- package/package.json +15 -47
- package/src/jscommon/umychart.resource/js/codemirror/javascript.js +1 -1
- package/src/jscommon/umychart.uniapp.h5/umychart.uniapp.h5.js +409 -115
- package/src/jscommon/umychart.vue/umychart.vue.js +409 -115
- package/.babelrc +0 -6
- package/.vscode/settings.json +0 -4
- package/Makefile +0 -9
- package/README.md +0 -452
- package/index.js +0 -17
- package/postcss.config.js +0 -5
- package/src/index.html +0 -18
- package/src/jscommon/backup/announcement.png +0 -0
- package/src/jscommon/backup/announcement2.png +0 -0
- package/src/jscommon/backup/blocktrading.png +0 -0
- package/src/jscommon/backup/investor.png +0 -0
- package/src/jscommon/backup/pforecast.png +0 -0
- package/src/jscommon/backup/research.png +0 -0
- package/src/jscommon/backup/tradedetail.png +0 -0
- package/src/jscommon/backup/umychart - backup.js +0 -17631
- package/src/jscommon/backup/umychart.macro.js +0 -4
- package/src/jscommon/backup/umychart.macro.vue.js +0 -3
- package/src/jscommon/commonindextree.json +0 -92
- package/src/jscommon/index.html +0 -13
- package/src/jscommon/jschinamapdata.js +0 -3
- package/src/jscommon/umychart.NetworkFilterTest.js +0 -48803
- package/src/jscommon/umychart.aliYunnetwork.js +0 -47
- package/src/jscommon/umychart.cninfo.components/readme.txt +0 -1
- package/src/jscommon/umychart.complier.js +0 -25291
- package/src/jscommon/umychart.complier.node/umychart.complier.controller.js +0 -559
- package/src/jscommon/umychart.complier.node/umychart.complier.node.js +0 -7043
- package/src/jscommon/umychart.complier.node/umychart.data.node.js +0 -816
- package/src/jscommon/umychart.console.js +0 -12
- package/src/jscommon/umychart.deal.js +0 -1452
- package/src/jscommon/umychart.dragdiv.js +0 -48
- package/src/jscommon/umychart.index.data.js +0 -4132
- package/src/jscommon/umychart.js +0 -90257
- package/src/jscommon/umychart.keyboard.js +0 -1659
- package/src/jscommon/umychart.listctrl.js +0 -690
- package/src/jscommon/umychart.mind.js +0 -2203
- package/src/jscommon/umychart.network.js +0 -44
- package/src/jscommon/umychart.news.js +0 -823
- package/src/jscommon/umychart.node.build/buildall.bat +0 -1
- package/src/jscommon/umychart.node.build/umychart.node.bat +0 -1
- package/src/jscommon/umychart.node.build/umychart.node.export.js +0 -40
- package/src/jscommon/umychart.regressiontest.js +0 -400
- package/src/jscommon/umychart.report.js +0 -5803
- package/src/jscommon/umychart.scrollbar.js +0 -1345
- package/src/jscommon/umychart.stock.js +0 -4218
- package/src/jscommon/umychart.style.js +0 -618
- package/src/jscommon/umychart.testdata.js +0 -150
- package/src/jscommon/umychart.uniapp.build/buildall.bat +0 -1
- package/src/jscommon/umychart.uniapp.build/umychart.bat +0 -1
- package/src/jscommon/umychart.uniapp.build/umychart.export.js +0 -70
- package/src/jscommon/umychart.user.js +0 -137
- package/src/jscommon/umychart.version.js +0 -30
- package/src/jscommon/umychart.vue/umychart.aliYunnetwork.vue.js +0 -56
- package/src/jscommon/umychart.vue.build/buildall.bat +0 -4
- package/src/jscommon/umychart.vue.build/copy_codemirror.bat +0 -2
- package/src/jscommon/umychart.vue.build/umychart.aliYunnetwork.vue.export.js +0 -9
- package/src/jscommon/umychart.vue.build/umychart.dragdiv.bat +0 -1
- package/src/jscommon/umychart.vue.build/umychart.dragdiv.export.js +0 -6
- package/src/jscommon/umychart.vue.build/umychart.index.data.bat +0 -1
- package/src/jscommon/umychart.vue.build/umychart.index.data.export.js +0 -4
- package/src/jscommon/umychart.vue.build/umychart.listctrl.vue.export.js +0 -15
- package/src/jscommon/umychart.vue.build/umychart.regressiontest.vue.export.js +0 -7
- package/src/jscommon/umychart.vue.build/umychart.regressiontest.wechat.export.js +0 -12
- package/src/jscommon/umychart.vue.build/umychart.stock.bat +0 -1
- package/src/jscommon/umychart.vue.build/umychart.stock.vue.export.js +0 -16
- package/src/jscommon/umychart.vue.build/umychart.testdata.bat +0 -3
- package/src/jscommon/umychart.vue.build/umychart.testdata.vue.export.js +0 -7
- package/src/jscommon/umychart.vue.build/umychart.vue.bat +0 -8
- package/src/jscommon/umychart.vue.build/umychart.vue.export.js +0 -112
- package/src/jscommon/umychart.vue.components/empyt.vue +0 -51
- package/src/jscommon/umychart.vue.components/historydayline.vue +0 -240
- package/src/jscommon/umychart.vue.components/jsloader.adddialog.vue +0 -315
- package/src/jscommon/umychart.vue.components/jsloader.vue +0 -93
- package/src/jscommon/umychart.vue.components/jsvuecontainer.vue +0 -160
- package/src/jscommon/umychart.vue.components/jsvuecontainer2.0.vue +0 -391
- package/src/jscommon/umychart.vue.components/login.vue +0 -178
- package/src/jscommon/umychart.vue.components/queryContent.vue +0 -750
- package/src/jscommon/umychart.vue.components/readme.txt +0 -8
- package/src/jscommon/umychart.vue.components/searchsymbol.vue +0 -299
- package/src/jscommon/umychart.vue.components/simulatetrade.vue +0 -1471
- package/src/jscommon/umychart.vue.components/stockchart.vue +0 -343
- package/src/jscommon/umychart.vue.components/stockchartV2.vue +0 -195
- package/src/jscommon/umychart.vue.components/stockdeal.vue +0 -358
- package/src/jscommon/umychart.vue.components/stockdealcount.vue +0 -262
- package/src/jscommon/umychart.vue.components/stockdeallastest.vue +0 -316
- package/src/jscommon/umychart.vue.components/stockdrawtool.vue +0 -343
- package/src/jscommon/umychart.vue.components/stockfull.vue +0 -355
- package/src/jscommon/umychart.vue.components/stockinfo.demo.vue +0 -153
- package/src/jscommon/umychart.vue.components/stockinfo.vue +0 -685
- package/src/jscommon/umychart.vue.components/stockkline.demo.vue +0 -1904
- package/src/jscommon/umychart.vue.components/stockmultiorder.vue +0 -174
- package/src/jscommon/umychart.vue.components/stockmultiperiod.vue +0 -222
- package/src/jscommon/umychart.vue.components/stockorder.vue +0 -320
- package/src/jscommon/umychart.vue.components/stocktradeinfo.demo.vue +0 -250
- package/src/jscommon/umychart.vue.components/stocktradeinfo.vue +0 -1907
- package/src/jscommon/umychart.vue.components/test.vue +0 -0
- package/src/jscommon/umychart.wechat/getDate.wechat.js +0 -91
- package/src/jscommon/umychart.wechat/lighter.news.wechat.js +0 -262
- package/src/jscommon/umychart.wechat/readme.txt +0 -3
- package/src/jscommon/umychart.wechat/umychart.analyze.wechat.js +0 -551
- package/src/jscommon/umychart.wechat/umychart.apidraw.wechat.js +0 -126
- package/src/jscommon/umychart.wechat/umychart.bigV.wechat.js +0 -2510
- package/src/jscommon/umychart.wechat/umychart.chartframe.wechat.js +0 -2931
- package/src/jscommon/umychart.wechat/umychart.chartpaint.wechat.js +0 -9752
- package/src/jscommon/umychart.wechat/umychart.charttitle.wechat.js +0 -2023
- package/src/jscommon/umychart.wechat/umychart.complier.wechat.js +0 -14726
- package/src/jscommon/umychart.wechat/umychart.console.wechat.js +0 -8
- package/src/jscommon/umychart.wechat/umychart.coordinatedata.wechat.js +0 -3654
- package/src/jscommon/umychart.wechat/umychart.data.wechat.js +0 -2243
- package/src/jscommon/umychart.wechat/umychart.element.wechart.js +0 -132
- package/src/jscommon/umychart.wechat/umychart.explainer.wechat.js +0 -1077
- package/src/jscommon/umychart.wechat/umychart.extendchart.wechat.js +0 -1140
- package/src/jscommon/umychart.wechat/umychart.framesplit.wechat.js +0 -2247
- package/src/jscommon/umychart.wechat/umychart.hqIndexformula.wechat.js +0 -941
- package/src/jscommon/umychart.wechat/umychart.index.data.wechat.js +0 -3628
- package/src/jscommon/umychart.wechat/umychart.index.wechat.js +0 -4074
- package/src/jscommon/umychart.wechat/umychart.klineinfo.wechat.js +0 -836
- package/src/jscommon/umychart.wechat/umychart.markethot.js +0 -50
- package/src/jscommon/umychart.wechat/umychart.network.wechart.js +0 -62
- package/src/jscommon/umychart.wechat/umychart.news.wechat.js +0 -3568
- package/src/jscommon/umychart.wechat/umychart.regressiontest.wechat.js +0 -412
- package/src/jscommon/umychart.wechat/umychart.report.wechat.js +0 -3983
- package/src/jscommon/umychart.wechat/umychart.resource.wechat.js +0 -919
- package/src/jscommon/umychart.wechat/umychart.shareimage.wechat.js +0 -681
- package/src/jscommon/umychart.wechat/umychart.simulatetrade.wechat.js +0 -238
- package/src/jscommon/umychart.wechat/umychart.stock.wechat.js +0 -4035
- package/src/jscommon/umychart.wechat/umychart.style.wechat.js +0 -419
- package/src/jscommon/umychart.wechat/umychart.uniapp.canvas.helper.js +0 -99
- package/src/jscommon/umychart.wechat/umychart.user.wechat.js +0 -588
- package/src/jscommon/umychart.wechat/umychart.userlog.wechat.js +0 -240
- package/src/jscommon/umychart.wechat/umychart.vedio.wechat.js +0 -112
- package/src/jscommon/umychart.wechat/umychart.version.wechat.js +0 -36
- package/src/jscommon/umychart.wechat/umychart.wechat.3.0.js +0 -12051
- package/src/jscommon/umychart.wechat/umychart.wechat.js +0 -15460
- package/src/jscommon/umychart.worker.js +0 -114
- package/src/jscommon/umychart.ws.stock.js +0 -110
- package/src/jscommon/umychart_python/.vscode/launch.json +0 -15
- package/src/jscommon/umychart_python/__init__.py +0 -4
- package/src/jscommon/umychart_python/build.cmd +0 -2
- package/src/jscommon/umychart_python/setup.py +0 -25
- package/src/jscommon/umychart_python/umychart_cache_testcase.py +0 -165
- package/src/jscommon/umychart_python/umychart_complier_data.py +0 -781
- package/src/jscommon/umychart_python/umychart_complier_help.py +0 -175
- package/src/jscommon/umychart_python/umychart_complier_job.py +0 -193
- package/src/jscommon/umychart_python/umychart_complier_jsalgorithm.py +0 -4144
- package/src/jscommon/umychart_python/umychart_complier_jscomplier.py +0 -177
- package/src/jscommon/umychart_python/umychart_complier_jsexecute.py +0 -517
- package/src/jscommon/umychart_python/umychart_complier_jsparser.py +0 -864
- package/src/jscommon/umychart_python/umychart_complier_jssymboldata.py +0 -1238
- package/src/jscommon/umychart_python/umychart_complier_jssymboldata_cache.py +0 -146
- package/src/jscommon/umychart_python/umychart_complier_jssymboldata_json.py +0 -106
- package/src/jscommon/umychart_python/umychart_complier_pandas_help.py +0 -80
- package/src/jscommon/umychart_python/umychart_complier_scanner.py +0 -554
- package/src/jscommon/umychart_python/umychart_complier_testcase.py +0 -362
- package/src/jscommon/umychart_python/umychart_complier_util.py +0 -30
- package/src/jscommon/umychart_python/umychart_webtemplate.py +0 -131
- package/src/jscommon/umychart_python/updatehqchartweb.bat +0 -5
- package/src/jscommon/vendor.js +0 -2
- package/src/pages/block.list.demo.page/App.vue +0 -117
- package/src/pages/block.list.demo.page/index.js +0 -12
- package/src/pages/brushTool.demo.page/App.vue +0 -19
- package/src/pages/brushTool.demo.page/index.js +0 -12
- package/src/pages/container.demo.page/App.vue +0 -118
- package/src/pages/container.demo.page/index.js +0 -18
- package/src/pages/dataZoom.demo.page/App.vue +0 -265
- package/src/pages/dataZoom.demo.page/components/dataZoom.vue +0 -303
- package/src/pages/dataZoom.demo.page/index.js +0 -12
- package/src/pages/historydayline.demo.page/App.vue +0 -57
- package/src/pages/historydayline.demo.page/index.js +0 -12
- package/src/pages/hq.demo.page/App.vue +0 -163
- package/src/pages/hq.demo.page/index.js +0 -12
- package/src/pages/hqchart.black/App.vue +0 -90
- package/src/pages/hqchart.black/components/searchsymbol.vue +0 -299
- package/src/pages/hqchart.black/components/stockdrawtool.vue +0 -300
- package/src/pages/hqchart.black/components/stockfull.vue +0 -313
- package/src/pages/hqchart.black/components/stockinfo.vue +0 -428
- package/src/pages/hqchart.black/components/stockkline.demo.vue +0 -1652
- package/src/pages/hqchart.black/components/stocktradeinfo.vue +0 -1337
- package/src/pages/hqchart.black/index.js +0 -30
- package/src/pages/hqchart.black/router/candlestickChart.vue +0 -108
- package/src/pages/hqchart.black/router/pricePointsTable.vue +0 -294
- package/src/pages/hqchart.black/router/stockDeallas.vue +0 -417
- package/src/pages/hqchart.black/router/timeShareChart.vue +0 -108
- package/src/pages/hqchart.page/App.vue +0 -101
- package/src/pages/hqchart.page/index.js +0 -18
- package/src/pages/index/App.vue +0 -1408
- package/src/pages/index/index.js +0 -7
- package/src/pages/indexHq/App.vue +0 -110
- package/src/pages/indexHq/index.js +0 -18
- package/src/pages/login.demo.page/App.vue +0 -22
- package/src/pages/login.demo.page/index.js +0 -12
- package/src/pages/queryContent.demo.page/App.vue +0 -29
- package/src/pages/queryContent.demo.page/index.js +0 -18
- package/src/pages/ranking.black/App.vue +0 -199
- package/src/pages/ranking.black/index.js +0 -18
- package/src/pages/search.demo.page/App.vue +0 -28
- package/src/pages/search.demo.page/index.js +0 -12
- package/src/pages/simulatetrade.demo.page/app.vue +0 -121
- package/src/pages/simulatetrade.demo.page/index.js +0 -17
- package/src/pages/stockdeal.demo.page/App.vue +0 -63
- package/src/pages/stockdeal.demo.page/index.js +0 -19
- package/src/pages/stockdealcount.demo.page/App.vue +0 -37
- package/src/pages/stockdealcount.demo.page/index.js +0 -12
- package/src/pages/stockdeallastest.demo.page/App.vue +0 -74
- package/src/pages/stockdeallastest.demo.page/index.js +0 -18
- package/src/pages/stockinfo.demo.page/App.vue +0 -92
- package/src/pages/stockinfo.demo.page/index.html +0 -13
- package/src/pages/stockinfo.demo.page/index.js +0 -19
- package/src/pages/stockkline.demo.page/App.vue +0 -55
- package/src/pages/stockkline.demo.page/index.js +0 -18
- package/src/pages/stockmultiorder.demo.page/App.vue +0 -149
- package/src/pages/stockmultiorder.demo.page/index.js +0 -18
- package/src/pages/stockmultiperiod.demo.page/App.vue +0 -87
- package/src/pages/stockmultiperiod.demo.page/index.js +0 -18
- package/src/pages/stockorder.demo.page/App.vue +0 -69
- package/src/pages/stockorder.demo.page/index.js +0 -18
- package/src/pages/test/App.vue +0 -22
- package/src/pages/test/index.js +0 -7
- package/src/pages/tradeinfopage/app.vue +0 -40
- package/src/pages/tradeinfopage/index.js +0 -7
- package/src/pages/tradeinfopage/tradeinfo.html +0 -12
- package/src/utils/urlObj.js +0 -81
- package/src/vendor.js +0 -2
- package/webpack.config.js +0 -104
|
@@ -1,4144 +0,0 @@
|
|
|
1
|
-
# Copyright (c) 2018 jones
|
|
2
|
-
#
|
|
3
|
-
# http://www.apache.org/licenses/LICENSE-2.0
|
|
4
|
-
#
|
|
5
|
-
# 开源项目 https://github.com/jones2000/HQChart
|
|
6
|
-
#
|
|
7
|
-
# jones_2000@163.com
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
import sys
|
|
11
|
-
import math
|
|
12
|
-
import copy
|
|
13
|
-
from umychart_complier_jssymboldata import JSSymbolData, g_JSComplierResource
|
|
14
|
-
from umychart_complier_help import JSComplierHelper ,Variant
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
#######################################################################################################
|
|
18
|
-
#
|
|
19
|
-
# 算法类
|
|
20
|
-
#
|
|
21
|
-
#######################################################################################################
|
|
22
|
-
class JSAlgorithm() :
|
|
23
|
-
def __init__(self, errorHandler, symbolData) :
|
|
24
|
-
self.ErrorHandler=errorHandler
|
|
25
|
-
self.SymbolData=symbolData # 股票数据
|
|
26
|
-
|
|
27
|
-
@staticmethod
|
|
28
|
-
def IsNumber(value):
|
|
29
|
-
return JSComplierHelper.IsNumber(value)
|
|
30
|
-
|
|
31
|
-
@staticmethod
|
|
32
|
-
def IsDivideNumber(value):
|
|
33
|
-
return JSComplierHelper.IsDivideNumber(value)
|
|
34
|
-
|
|
35
|
-
@staticmethod
|
|
36
|
-
def IsArray(value) :
|
|
37
|
-
return isinstance(value,list)
|
|
38
|
-
|
|
39
|
-
@staticmethod # value 和 value2 是否都是数值型
|
|
40
|
-
def Is2Number(value,value2) :
|
|
41
|
-
return JSComplierHelper.IsNumber(value) and JSComplierHelper.IsNumber(value2)
|
|
42
|
-
|
|
43
|
-
@staticmethod # value 和 value2 是否有1个是非数值行
|
|
44
|
-
def Is2NaN(value, value2) :
|
|
45
|
-
bValue=JSComplierHelper.IsNaN(value)
|
|
46
|
-
bValue2=JSComplierHelper.IsNaN(value2)
|
|
47
|
-
return bValue or bValue2
|
|
48
|
-
#return JSComplierHelper.IsNaN(value) or JSComplierHelper.IsNaN(value2)
|
|
49
|
-
|
|
50
|
-
@staticmethod
|
|
51
|
-
def IsNaN(value) :
|
|
52
|
-
return JSComplierHelper.IsNaN(value)
|
|
53
|
-
|
|
54
|
-
@staticmethod
|
|
55
|
-
def CreateArray(count, value=JSComplierHelper.NoneNumber) :
|
|
56
|
-
return JSComplierHelper.CreateArray(count,value)
|
|
57
|
-
|
|
58
|
-
@staticmethod # 是否是一个有效素组 data!=null and data.length>0
|
|
59
|
-
def IsVaildArray(data) :
|
|
60
|
-
if not data :
|
|
61
|
-
return False
|
|
62
|
-
if not isinstance(data,list):
|
|
63
|
-
return False
|
|
64
|
-
if len(data)<=0 :
|
|
65
|
-
return False
|
|
66
|
-
return True
|
|
67
|
-
|
|
68
|
-
@staticmethod # 计算数组均值
|
|
69
|
-
def ArrayAverage(data,n) :
|
|
70
|
-
dataLen=len(data)
|
|
71
|
-
averageData=JSAlgorithm.CreateArray(dataLen) # 平均值
|
|
72
|
-
for i in range(n-1, dataLen) :
|
|
73
|
-
total=0
|
|
74
|
-
for j in range(n) :
|
|
75
|
-
if JSAlgorithm.IsNumber(data[i-j]) :
|
|
76
|
-
total+=data[i-j]
|
|
77
|
-
averageData[i]=total/n
|
|
78
|
-
return averageData
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
######################################################################################
|
|
82
|
-
#
|
|
83
|
-
# 四则运算 + - * /
|
|
84
|
-
#
|
|
85
|
-
########################################################################################
|
|
86
|
-
|
|
87
|
-
# 相加
|
|
88
|
-
def Add(self, data, data2) :
|
|
89
|
-
isNumber=JSAlgorithm.IsNumber(data)
|
|
90
|
-
isNumber2=JSAlgorithm.IsNumber(data2)
|
|
91
|
-
|
|
92
|
-
if isNumber and isNumber2 : # 单数值相加
|
|
93
|
-
return data+data2
|
|
94
|
-
|
|
95
|
-
# 都是数组相加
|
|
96
|
-
if not isNumber and not isNumber2 :
|
|
97
|
-
len1=len(data)
|
|
98
|
-
len2=len(data2)
|
|
99
|
-
count=max(len1, len2)
|
|
100
|
-
result=JSAlgorithm.CreateArray(count) # 初始化
|
|
101
|
-
for i in range(count) :
|
|
102
|
-
if i<len1 and i<len2 and JSAlgorithm.Is2Number(data[i],data2[i]) :
|
|
103
|
-
result[i]=data[i]+data2[i]
|
|
104
|
-
|
|
105
|
-
return result
|
|
106
|
-
|
|
107
|
-
# 单数据和数组相加
|
|
108
|
-
if isNumber :
|
|
109
|
-
value=data
|
|
110
|
-
aryData=data2
|
|
111
|
-
else :
|
|
112
|
-
value=data2
|
|
113
|
-
aryData=data
|
|
114
|
-
|
|
115
|
-
count=len(aryData)
|
|
116
|
-
result=JSAlgorithm.CreateArray(count)
|
|
117
|
-
for i in range(count) :
|
|
118
|
-
if JSAlgorithm.Is2Number(aryData[i],value) :
|
|
119
|
-
result[i]=value+aryData[i]
|
|
120
|
-
|
|
121
|
-
return result
|
|
122
|
-
|
|
123
|
-
# 相减
|
|
124
|
-
def Subtract(self, data,data2) :
|
|
125
|
-
isNumber=JSAlgorithm.IsNumber(data)
|
|
126
|
-
isNumber2=JSAlgorithm.IsNumber(data2)
|
|
127
|
-
|
|
128
|
-
# 单数值相减
|
|
129
|
-
if isNumber and isNumber2 :
|
|
130
|
-
return data-data2
|
|
131
|
-
|
|
132
|
-
# 都是数组相减
|
|
133
|
-
|
|
134
|
-
if not isNumber and not isNumber2 :
|
|
135
|
-
len1=len(data)
|
|
136
|
-
len2=len(data2)
|
|
137
|
-
count=max(len1, len2)
|
|
138
|
-
result=JSAlgorithm.CreateArray(count)
|
|
139
|
-
for i in range(count) :
|
|
140
|
-
if i<len1 and i<len2 and JSAlgorithm.Is2Number(data[i],data2[i]) :
|
|
141
|
-
result[i]=data[i]-data2[i]
|
|
142
|
-
|
|
143
|
-
return result
|
|
144
|
-
|
|
145
|
-
if isNumber : # 单数据-数组
|
|
146
|
-
count=len(data2)
|
|
147
|
-
result=JSAlgorithm.CreateArray(count)
|
|
148
|
-
for i in range(count) :
|
|
149
|
-
if JSAlgorithm.Is2Number(data,data2[i]) :
|
|
150
|
-
result[i]=data-data2[i]
|
|
151
|
-
else : # 数组-单数据
|
|
152
|
-
count=len(data)
|
|
153
|
-
result=JSAlgorithm.CreateArray(count)
|
|
154
|
-
for i in range(count) :
|
|
155
|
-
if JSAlgorithm.Is2Number(data[i],data2) :
|
|
156
|
-
result[i]=data[i]-data2
|
|
157
|
-
|
|
158
|
-
return result
|
|
159
|
-
|
|
160
|
-
# 相乘
|
|
161
|
-
def Multiply(self,data,data2) :
|
|
162
|
-
isNumber=JSAlgorithm.IsNumber(data)
|
|
163
|
-
isNumber2=JSAlgorithm.IsNumber(data2)
|
|
164
|
-
|
|
165
|
-
# 单数值相乘
|
|
166
|
-
if isNumber and isNumber2 :
|
|
167
|
-
return data*data2
|
|
168
|
-
|
|
169
|
-
# 都是数组相乘
|
|
170
|
-
if not isNumber and not isNumber2 :
|
|
171
|
-
len1, len2 = len(data), len(data2)
|
|
172
|
-
count=max(len1, len2)
|
|
173
|
-
result=JSAlgorithm.CreateArray(count) # 初始化
|
|
174
|
-
for i in range(count) :
|
|
175
|
-
if i<len1 and i<len2 and JSAlgorithm.Is2Number(data[i],data2[i]) :
|
|
176
|
-
result[i]=data[i]*data2[i]
|
|
177
|
-
|
|
178
|
-
return result
|
|
179
|
-
|
|
180
|
-
# 单数据和数组相乘
|
|
181
|
-
if isNumber :
|
|
182
|
-
value=data
|
|
183
|
-
aryData=data2
|
|
184
|
-
else :
|
|
185
|
-
value=data2
|
|
186
|
-
aryData=data
|
|
187
|
-
|
|
188
|
-
count=len(aryData)
|
|
189
|
-
result=JSAlgorithm.CreateArray(count) # 初始化
|
|
190
|
-
for i in range(count) :
|
|
191
|
-
if JSAlgorithm.Is2Number(aryData[i],value) :
|
|
192
|
-
result[i]=value*aryData[i]
|
|
193
|
-
|
|
194
|
-
return result
|
|
195
|
-
|
|
196
|
-
# 相除
|
|
197
|
-
def Divide(self, data,data2) :
|
|
198
|
-
isNumber=JSAlgorithm.IsNumber(data)
|
|
199
|
-
isNumber2=JSAlgorithm.IsNumber(data2)
|
|
200
|
-
|
|
201
|
-
# 单数值相除
|
|
202
|
-
if isNumber and isNumber2 :
|
|
203
|
-
if data2==0 : # 除0判断
|
|
204
|
-
return None
|
|
205
|
-
return data/data2
|
|
206
|
-
|
|
207
|
-
# 都是数组相除
|
|
208
|
-
if not isNumber and not isNumber2 :
|
|
209
|
-
len1, len2 = len(data), len(data2)
|
|
210
|
-
count=max(len1, len2)
|
|
211
|
-
result=JSAlgorithm.CreateArray(count) # 初始化
|
|
212
|
-
for i in range(count) :
|
|
213
|
-
if i<len1 and i<len2 and JSAlgorithm.IsNumber(data[i]) and JSAlgorithm.IsDivideNumber(data2[i]) :
|
|
214
|
-
result[i]=data[i]/data2[i]
|
|
215
|
-
|
|
216
|
-
return result
|
|
217
|
-
|
|
218
|
-
if isNumber : # 单数据-数组
|
|
219
|
-
count=len(data2)
|
|
220
|
-
result=JSAlgorithm.CreateArray(count) # 初始化
|
|
221
|
-
for i in range(count) :
|
|
222
|
-
if JSAlgorithm.IsNumber(data) and JSAlgorithm.IsDivideNumber(data2[i]) :
|
|
223
|
-
result[i]=data/data2[i]
|
|
224
|
-
else : # 数组-单数据
|
|
225
|
-
count=len(data)
|
|
226
|
-
result=JSAlgorithm.CreateArray(count) # 初始化
|
|
227
|
-
for i in range(count) :
|
|
228
|
-
if JSAlgorithm.IsNumber(data[i]) and JSAlgorithm.IsDivideNumber(data2) :
|
|
229
|
-
result[i]=data[i]/data2
|
|
230
|
-
|
|
231
|
-
return result
|
|
232
|
-
|
|
233
|
-
############################################################################################
|
|
234
|
-
#
|
|
235
|
-
# 逻辑运算 > >= < <= = !=
|
|
236
|
-
#
|
|
237
|
-
#############################################################################################
|
|
238
|
-
|
|
239
|
-
# 大于 >
|
|
240
|
-
def GT(self, data,data2) :
|
|
241
|
-
isNumber=JSAlgorithm.IsNumber(data)
|
|
242
|
-
isNumber2=JSAlgorithm.IsNumber(data2)
|
|
243
|
-
|
|
244
|
-
# 单数值比较
|
|
245
|
-
if isNumber and isNumber2 :
|
|
246
|
-
return 1 if data>data2 else 0
|
|
247
|
-
|
|
248
|
-
# 都是数组比较
|
|
249
|
-
if not isNumber and not isNumber2 :
|
|
250
|
-
len1, len2 = len(data), len(data2)
|
|
251
|
-
count=max(len1, len2)
|
|
252
|
-
result=JSComplierHelper.CreateArray(count) # 初始化
|
|
253
|
-
for i in range(count) :
|
|
254
|
-
if i<len1 and i<len2 and not JSAlgorithm.Is2NaN(data[i],data2[i]) :
|
|
255
|
-
result[i]= 1 if data[i]>data2[i] else 0
|
|
256
|
-
|
|
257
|
-
return result
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
if isNumber : # 单数据-数组
|
|
261
|
-
count=len(data2)
|
|
262
|
-
result=JSComplierHelper.CreateArray(count) # 初始化
|
|
263
|
-
for i in range(count) :
|
|
264
|
-
if not JSAlgorithm.Is2NaN(data,data2[i]) :
|
|
265
|
-
result[i]=1 if data>data2[i] else 0
|
|
266
|
-
|
|
267
|
-
else : # 数组-单数据
|
|
268
|
-
count=len(data)
|
|
269
|
-
result=JSComplierHelper.CreateArray(count) # 初始化
|
|
270
|
-
for i in range(count) :
|
|
271
|
-
if not JSAlgorithm.Is2NaN(data[i],data2) :
|
|
272
|
-
result[i]=1 if data[i]>data2 else 0
|
|
273
|
-
|
|
274
|
-
return result
|
|
275
|
-
|
|
276
|
-
# 大于等于 >=
|
|
277
|
-
def GTE(self, data,data2) :
|
|
278
|
-
isNumber=JSAlgorithm.IsNumber(data)
|
|
279
|
-
isNumber2=JSAlgorithm.IsNumber(data2)
|
|
280
|
-
|
|
281
|
-
# 单数值比较
|
|
282
|
-
if isNumber and isNumber2 :
|
|
283
|
-
return 1 if data>=data2 else 0
|
|
284
|
-
|
|
285
|
-
# 都是数组比较
|
|
286
|
-
if not isNumber and not isNumber2 :
|
|
287
|
-
len1, len2 = len(data), len(data2)
|
|
288
|
-
count=max(len1, len2)
|
|
289
|
-
result=JSComplierHelper.CreateArray(count) # 初始化
|
|
290
|
-
for i in range(count) :
|
|
291
|
-
if i<len1 and i<len2 and not JSAlgorithm.Is2NaN(data[i],data2[i]) :
|
|
292
|
-
result[i]= 1 if data[i]>=data2[i] else 0
|
|
293
|
-
|
|
294
|
-
return result
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
if isNumber : # 单数据-数组
|
|
298
|
-
count=len(data2)
|
|
299
|
-
result=JSComplierHelper.CreateArray(count) # 初始化
|
|
300
|
-
for i in range(count) :
|
|
301
|
-
if not JSAlgorithm.Is2NaN(data,data2[i]) :
|
|
302
|
-
result[i]=1 if data>=data2[i] else 0
|
|
303
|
-
|
|
304
|
-
else : # 数组-单数据
|
|
305
|
-
count=len(data)
|
|
306
|
-
result=JSComplierHelper.CreateArray(count) # 初始化
|
|
307
|
-
for i in range(count) :
|
|
308
|
-
if not JSAlgorithm.Is2NaN(data[i],data2) :
|
|
309
|
-
result[i]=1 if data[i]>=data2 else 0
|
|
310
|
-
|
|
311
|
-
return result
|
|
312
|
-
|
|
313
|
-
# 小于 <
|
|
314
|
-
def LT(self,data,data2) :
|
|
315
|
-
isNumber=JSAlgorithm.IsNumber(data)
|
|
316
|
-
isNumber2=JSAlgorithm.IsNumber(data2)
|
|
317
|
-
|
|
318
|
-
# 单数值比较
|
|
319
|
-
if isNumber and isNumber2 :
|
|
320
|
-
return 1 if data<data2 else 0
|
|
321
|
-
|
|
322
|
-
# 都是数组比较
|
|
323
|
-
if not isNumber and not isNumber2 :
|
|
324
|
-
len1, len2 = len(data), len(data2)
|
|
325
|
-
count=max(len1, len2)
|
|
326
|
-
result=JSComplierHelper.CreateArray(count) # 初始化
|
|
327
|
-
for i in range(count) :
|
|
328
|
-
if i<len1 and i<len2 and not JSAlgorithm.Is2NaN(data[i],data2[i]) :
|
|
329
|
-
result[i]= 1 if data[i]<data2[i] else 0
|
|
330
|
-
|
|
331
|
-
return result
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
if isNumber : # 单数据-数组
|
|
335
|
-
count=len(data2)
|
|
336
|
-
result=JSComplierHelper.CreateArray(count) # 初始化
|
|
337
|
-
for i in range(count) :
|
|
338
|
-
if not JSAlgorithm.Is2NaN(data,data2[i]) :
|
|
339
|
-
result[i]=1 if data<data2[i] else 0
|
|
340
|
-
|
|
341
|
-
else : # 数组-单数据
|
|
342
|
-
count=len(data)
|
|
343
|
-
result=JSComplierHelper.CreateArray(count) # 初始化
|
|
344
|
-
for i in range(count) :
|
|
345
|
-
if not JSAlgorithm.Is2NaN(data[i],data2) :
|
|
346
|
-
result[i]=1 if data[i]<data2 else 0
|
|
347
|
-
|
|
348
|
-
return result
|
|
349
|
-
|
|
350
|
-
# 小于等于
|
|
351
|
-
def LTE(self,data,data2) :
|
|
352
|
-
isNumber=JSAlgorithm.IsNumber(data)
|
|
353
|
-
isNumber2=JSAlgorithm.IsNumber(data2)
|
|
354
|
-
|
|
355
|
-
# 单数值比较
|
|
356
|
-
if isNumber and isNumber2 :
|
|
357
|
-
return 1 if data<=data2 else 0
|
|
358
|
-
|
|
359
|
-
# 都是数组比较
|
|
360
|
-
if not isNumber and not isNumber2 :
|
|
361
|
-
len1, len2 = len(data), len(data2)
|
|
362
|
-
count=max(len1, len2)
|
|
363
|
-
result=JSComplierHelper.CreateArray(count) # 初始化
|
|
364
|
-
for i in range(count) :
|
|
365
|
-
if i<len1 and i<len2 and not JSAlgorithm.Is2NaN(data[i],data2[i]) :
|
|
366
|
-
result[i]= 1 if data[i]<=data2[i] else 0
|
|
367
|
-
|
|
368
|
-
return result
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
if isNumber : # 单数据-数组
|
|
372
|
-
count=len(data2)
|
|
373
|
-
result=JSComplierHelper.CreateArray(count) # 初始化
|
|
374
|
-
for i in range(count) :
|
|
375
|
-
if not JSAlgorithm.Is2NaN(data,data2[i]) :
|
|
376
|
-
result[i]=1 if data<=data2[i] else 0
|
|
377
|
-
|
|
378
|
-
else : # 数组-单数据
|
|
379
|
-
count=len(data)
|
|
380
|
-
result=JSComplierHelper.CreateArray(count) # 初始化
|
|
381
|
-
for i in range(count) :
|
|
382
|
-
if not JSAlgorithm.Is2NaN(data[i],data2) :
|
|
383
|
-
result[i]=1 if data[i]<=data2 else 0
|
|
384
|
-
|
|
385
|
-
return result
|
|
386
|
-
|
|
387
|
-
# 等于
|
|
388
|
-
def EQ(self, data,data2) :
|
|
389
|
-
isNumber=JSAlgorithm.IsNumber(data)
|
|
390
|
-
isNumber2=JSAlgorithm.IsNumber(data2)
|
|
391
|
-
|
|
392
|
-
# 单数值比较
|
|
393
|
-
if isNumber and isNumber2 :
|
|
394
|
-
return 1 if data==data2 else 0
|
|
395
|
-
|
|
396
|
-
# 都是数组比较
|
|
397
|
-
if not isNumber and not isNumber2 :
|
|
398
|
-
len1, len2 = len(data), len(data2)
|
|
399
|
-
count=max(len1, len2)
|
|
400
|
-
result=JSComplierHelper.CreateArray(count) # 初始化
|
|
401
|
-
for i in range(count) :
|
|
402
|
-
if i<len1 and i<len2 and not JSAlgorithm.Is2NaN(data[i],data2[i]) :
|
|
403
|
-
result[i]= 1 if data[i]==data2[i] else 0
|
|
404
|
-
|
|
405
|
-
return result
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
if isNumber : # 单数据-数组
|
|
409
|
-
count=len(data2)
|
|
410
|
-
result=JSComplierHelper.CreateArray(count) # 初始化
|
|
411
|
-
for i in range(count) :
|
|
412
|
-
if not JSAlgorithm.Is2NaN(data,data2[i]) :
|
|
413
|
-
result[i]=1 if data==data2[i] else 0
|
|
414
|
-
|
|
415
|
-
else : # 数组-单数据
|
|
416
|
-
count=len(data)
|
|
417
|
-
result=JSComplierHelper.CreateArray(count) # 初始化
|
|
418
|
-
for i in range(count) :
|
|
419
|
-
if not JSAlgorithm.Is2NaN(data[i],data2) :
|
|
420
|
-
result[i]=1 if data[i]==data2 else 0
|
|
421
|
-
|
|
422
|
-
return result
|
|
423
|
-
|
|
424
|
-
# 不等于
|
|
425
|
-
def NEQ(self, data,data2) :
|
|
426
|
-
isNumber=JSAlgorithm.IsNumber(data)
|
|
427
|
-
isNumber2=JSAlgorithm.IsNumber(data2)
|
|
428
|
-
|
|
429
|
-
# 单数值比较
|
|
430
|
-
if isNumber and isNumber2 :
|
|
431
|
-
return 1 if data!=data2 else 0
|
|
432
|
-
|
|
433
|
-
# 都是数组比较
|
|
434
|
-
if not isNumber and not isNumber2 :
|
|
435
|
-
len1, len2 = len(data), len(data2)
|
|
436
|
-
count=max(len1, len2)
|
|
437
|
-
result=JSComplierHelper.CreateArray(count) # 初始化
|
|
438
|
-
for i in range(count) :
|
|
439
|
-
if i<len1 and i<len2 and not JSAlgorithm.Is2NaN(data[i],data2[i]) :
|
|
440
|
-
result[i]= 1 if data[i]!=data2[i] else 0
|
|
441
|
-
|
|
442
|
-
return result
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
if isNumber : # 单数据-数组
|
|
446
|
-
count=len(data2)
|
|
447
|
-
result=JSComplierHelper.CreateArray(count) # 初始化
|
|
448
|
-
for i in range(count) :
|
|
449
|
-
if not JSAlgorithm.Is2NaN(data,data2[i]) :
|
|
450
|
-
result[i]=1 if data!=data2[i] else 0
|
|
451
|
-
|
|
452
|
-
else : # 数组-单数据
|
|
453
|
-
count=len(data)
|
|
454
|
-
result=JSComplierHelper.CreateArray(count) # 初始化
|
|
455
|
-
for i in range(count) :
|
|
456
|
-
if not JSAlgorithm.Is2NaN(data[i],data2) :
|
|
457
|
-
result[i]=1 if data[i]!=data2 else 0
|
|
458
|
-
|
|
459
|
-
return result
|
|
460
|
-
|
|
461
|
-
############################################################################################
|
|
462
|
-
#
|
|
463
|
-
# 逻辑运算 and, or
|
|
464
|
-
#
|
|
465
|
-
#############################################################################################
|
|
466
|
-
|
|
467
|
-
# AND &&
|
|
468
|
-
def And(self, data,data2):
|
|
469
|
-
isNumber=JSAlgorithm.IsNumber(data)
|
|
470
|
-
isNumber2=JSAlgorithm.IsNumber(data2)
|
|
471
|
-
|
|
472
|
-
# 单数值比较
|
|
473
|
-
if isNumber and isNumber2 :
|
|
474
|
-
return 1 if data and data2 else 0
|
|
475
|
-
|
|
476
|
-
# 都是数组比较
|
|
477
|
-
result=[]
|
|
478
|
-
if not isNumber and not isNumber2 :
|
|
479
|
-
len1, len2 = len(data), len(data2)
|
|
480
|
-
count=max(len1, len2)
|
|
481
|
-
result=JSComplierHelper.CreateArray(count) # 初始化
|
|
482
|
-
for i in range(count) :
|
|
483
|
-
if i<len1 and i<len2 and not JSAlgorithm.Is2NaN(data[i],data2[i]) :
|
|
484
|
-
result[i]= 1 if data[i] and data2[i] else 0
|
|
485
|
-
|
|
486
|
-
return result
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
if isNumber : # 单数据-数组
|
|
490
|
-
count=len(data2)
|
|
491
|
-
result=JSComplierHelper.CreateArray(count) # 初始化
|
|
492
|
-
for i in range(count) :
|
|
493
|
-
if not JSAlgorithm.Is2NaN(data,data2[i]) :
|
|
494
|
-
result[i]=1 if data and data2[i] else 0
|
|
495
|
-
|
|
496
|
-
else : # 数组-单数据
|
|
497
|
-
count=len(data)
|
|
498
|
-
result=JSComplierHelper.CreateArray(count) # 初始化
|
|
499
|
-
for i in range(count) :
|
|
500
|
-
if not JSAlgorithm.Is2NaN(data[i],data2) :
|
|
501
|
-
result[i]=1 if data[i] and data2 else 0
|
|
502
|
-
|
|
503
|
-
return result
|
|
504
|
-
|
|
505
|
-
# OR ||
|
|
506
|
-
def Or(self, data,data2) :
|
|
507
|
-
isNumber=JSAlgorithm.IsNumber(data)
|
|
508
|
-
isNumber2=JSAlgorithm.IsNumber(data2)
|
|
509
|
-
|
|
510
|
-
# 单数值比较
|
|
511
|
-
if isNumber and isNumber2 :
|
|
512
|
-
return 1 if data or data2 else 0
|
|
513
|
-
|
|
514
|
-
# 都是数组比较
|
|
515
|
-
result=[]
|
|
516
|
-
if not isNumber and not isNumber2 :
|
|
517
|
-
len1, len2 = len(data), len(data2)
|
|
518
|
-
count=max(len1, len2)
|
|
519
|
-
result=JSComplierHelper.CreateArray(count) # 初始化
|
|
520
|
-
for i in range(count) :
|
|
521
|
-
if i<len1 and i<len2 and not JSAlgorithm.Is2NaN(data[i],data2[i]) :
|
|
522
|
-
result[i]= 1 if data[i] or data2[i] else 0
|
|
523
|
-
|
|
524
|
-
return result
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
if isNumber : # 单数据-数组
|
|
528
|
-
count=len(data2)
|
|
529
|
-
result=JSComplierHelper.CreateArray(count) # 初始化
|
|
530
|
-
for i in range(count) :
|
|
531
|
-
if not JSAlgorithm.Is2NaN(data,data2[i]) :
|
|
532
|
-
result[i]=1 if data or data2[i] else 0
|
|
533
|
-
|
|
534
|
-
else : # 数组-单数据
|
|
535
|
-
count=len(data)
|
|
536
|
-
result=JSComplierHelper.CreateArray(count) # 初始化
|
|
537
|
-
for i in range(count) :
|
|
538
|
-
if not JSAlgorithm.Is2NaN(data[i],data2) :
|
|
539
|
-
result[i]=1 if data[i] or data2 else 0
|
|
540
|
-
|
|
541
|
-
return result
|
|
542
|
-
|
|
543
|
-
##########################################################################
|
|
544
|
-
#
|
|
545
|
-
# 条件语句 if , ifn
|
|
546
|
-
#
|
|
547
|
-
#########################################################################
|
|
548
|
-
|
|
549
|
-
def IF(self,data,trueData,falseData) :
|
|
550
|
-
isNumber=JSAlgorithm.IsNumber(data)
|
|
551
|
-
isNumber2=JSAlgorithm.IsNumber(trueData)
|
|
552
|
-
isNumber3=JSAlgorithm.IsNumber(falseData)
|
|
553
|
-
|
|
554
|
-
# 单数值
|
|
555
|
-
if isNumber :
|
|
556
|
-
if isNumber2 and isNumber3 :
|
|
557
|
-
return trueData if data else falseData
|
|
558
|
-
return trueData if data else falseData
|
|
559
|
-
|
|
560
|
-
# 都是数组
|
|
561
|
-
count=len(data)
|
|
562
|
-
result=JSComplierHelper.CreateArray(count)
|
|
563
|
-
for i in range(count) :
|
|
564
|
-
if data[i] :
|
|
565
|
-
if isNumber2 :
|
|
566
|
-
result[i]=trueData
|
|
567
|
-
else :
|
|
568
|
-
result[i]=trueData[i]
|
|
569
|
-
else :
|
|
570
|
-
if isNumber3 :
|
|
571
|
-
result[i]=falseData
|
|
572
|
-
else :
|
|
573
|
-
result[i]=falseData[i]
|
|
574
|
-
|
|
575
|
-
return result
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
# 根据条件求不同的值,同IF判断相反.
|
|
579
|
-
# 用法: IFN(X,A,B)若X不为0则返回B,否则返回A
|
|
580
|
-
# 例如: IFN(CLOSE>OPEN,HIGH,LOW)表示该周期收阴则返回最高值,否则返回最低值
|
|
581
|
-
def IFN(self, data,trueData,falseData) :
|
|
582
|
-
return self.IF(data,falseData,trueData)
|
|
583
|
-
|
|
584
|
-
########################################################################
|
|
585
|
-
#
|
|
586
|
-
# 指标函数 函数名全部大写
|
|
587
|
-
#
|
|
588
|
-
#########################################################################
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
# 引用若干周期前的数据(平滑处理).
|
|
592
|
-
# 用法:REF(X,A),引用A周期前的X值.A可以是变量.
|
|
593
|
-
# 平滑处理:当引用不到数据时进行的操作.此函数中,平滑时使用上一个周期的引用值.
|
|
594
|
-
# 例如:REF(CLOSE,BARSCOUNT(C)-1)表示第二根K线的收盘价.
|
|
595
|
-
def REF(self,data,n) :
|
|
596
|
-
result=[]
|
|
597
|
-
if JSAlgorithm.IsNumber(n) :
|
|
598
|
-
count=len(data)
|
|
599
|
-
n=int(n)
|
|
600
|
-
if count<=0 :
|
|
601
|
-
return result
|
|
602
|
-
if n>=count :
|
|
603
|
-
return result
|
|
604
|
-
|
|
605
|
-
result=data[0:count-n]
|
|
606
|
-
|
|
607
|
-
fristData=data[0] # 平滑使用第1个数据
|
|
608
|
-
for i in range(n) :
|
|
609
|
-
result.insert(0,fristData)
|
|
610
|
-
|
|
611
|
-
else : # n 为数组的情况
|
|
612
|
-
nCount=len(n)
|
|
613
|
-
count=len(data)
|
|
614
|
-
result=JSComplierHelper.CreateArray(count)
|
|
615
|
-
for i in range(len(data)) :
|
|
616
|
-
if i>=nCount :
|
|
617
|
-
continue
|
|
618
|
-
|
|
619
|
-
value=n[i]
|
|
620
|
-
if (JSAlgorithm.IsNumber(value)) :
|
|
621
|
-
value=int(value)
|
|
622
|
-
if value>=0 and value<=i :
|
|
623
|
-
result[i]=data[i-value]
|
|
624
|
-
elif i :
|
|
625
|
-
result[i]=result[i-1]
|
|
626
|
-
else :
|
|
627
|
-
result[i]=data[i]
|
|
628
|
-
|
|
629
|
-
return result
|
|
630
|
-
|
|
631
|
-
# 引用若干周期前的数据(未作平滑处理).
|
|
632
|
-
# 用法: REFV(X,A),引用A周期前的X值.A可以是变量.
|
|
633
|
-
# 平滑处理:当引用不到数据时进行的操作.
|
|
634
|
-
# 例如: REFV(CLOSE,BARSCOUNT(C)-1)表示第二根K线的收盘价.
|
|
635
|
-
def REFV(self,data,n) :
|
|
636
|
-
result=[]
|
|
637
|
-
if JSAlgorithm.IsNumber(n) :
|
|
638
|
-
count=len(data)
|
|
639
|
-
n=int(n)
|
|
640
|
-
if count<=0 :
|
|
641
|
-
return result
|
|
642
|
-
if n>=count :
|
|
643
|
-
return result
|
|
644
|
-
|
|
645
|
-
result=data[0:count-n]
|
|
646
|
-
|
|
647
|
-
for i in range(n) :
|
|
648
|
-
result.insert(0,JSComplierHelper.NoneNumber)
|
|
649
|
-
|
|
650
|
-
else : # n 为数组的情况
|
|
651
|
-
nCount=len(n)
|
|
652
|
-
count=len(data)
|
|
653
|
-
result=JSComplierHelper.CreateArray(count)
|
|
654
|
-
for i in range(len(data)) :
|
|
655
|
-
result[i]=JSComplierHelper.NoneNumber
|
|
656
|
-
if i>=nCount :
|
|
657
|
-
continue
|
|
658
|
-
|
|
659
|
-
value=n[i]
|
|
660
|
-
if (JSAlgorithm.IsNumber(value)) :
|
|
661
|
-
value=int(value)
|
|
662
|
-
if value>=0 and value<=i :
|
|
663
|
-
result[i]=data[i-value]
|
|
664
|
-
|
|
665
|
-
return result
|
|
666
|
-
|
|
667
|
-
# 属于未来函数,引用若干周期后的数据(平滑处理).
|
|
668
|
-
# 用法:REFX(X,A),引用A周期后的X值.A可以是变量.
|
|
669
|
-
# 平滑处理:当引用不到数据时进行的操作.此函数中,平滑时使用上一个周期的引用值.
|
|
670
|
-
# 例如: TT:=IF(C>O,1,2);
|
|
671
|
-
# REFX(CLOSE,TT);表示阳线引用下一周期的收盘价,阴线引用日后第二周期的收盘价.
|
|
672
|
-
def REFX(self,data,n) :
|
|
673
|
-
result=[]
|
|
674
|
-
if JSAlgorithm.IsNumber(n) :
|
|
675
|
-
count=len(data)
|
|
676
|
-
n=int(n)
|
|
677
|
-
if count<=0 :
|
|
678
|
-
return result
|
|
679
|
-
if n>=count :
|
|
680
|
-
return result
|
|
681
|
-
|
|
682
|
-
result=data[n:count]
|
|
683
|
-
lastData=data[count-1]
|
|
684
|
-
|
|
685
|
-
for i in range(n) :
|
|
686
|
-
result.append(lastData) # 使用最后一个数据平滑
|
|
687
|
-
|
|
688
|
-
else : # n 为数组的情况
|
|
689
|
-
nCount=len(n)
|
|
690
|
-
count=len(data)
|
|
691
|
-
result=JSComplierHelper.CreateArray(count)
|
|
692
|
-
for i in range(len(data)) :
|
|
693
|
-
if i>=nCount :
|
|
694
|
-
continue
|
|
695
|
-
|
|
696
|
-
value=n[i]
|
|
697
|
-
if (JSAlgorithm.IsNumber(value)) :
|
|
698
|
-
value=int(value)
|
|
699
|
-
if value>0 and value+i<count :
|
|
700
|
-
result[i]=data[i+value]
|
|
701
|
-
elif i :
|
|
702
|
-
result[i]=result[i-1]
|
|
703
|
-
else :
|
|
704
|
-
result[i]=data[i]
|
|
705
|
-
|
|
706
|
-
return result
|
|
707
|
-
|
|
708
|
-
# 属于未来函数,引用若干周期后的数据(未作平滑处理).
|
|
709
|
-
# 用法: REFXV(X,A),引用A周期后的X值.A可以是变量.
|
|
710
|
-
# 平滑处理:当引用不到数据时进行的操作.
|
|
711
|
-
# 例如: REFXV(CLOSE,1)表示下一周期的收盘价,在日线上就是明天收盘价
|
|
712
|
-
def REFXV(self,data,n) :
|
|
713
|
-
result=[]
|
|
714
|
-
if JSAlgorithm.IsNumber(n) :
|
|
715
|
-
count=len(data)
|
|
716
|
-
n=int(n)
|
|
717
|
-
if count<=0 :
|
|
718
|
-
return result
|
|
719
|
-
if n>=count :
|
|
720
|
-
return result
|
|
721
|
-
|
|
722
|
-
result=data[0:count-n]
|
|
723
|
-
|
|
724
|
-
for i in range(n) :
|
|
725
|
-
result.append(JSComplierHelper.NoneNumber)
|
|
726
|
-
|
|
727
|
-
else : # n 为数组的情况
|
|
728
|
-
nCount=len(n)
|
|
729
|
-
count=len(data)
|
|
730
|
-
result=JSComplierHelper.CreateArray(count)
|
|
731
|
-
for i in range(len(data)) :
|
|
732
|
-
if i>=nCount :
|
|
733
|
-
continue
|
|
734
|
-
|
|
735
|
-
value=n[i]
|
|
736
|
-
if (JSAlgorithm.IsNumber(value)) :
|
|
737
|
-
value=int(value)
|
|
738
|
-
if value>=0 and value+i< count:
|
|
739
|
-
result[i]=data[i-value]
|
|
740
|
-
|
|
741
|
-
return result
|
|
742
|
-
|
|
743
|
-
def MAX(self,data,data2) :
|
|
744
|
-
isNumber=JSAlgorithm.IsNumber(data)
|
|
745
|
-
isNumber2=JSAlgorithm.IsNumber(data2)
|
|
746
|
-
|
|
747
|
-
# 单数值比较
|
|
748
|
-
if isNumber and isNumber2 :
|
|
749
|
-
return max(data,data2)
|
|
750
|
-
|
|
751
|
-
# 都是数组比较
|
|
752
|
-
|
|
753
|
-
if not isNumber and not isNumber2 :
|
|
754
|
-
len1, len2 = len(data), len(data2)
|
|
755
|
-
count=max(len1, len2)
|
|
756
|
-
result=JSComplierHelper.CreateArray(count)
|
|
757
|
-
for i in range(count) :
|
|
758
|
-
if i<len1 and i<len2 and JSAlgorithm.Is2Number(data[i],data2[i]) :
|
|
759
|
-
result[i]= max(data[i],data2[i])
|
|
760
|
-
|
|
761
|
-
return result
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
if isNumber : # 单数据-数组
|
|
765
|
-
count=len(data2)
|
|
766
|
-
result=JSComplierHelper.CreateArray(count)
|
|
767
|
-
for i in range(count) :
|
|
768
|
-
if JSAlgorithm.Is2Number(data,data2[i]) :
|
|
769
|
-
result[i]=max(data,data2[i])
|
|
770
|
-
|
|
771
|
-
else : # 数组-单数据
|
|
772
|
-
count=len(data)
|
|
773
|
-
result=JSComplierHelper.CreateArray(count)
|
|
774
|
-
for i in range(count) :
|
|
775
|
-
if JSAlgorithm.Is2Number(data[i],data2) :
|
|
776
|
-
result[i]=max(data[i],data2)
|
|
777
|
-
|
|
778
|
-
return result
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
def MIN(self,data,data2) :
|
|
782
|
-
isNumber=JSAlgorithm.IsNumber(data)
|
|
783
|
-
isNumber2=JSAlgorithm.IsNumber(data2)
|
|
784
|
-
|
|
785
|
-
# 单数值比较
|
|
786
|
-
if isNumber and isNumber2 :
|
|
787
|
-
return min(data,data2)
|
|
788
|
-
|
|
789
|
-
# 都是数组比较
|
|
790
|
-
result=[]
|
|
791
|
-
if not isNumber and not isNumber2 :
|
|
792
|
-
len1, len2 = len(data), len(data2)
|
|
793
|
-
count=max(len1, len2)
|
|
794
|
-
result=JSComplierHelper.CreateArray(count)
|
|
795
|
-
for i in range(count) :
|
|
796
|
-
if i<len1 and i<len2 and JSAlgorithm.Is2Number(data[i],data2[i]) :
|
|
797
|
-
result[i]= min(data[i],data2[i])
|
|
798
|
-
|
|
799
|
-
return result
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
if isNumber : # 单数据-数组
|
|
803
|
-
count=len(data2)
|
|
804
|
-
result=JSComplierHelper.CreateArray(count)
|
|
805
|
-
for i in range(count) :
|
|
806
|
-
if JSAlgorithm.Is2Number(data,data2[i]) :
|
|
807
|
-
result[i]=min(data,data2[i])
|
|
808
|
-
|
|
809
|
-
else : # 数组-单数据
|
|
810
|
-
count=len(data)
|
|
811
|
-
result=JSComplierHelper.CreateArray(count)
|
|
812
|
-
for i in range(count) :
|
|
813
|
-
if JSAlgorithm.Is2Number(data[i],data2) :
|
|
814
|
-
result[i]=min(data[i],data2)
|
|
815
|
-
|
|
816
|
-
return result
|
|
817
|
-
|
|
818
|
-
# 取正数
|
|
819
|
-
def ABS(self, data) :
|
|
820
|
-
isNumber=JSAlgorithm.IsNumber(data)
|
|
821
|
-
if isNumber :
|
|
822
|
-
return abs(data)
|
|
823
|
-
|
|
824
|
-
count=len(data)
|
|
825
|
-
result=JSComplierHelper.CreateArray(count)
|
|
826
|
-
for i in range(count) :
|
|
827
|
-
if not JSAlgorithm.IsNaN(data[i]) :
|
|
828
|
-
result[i]=abs(data[i])
|
|
829
|
-
|
|
830
|
-
return result
|
|
831
|
-
|
|
832
|
-
# 返回简单移动平均
|
|
833
|
-
# 用法:
|
|
834
|
-
# MA(X,N):X的N日简单移动平均,算法(X1+X2+X3+...+Xn)/N,N支持变量
|
|
835
|
-
# N 支持数组
|
|
836
|
-
def MA(self, data,n) :
|
|
837
|
-
if (JSAlgorithm.IsArray(n)):
|
|
838
|
-
return self.MA_ARRAY(data,n)
|
|
839
|
-
|
|
840
|
-
dayCount=int(n)
|
|
841
|
-
if dayCount<=0:
|
|
842
|
-
dayCount=1
|
|
843
|
-
|
|
844
|
-
result=[]
|
|
845
|
-
if not data or len(data)<=0:
|
|
846
|
-
return result
|
|
847
|
-
|
|
848
|
-
result=JSComplierHelper.CreateArray(len(data)) # 初始化数据
|
|
849
|
-
for i in range(len(data)) :
|
|
850
|
-
if JSAlgorithm.IsNumber(data[i]):
|
|
851
|
-
break
|
|
852
|
-
|
|
853
|
-
data2=data[0:] # 复制一份数据出来
|
|
854
|
-
days=-1
|
|
855
|
-
for i in range(i,len(data2)) :
|
|
856
|
-
days+=1
|
|
857
|
-
|
|
858
|
-
if days<dayCount-1 :
|
|
859
|
-
continue
|
|
860
|
-
|
|
861
|
-
preValue=data[i-(dayCount-1)]
|
|
862
|
-
sum=0
|
|
863
|
-
|
|
864
|
-
for j in range(dayCount-1,-1,-1) :
|
|
865
|
-
value=data[i-j]
|
|
866
|
-
if not JSAlgorithm.IsNumber(value) :
|
|
867
|
-
value=preValue # 空数据就取上一个数据
|
|
868
|
-
data[i-j]=value
|
|
869
|
-
else :
|
|
870
|
-
preValue=value
|
|
871
|
-
sum+=value
|
|
872
|
-
|
|
873
|
-
result[i]=sum/dayCount
|
|
874
|
-
|
|
875
|
-
return result
|
|
876
|
-
|
|
877
|
-
# MA N=数组
|
|
878
|
-
def MA_ARRAY(self,data,n):
|
|
879
|
-
if not data or len(data)<=0:
|
|
880
|
-
return []
|
|
881
|
-
|
|
882
|
-
dataCount=len(data)
|
|
883
|
-
result=JSAlgorithm.CreateArray(dataCount)
|
|
884
|
-
for i in range(len(n)) :
|
|
885
|
-
period=n[i]
|
|
886
|
-
if (not JSAlgorithm.IsNumber(period)) :
|
|
887
|
-
continue
|
|
888
|
-
period=int(period)
|
|
889
|
-
if (period<=0):
|
|
890
|
-
continue
|
|
891
|
-
sum=0
|
|
892
|
-
value=0
|
|
893
|
-
sumCount=0
|
|
894
|
-
for j in range(period):
|
|
895
|
-
index=i-j
|
|
896
|
-
if (index<0):
|
|
897
|
-
break
|
|
898
|
-
value=data[index]
|
|
899
|
-
if JSAlgorithm.IsNumber(value):
|
|
900
|
-
sum+=value
|
|
901
|
-
sumCount+=1
|
|
902
|
-
if (sumCount>0):
|
|
903
|
-
value=sum/sumCount
|
|
904
|
-
result[i]=value
|
|
905
|
-
|
|
906
|
-
return result
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
# 指数平均数指标 EMA(close,10)
|
|
910
|
-
def EMA(self,data,n) :
|
|
911
|
-
if (JSAlgorithm.IsArray(n)):
|
|
912
|
-
return self.EMA_ARRAY(data,n)
|
|
913
|
-
|
|
914
|
-
dayCount=int(n)
|
|
915
|
-
result = []
|
|
916
|
-
offset=0
|
|
917
|
-
if offset>=len(data) :
|
|
918
|
-
return result
|
|
919
|
-
|
|
920
|
-
result=JSComplierHelper.CreateArray(len(data)) # 初始化数据
|
|
921
|
-
|
|
922
|
-
# 取首个有效数据
|
|
923
|
-
for i in range(len(data)) :
|
|
924
|
-
if JSAlgorithm.IsNumber(data[i]) :
|
|
925
|
-
break
|
|
926
|
-
|
|
927
|
-
offset=i
|
|
928
|
-
p1Index=offset
|
|
929
|
-
p2Index=offset+1
|
|
930
|
-
result[p1Index]=data[p1Index]
|
|
931
|
-
for i in range(offset+1,len(data)) :
|
|
932
|
-
result[p2Index]=((2*data[p2Index]+(dayCount-1)*result[p1Index]))/(dayCount+1)
|
|
933
|
-
p1Index+=1
|
|
934
|
-
p2Index+=1
|
|
935
|
-
|
|
936
|
-
return result
|
|
937
|
-
|
|
938
|
-
# EMA(N) = 2/(N+1)*C + (N-1)/(N+1)*EMA', EMA'为前一天的ema
|
|
939
|
-
def EMA_ARRAY(self,data,n):
|
|
940
|
-
dataCount=len(data)
|
|
941
|
-
if (dataCount<=0):
|
|
942
|
-
return []
|
|
943
|
-
|
|
944
|
-
result=JSAlgorithm.CreateArray(dataCount)
|
|
945
|
-
for i in range(len(n)) :
|
|
946
|
-
period=n[i]
|
|
947
|
-
if (not JSAlgorithm.IsNumber(period)) :
|
|
948
|
-
continue
|
|
949
|
-
period=int(period)
|
|
950
|
-
if (period<=0) :
|
|
951
|
-
continue
|
|
952
|
-
if (period>i+1) :
|
|
953
|
-
period=i+1
|
|
954
|
-
ema=None
|
|
955
|
-
lastEMA=None
|
|
956
|
-
EMAFactor=[ 2.0/ (period + 1), (period - 1.0) / (period + 1.0)]
|
|
957
|
-
for j in range(period) :
|
|
958
|
-
index=i-(period-j-1)
|
|
959
|
-
value=data[index]
|
|
960
|
-
if (not JSAlgorithm.IsNumber(value)):
|
|
961
|
-
continue
|
|
962
|
-
if (lastEMA==None):
|
|
963
|
-
ema=value
|
|
964
|
-
lastEMA=ema
|
|
965
|
-
else :
|
|
966
|
-
ema = EMAFactor[0] * value + EMAFactor[1] * lastEMA
|
|
967
|
-
lastEMA=ema
|
|
968
|
-
if (ema!=None) :
|
|
969
|
-
result[i]=ema
|
|
970
|
-
|
|
971
|
-
return result
|
|
972
|
-
|
|
973
|
-
# SMA 移动平均
|
|
974
|
-
# 返回移动平均。
|
|
975
|
-
# 用法: SMA(X,N,M) X的N日移动平均,M为权重,如Y=(X*M+Y'*(N-M))/N
|
|
976
|
-
def SMA(self,data,n,m) :
|
|
977
|
-
if (JSAlgorithm.IsArray(n)) :
|
|
978
|
-
return self.SMA_ARRAY(data,n,m)
|
|
979
|
-
|
|
980
|
-
period=int(n)
|
|
981
|
-
if (period<=0) :
|
|
982
|
-
return []
|
|
983
|
-
|
|
984
|
-
result = JSComplierHelper.CreateArray(len(data))
|
|
985
|
-
lastData=None
|
|
986
|
-
for i in range(len(data)) :
|
|
987
|
-
if JSAlgorithm.IsNumber(data[i]) :
|
|
988
|
-
lastData=data[i]
|
|
989
|
-
result[i]=lastData # 第一天的数据
|
|
990
|
-
break
|
|
991
|
-
|
|
992
|
-
for i in range(i+1,len(data)) :
|
|
993
|
-
result[i]=(m*data[i]+(period-m)*lastData)/period
|
|
994
|
-
lastData=result[i]
|
|
995
|
-
|
|
996
|
-
return result
|
|
997
|
-
|
|
998
|
-
def SMA_ARRAY(self,data,n,m) :
|
|
999
|
-
dataCount=len(data)
|
|
1000
|
-
if (dataCount<=0):
|
|
1001
|
-
return []
|
|
1002
|
-
|
|
1003
|
-
result=JSAlgorithm.CreateArray(dataCount)
|
|
1004
|
-
for i in range(len(n)):
|
|
1005
|
-
period=n[i]
|
|
1006
|
-
if (not JSAlgorithm.IsNumber(period)) :
|
|
1007
|
-
continue
|
|
1008
|
-
period=int(period)
|
|
1009
|
-
if (period<=0):
|
|
1010
|
-
continue
|
|
1011
|
-
if (period<i+1):
|
|
1012
|
-
period=i+1
|
|
1013
|
-
|
|
1014
|
-
sma=None
|
|
1015
|
-
lastSMA=None
|
|
1016
|
-
for j in range(period) :
|
|
1017
|
-
index=i-(period-j-1)
|
|
1018
|
-
value=data[index]
|
|
1019
|
-
if (not JSAlgorithm.IsNumber(value)):
|
|
1020
|
-
continue
|
|
1021
|
-
if (lastSMA==None):
|
|
1022
|
-
sma=value
|
|
1023
|
-
lastSMA=sma
|
|
1024
|
-
else :
|
|
1025
|
-
sma=(m*data[i]+(period-m)*lastSMA)/period
|
|
1026
|
-
lastSMA=sma
|
|
1027
|
-
if (sma!=None):
|
|
1028
|
-
result[i]=sma
|
|
1029
|
-
|
|
1030
|
-
return result
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
# 求动态移动平均.
|
|
1034
|
-
# 用法: DMA(X,A),求X的动态移动平均.
|
|
1035
|
-
# 算法: 若Y=DMA(X,A)则 Y=A*X+(1-A)*Y',其中Y'表示上一周期Y值,A必须小于1.
|
|
1036
|
-
# 例如:DMA(CLOSE,VOL/CAPITAL)表示求以换手率作平滑因子的平均价
|
|
1037
|
-
def DMA(self,data,data2) :
|
|
1038
|
-
result = []
|
|
1039
|
-
len1, len2 = len(data), len(data2)
|
|
1040
|
-
if len1<0 or len2!=len2 :
|
|
1041
|
-
return result
|
|
1042
|
-
|
|
1043
|
-
result = JSAlgorithm.CreateArray(len(data))
|
|
1044
|
-
for index in range(len1) :
|
|
1045
|
-
if JSAlgorithm.Is2Number(data[index],data2[index]) :
|
|
1046
|
-
result[index]=data[index]
|
|
1047
|
-
break
|
|
1048
|
-
|
|
1049
|
-
for index in range(index+1,len1) :
|
|
1050
|
-
if JSAlgorithm.Is2Number(data[index],data2[index]) :
|
|
1051
|
-
if data2[index]<1 :
|
|
1052
|
-
result[index]=(data2[index]*data[index])+(1-data2[index])*result[index-1]
|
|
1053
|
-
else :
|
|
1054
|
-
result[index]= data[index]
|
|
1055
|
-
return result
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
# 返回加权移动平均
|
|
1059
|
-
# 用法:WMA(X,N):X的N日加权移动平均.
|
|
1060
|
-
# 算法:Yn=(1*X1+2*X2+...+n*Xn)/(1+2+...+n)
|
|
1061
|
-
def WMA(self,data, n) :
|
|
1062
|
-
result=[]
|
|
1063
|
-
len1=len(data)
|
|
1064
|
-
if not data or len1<=0 :
|
|
1065
|
-
return result
|
|
1066
|
-
|
|
1067
|
-
result=JSAlgorithm.CreateArray(len1) # 初始化
|
|
1068
|
-
|
|
1069
|
-
if (JSAlgorithm.IsArray(n)) :
|
|
1070
|
-
for i in range(len(n)):
|
|
1071
|
-
period=n[i]
|
|
1072
|
-
if (not JSAlgorithm.IsNumber(period)) :
|
|
1073
|
-
continue
|
|
1074
|
-
period=int(period)
|
|
1075
|
-
if (period<=0):
|
|
1076
|
-
continue
|
|
1077
|
-
if (period>i+1) :
|
|
1078
|
-
period=i+1
|
|
1079
|
-
|
|
1080
|
-
start=0
|
|
1081
|
-
preValue=0
|
|
1082
|
-
for j in range(period) :
|
|
1083
|
-
index=i-(period-j-1)
|
|
1084
|
-
value=data[index]
|
|
1085
|
-
start=j
|
|
1086
|
-
if (JSAlgorithm.IsNumber(value)) :
|
|
1087
|
-
preValue=value
|
|
1088
|
-
break
|
|
1089
|
-
|
|
1090
|
-
if (start>=period) :
|
|
1091
|
-
continue
|
|
1092
|
-
|
|
1093
|
-
sum, count , k =0, 0, 1
|
|
1094
|
-
for j in range(start, period) :
|
|
1095
|
-
index=i-(period-j-1)
|
|
1096
|
-
value=data[index]
|
|
1097
|
-
if (JSAlgorithm.IsNumber(value)) :
|
|
1098
|
-
preValue = value
|
|
1099
|
-
else :
|
|
1100
|
-
value=preValue
|
|
1101
|
-
|
|
1102
|
-
count+= k
|
|
1103
|
-
sum += value * k
|
|
1104
|
-
k+=1
|
|
1105
|
-
|
|
1106
|
-
result[i] = sum / count
|
|
1107
|
-
|
|
1108
|
-
else :
|
|
1109
|
-
dayCount=int(n)
|
|
1110
|
-
if dayCount<=0 :
|
|
1111
|
-
return result
|
|
1112
|
-
|
|
1113
|
-
start=0
|
|
1114
|
-
for i in range(len1) :
|
|
1115
|
-
start=i
|
|
1116
|
-
if JSAlgorithm.IsNumber(data[i]) :
|
|
1117
|
-
break
|
|
1118
|
-
|
|
1119
|
-
data2 = data[0:]
|
|
1120
|
-
days =int(-1)
|
|
1121
|
-
for i in range(start,len1) :
|
|
1122
|
-
days+=1
|
|
1123
|
-
if days < dayCount-1 :
|
|
1124
|
-
continue
|
|
1125
|
-
|
|
1126
|
-
preValue = data2[i - (dayCount-1)]
|
|
1127
|
-
sum = 0
|
|
1128
|
-
count = 0
|
|
1129
|
-
for j in range(dayCount-1,-1,-1) :
|
|
1130
|
-
value = data2[i-j]
|
|
1131
|
-
if not JSAlgorithm.IsNumber(value) :
|
|
1132
|
-
value = preValue
|
|
1133
|
-
data2[i-j] = value
|
|
1134
|
-
else :
|
|
1135
|
-
preValue = value
|
|
1136
|
-
|
|
1137
|
-
count += dayCount - j
|
|
1138
|
-
sum += value * (dayCount - j)
|
|
1139
|
-
|
|
1140
|
-
result[i] = sum / count
|
|
1141
|
-
|
|
1142
|
-
return result
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
# 返回平滑移动平均
|
|
1146
|
-
# 用法:MEMA(X,N):X的N日平滑移动平均,如Y=(X+Y'*(N-1))/N
|
|
1147
|
-
# MEMA(X,N)相当于SMA(X,N,1)
|
|
1148
|
-
def MEMA(self, data, dayCount):
|
|
1149
|
-
result=[]
|
|
1150
|
-
dataLen=len(data)
|
|
1151
|
-
if not data or dataLen<=0 :
|
|
1152
|
-
return result
|
|
1153
|
-
|
|
1154
|
-
result=JSAlgorithm.CreateArray(dataLen)
|
|
1155
|
-
for i in range(dataLen) :
|
|
1156
|
-
if JSAlgorithm.IsNumber(data[i]) :
|
|
1157
|
-
break
|
|
1158
|
-
|
|
1159
|
-
if dayCount<1 or i+dayCount>=dataLen :
|
|
1160
|
-
return result
|
|
1161
|
-
|
|
1162
|
-
sum = 0
|
|
1163
|
-
data2 = data[0:]
|
|
1164
|
-
for i in range(i,i+dayCount) :
|
|
1165
|
-
if not JSAlgorithm.IsNumber(data2[i]) and i-1 >= 0 :
|
|
1166
|
-
data2[i] = data2[i-1]
|
|
1167
|
-
sum += data2[i]
|
|
1168
|
-
|
|
1169
|
-
result[i-1] = sum / dayCount
|
|
1170
|
-
for i in range(i,dataLen) :
|
|
1171
|
-
if self.IsNumber(result[i-1]) and self.IsNumber(data[i]) :
|
|
1172
|
-
result[i] = (data[i]+result[i-1]*(dayCount-1)) / dayCount
|
|
1173
|
-
elif i-1 > -1 and self.IsNumber(result[i-1]) :
|
|
1174
|
-
result[i] = result[i-1]
|
|
1175
|
-
|
|
1176
|
-
return result
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
# 加权移动平均
|
|
1180
|
-
# 返回加权移动平均
|
|
1181
|
-
# 用法:EXPMA(X,M):X的M日加权移动平均
|
|
1182
|
-
# EXPMA[i]=buffer[i]*para+(1-para)*EXPMA[i-1] para=2/(1+__para)
|
|
1183
|
-
def EXPMA(self,data,dayCount) :
|
|
1184
|
-
result=[]
|
|
1185
|
-
dataLen=len(data)
|
|
1186
|
-
if dayCount>=dataLen :
|
|
1187
|
-
return result
|
|
1188
|
-
|
|
1189
|
-
result=JSAlgorithm.CreateArray(dataLen) # 初始化
|
|
1190
|
-
for i in range(dayCount,dataLen) : # 获取第1个有效数据
|
|
1191
|
-
if JSAlgorithm.IsNumber(data[i]) :
|
|
1192
|
-
result[i]=data[i]
|
|
1193
|
-
break
|
|
1194
|
-
|
|
1195
|
-
for i in range(i+1,dataLen) :
|
|
1196
|
-
if JSAlgorithm.Is2Number(result[i-1], data[i]) :
|
|
1197
|
-
result[i]=(2*data[i]+(dayCount-1)*result[i-1])/(dayCount+1)
|
|
1198
|
-
elif JSAlgorithm.IsNumber(result[i-1]) :
|
|
1199
|
-
result[i]=result[i-1]
|
|
1200
|
-
|
|
1201
|
-
return result
|
|
1202
|
-
|
|
1203
|
-
# 加权平滑平均,MEMA[i]=SMA[i]*para+(1-para)*SMA[i-1] para=2/(1+__para)
|
|
1204
|
-
def EXPMEMA(self,data,dayCount) :
|
|
1205
|
-
result=[]
|
|
1206
|
-
dataLen=len(data)
|
|
1207
|
-
if dayCount>=dataLen :
|
|
1208
|
-
return result
|
|
1209
|
-
|
|
1210
|
-
result=JSAlgorithm.CreateArray(dataLen) # 初始化
|
|
1211
|
-
for i in range(dataLen) :
|
|
1212
|
-
if JSAlgorithm.IsNumber(data[i]) :
|
|
1213
|
-
break
|
|
1214
|
-
|
|
1215
|
-
index=i
|
|
1216
|
-
sum=0
|
|
1217
|
-
for i in range(dayCount) :
|
|
1218
|
-
if index>=dataLen :
|
|
1219
|
-
break
|
|
1220
|
-
|
|
1221
|
-
if JSAlgorithm.IsNumber(data[index]) :
|
|
1222
|
-
sum+=data[index]
|
|
1223
|
-
else :
|
|
1224
|
-
sum+=data[index-1]
|
|
1225
|
-
|
|
1226
|
-
index+=1
|
|
1227
|
-
|
|
1228
|
-
result[index-1]=sum/dayCount
|
|
1229
|
-
for index in range(index,dataLen) :
|
|
1230
|
-
if JSAlgorithm.Is2Number(result[index-1], data[index]) :
|
|
1231
|
-
result[index]=(2*data[index]+(dayCount-1)*result[index-1])/(dayCount+1)
|
|
1232
|
-
elif JSAlgorithm.IsNumber(result[index-1]) :
|
|
1233
|
-
result[index] = result[index-1]
|
|
1234
|
-
|
|
1235
|
-
return result
|
|
1236
|
-
|
|
1237
|
-
# 向前累加到指定值到现在的周期数.
|
|
1238
|
-
# 用法:SUMBARS(X,A):将X向前累加直到大于等于A,返回这个区间的周期数
|
|
1239
|
-
# 例如:SUMBARS(VOL,CAPITAL)求完全换手到现在的周期数
|
|
1240
|
-
def SUMBARS(self, data, data2) :
|
|
1241
|
-
result = []
|
|
1242
|
-
if not data or not data2:
|
|
1243
|
-
return result
|
|
1244
|
-
len1, len2 = len(data), len(data2)
|
|
1245
|
-
if len1<=0 or len2<=0:
|
|
1246
|
-
return result
|
|
1247
|
-
|
|
1248
|
-
result=JSAlgorithm.CreateArray(len1)
|
|
1249
|
-
for start in range(len1) :
|
|
1250
|
-
if JSAlgorithm.IsNumber(data[start]) :
|
|
1251
|
-
break
|
|
1252
|
-
|
|
1253
|
-
for i in range(len1-1,start-1,-1) :
|
|
1254
|
-
total = 0
|
|
1255
|
-
for j in range(i,start-1,-1) :
|
|
1256
|
-
if total>=data2[i]:
|
|
1257
|
-
break
|
|
1258
|
-
total += data[j]
|
|
1259
|
-
|
|
1260
|
-
if j < start:
|
|
1261
|
-
pass
|
|
1262
|
-
else :
|
|
1263
|
-
result[i] = i - j
|
|
1264
|
-
|
|
1265
|
-
for i in range(start+1,len1) :
|
|
1266
|
-
if result[i]==JSComplierHelper.NoneNumber :
|
|
1267
|
-
result[i] = result[i-1]
|
|
1268
|
-
|
|
1269
|
-
return result
|
|
1270
|
-
|
|
1271
|
-
|
|
1272
|
-
# 求相反数.
|
|
1273
|
-
# 用法:REVERSE(X)返回-X.
|
|
1274
|
-
# 例如:REVERSE(CLOSE)返回-CLOSE
|
|
1275
|
-
def REVERSE(self,data) :
|
|
1276
|
-
isNumber=JSAlgorithm.IsNumber(data)
|
|
1277
|
-
if isNumber :
|
|
1278
|
-
return 0-data
|
|
1279
|
-
|
|
1280
|
-
count=len(data)
|
|
1281
|
-
result = JSAlgorithm.CreateArray(count)
|
|
1282
|
-
for i in range(count) :
|
|
1283
|
-
if JSAlgorithm.IsNumber(data[i]) :
|
|
1284
|
-
result[i]=0-data[i]
|
|
1285
|
-
|
|
1286
|
-
return result
|
|
1287
|
-
|
|
1288
|
-
def COUNT(self, data,n):
|
|
1289
|
-
dataLen=len(data)
|
|
1290
|
-
result=[0]*dataLen # 初始全部是0
|
|
1291
|
-
|
|
1292
|
-
if (JSAlgorithm.IsArray(n)):
|
|
1293
|
-
for i in range(len(n)) :
|
|
1294
|
-
period=n[i]
|
|
1295
|
-
if (not JSAlgorithm.IsNumber(period)):
|
|
1296
|
-
continue
|
|
1297
|
-
period=int(period)
|
|
1298
|
-
if (period<1) :
|
|
1299
|
-
period=i+1
|
|
1300
|
-
count=0
|
|
1301
|
-
for j in range(period) :
|
|
1302
|
-
index=i-j
|
|
1303
|
-
if (index<0):
|
|
1304
|
-
break
|
|
1305
|
-
if data[index] :
|
|
1306
|
-
count+=1
|
|
1307
|
-
result[i]=count
|
|
1308
|
-
else :
|
|
1309
|
-
n=int(n)
|
|
1310
|
-
for i in range(dataLen) :
|
|
1311
|
-
count=0
|
|
1312
|
-
for j in range(n) :
|
|
1313
|
-
if i-j<0 :
|
|
1314
|
-
break
|
|
1315
|
-
if data[i-j] :
|
|
1316
|
-
count+=1
|
|
1317
|
-
result[i]=count
|
|
1318
|
-
|
|
1319
|
-
return result
|
|
1320
|
-
|
|
1321
|
-
# HHV 最高值
|
|
1322
|
-
# 求最高值。
|
|
1323
|
-
# 用法: HHV(X,N) 求N周期内X最高值,N=0则从第一个有效值开始。
|
|
1324
|
-
# 例如: HHV(HIGH,30) 表示求30日最高价。
|
|
1325
|
-
def HHV(self,data,n):
|
|
1326
|
-
dataLen=len(data)
|
|
1327
|
-
result = JSAlgorithm.CreateArray(dataLen)
|
|
1328
|
-
isNumber=JSAlgorithm.IsNumber(n)
|
|
1329
|
-
if not isNumber : # n是一个数组 周期变动
|
|
1330
|
-
max=None
|
|
1331
|
-
nLen=len(n)
|
|
1332
|
-
for i in range(dataLen) :
|
|
1333
|
-
if i>nLen :
|
|
1334
|
-
continue
|
|
1335
|
-
max=None
|
|
1336
|
-
count=int(n[i])
|
|
1337
|
-
if count>0 and count<=i :
|
|
1338
|
-
for j in range(i-count,i+1) :
|
|
1339
|
-
if max==None or max<data[j] :
|
|
1340
|
-
max=data[j]
|
|
1341
|
-
else :
|
|
1342
|
-
count=i
|
|
1343
|
-
for j in range(i+1) :
|
|
1344
|
-
if max==None or max<data[j] :
|
|
1345
|
-
max=data[j]
|
|
1346
|
-
result[i]=max
|
|
1347
|
-
|
|
1348
|
-
else :
|
|
1349
|
-
n=int(n)
|
|
1350
|
-
if n>dataLen :
|
|
1351
|
-
return result
|
|
1352
|
-
|
|
1353
|
-
if n<=0:
|
|
1354
|
-
n=dataLen-1
|
|
1355
|
-
|
|
1356
|
-
for nMax in range(dataLen) :
|
|
1357
|
-
if JSAlgorithm.IsNumber(data[nMax]) :
|
|
1358
|
-
break
|
|
1359
|
-
|
|
1360
|
-
if nMax<dataLen :
|
|
1361
|
-
result[nMax]=data[nMax]
|
|
1362
|
-
|
|
1363
|
-
j=2
|
|
1364
|
-
for i in range(nMax+1,dataLen):
|
|
1365
|
-
if j>=n :
|
|
1366
|
-
break
|
|
1367
|
-
if data[i]>=data[nMax] :
|
|
1368
|
-
nMax=i
|
|
1369
|
-
result[i]=data[nMax]
|
|
1370
|
-
j+=1
|
|
1371
|
-
|
|
1372
|
-
for i in range(i,dataLen) :
|
|
1373
|
-
if i-nMax<n :
|
|
1374
|
-
nMax=nMax if data[i]<data[nMax] else i
|
|
1375
|
-
else :
|
|
1376
|
-
nMax=(i-n+2)
|
|
1377
|
-
for j in range(nMax,i+1) :
|
|
1378
|
-
nMax=nMax if data[j]<data[nMax] else j
|
|
1379
|
-
result[i]=data[nMax]
|
|
1380
|
-
|
|
1381
|
-
return result
|
|
1382
|
-
|
|
1383
|
-
# LLV 最低值
|
|
1384
|
-
# 求最低值。
|
|
1385
|
-
# 用法: LLV(X,N) 求N周期内X最低值,N=0则从第一个有效值开始。
|
|
1386
|
-
# 例如: LLV(LOW,0) 表示求历史最低价。
|
|
1387
|
-
def LLV(self,data,n) :
|
|
1388
|
-
dataLen=len(data)
|
|
1389
|
-
result = JSAlgorithm.CreateArray(dataLen)
|
|
1390
|
-
isNumber=JSAlgorithm.IsNumber(n)
|
|
1391
|
-
if not isNumber : # n是数组
|
|
1392
|
-
for i in range(dataLen) :
|
|
1393
|
-
if i>=dataLen :
|
|
1394
|
-
continue
|
|
1395
|
-
min=None
|
|
1396
|
-
count=int(n[i])
|
|
1397
|
-
if count>0 and count<=i :
|
|
1398
|
-
for j in range(i-count,i+1):
|
|
1399
|
-
if min==None or min>data[j] :
|
|
1400
|
-
min=data[j]
|
|
1401
|
-
else :
|
|
1402
|
-
count=i
|
|
1403
|
-
for j in range(i+1) :
|
|
1404
|
-
if min==None or min>data[j] :
|
|
1405
|
-
min=data[j]
|
|
1406
|
-
result[i]=min
|
|
1407
|
-
else :
|
|
1408
|
-
n=int(n)
|
|
1409
|
-
if n>dataLen :
|
|
1410
|
-
return result
|
|
1411
|
-
if n<=0 :
|
|
1412
|
-
n=dataLen-1
|
|
1413
|
-
|
|
1414
|
-
min=n
|
|
1415
|
-
for i in range(n,dataLen):
|
|
1416
|
-
if i<n+min :
|
|
1417
|
-
min=min if data[i]>data[min] else i
|
|
1418
|
-
else :
|
|
1419
|
-
min=i-n+1
|
|
1420
|
-
for j in range(min+1,i+1) :
|
|
1421
|
-
if data[j]<data[min] :
|
|
1422
|
-
min=j
|
|
1423
|
-
result[i] = data[min]
|
|
1424
|
-
|
|
1425
|
-
return result
|
|
1426
|
-
|
|
1427
|
-
# STD(X,N) 返回估算标准差
|
|
1428
|
-
def STD(self,data,n) :
|
|
1429
|
-
if not data or len(data)<=0 :
|
|
1430
|
-
return []
|
|
1431
|
-
|
|
1432
|
-
dataLen=len(data)
|
|
1433
|
-
result=JSAlgorithm.CreateArray(dataLen)
|
|
1434
|
-
if n<=0:
|
|
1435
|
-
n=dataLen-1
|
|
1436
|
-
|
|
1437
|
-
averageData=JSAlgorithm.ArrayAverage(data,n) # 平均值
|
|
1438
|
-
for i in range(dataLen) :
|
|
1439
|
-
total=0
|
|
1440
|
-
for j in range(n) :
|
|
1441
|
-
if JSAlgorithm.Is2Number(data[i-j],averageData[i]) :
|
|
1442
|
-
total+=(data[i-j]-averageData[i])*(data[i-j]-averageData[i])
|
|
1443
|
-
result[i]=math.sqrt(total/n)
|
|
1444
|
-
|
|
1445
|
-
return result
|
|
1446
|
-
|
|
1447
|
-
# 平均绝对方差
|
|
1448
|
-
def AVEDEV(self,data,n) :
|
|
1449
|
-
if not JSAlgorithm.IsVaildArray(data) :
|
|
1450
|
-
return []
|
|
1451
|
-
|
|
1452
|
-
dataLen=len(data)
|
|
1453
|
-
result=JSAlgorithm.CreateArray(dataLen)
|
|
1454
|
-
if n<=0:
|
|
1455
|
-
n=dataLen-1
|
|
1456
|
-
|
|
1457
|
-
averageData=JSAlgorithm.ArrayAverage(data,n) # 平均值
|
|
1458
|
-
for i in range(n-1,dataLen) :
|
|
1459
|
-
total=0
|
|
1460
|
-
for j in range(n) :
|
|
1461
|
-
if JSAlgorithm.Is2Number(data[i-j],averageData[i]) :
|
|
1462
|
-
total+=abs(data[i-j]-averageData[i])
|
|
1463
|
-
result[i]=total/n
|
|
1464
|
-
|
|
1465
|
-
return result
|
|
1466
|
-
|
|
1467
|
-
# 上穿
|
|
1468
|
-
def CROSS(self, data,data2) :
|
|
1469
|
-
if JSAlgorithm.IsArray(data) and JSAlgorithm.IsArray(data2) :
|
|
1470
|
-
len1, len2 = len(data), len(data2)
|
|
1471
|
-
if len1!=len2 :
|
|
1472
|
-
return []
|
|
1473
|
-
|
|
1474
|
-
result=JSAlgorithm.CreateArray(len1,0)
|
|
1475
|
-
for index in range(len1) :
|
|
1476
|
-
if JSAlgorithm.Is2Number(data[index],data2[index]) :
|
|
1477
|
-
break
|
|
1478
|
-
|
|
1479
|
-
for index in range(index+1, len1) :
|
|
1480
|
-
result[index]= 1 if data[index]>data2[index] and data[index-1]<data2[index-1] else 0
|
|
1481
|
-
|
|
1482
|
-
elif JSAlgorithm.IsArray(data) and JSAlgorithm.IsNumber(data2):
|
|
1483
|
-
# data2=float(data2)
|
|
1484
|
-
len1=len(data)
|
|
1485
|
-
result=JSAlgorithm.CreateArray(len1,0)
|
|
1486
|
-
for index in range(len1) :
|
|
1487
|
-
if JSAlgorithm.IsNumber(data[index]) :
|
|
1488
|
-
break
|
|
1489
|
-
|
|
1490
|
-
for index in range(index+1, len1) :
|
|
1491
|
-
result[index]= 1 if data[index]>data2 and data[index-1]<data2 else 0
|
|
1492
|
-
|
|
1493
|
-
elif JSAlgorithm.IsNumber(data) and JSAlgorithm.IsArray(data2) :
|
|
1494
|
-
# data=float(data)
|
|
1495
|
-
len2=len(data2)
|
|
1496
|
-
result=JSAlgorithm.CreateArray(len2,0)
|
|
1497
|
-
for index in range(len2) :
|
|
1498
|
-
if JSAlgorithm.IsNumber(data2[index]) :
|
|
1499
|
-
break
|
|
1500
|
-
|
|
1501
|
-
for index in range(index+1, len2) :
|
|
1502
|
-
result[index]= 1 if data2[index]<data and data2[index-1]>data else 0
|
|
1503
|
-
|
|
1504
|
-
else :
|
|
1505
|
-
return []
|
|
1506
|
-
|
|
1507
|
-
return result
|
|
1508
|
-
|
|
1509
|
-
# 累乘
|
|
1510
|
-
def MULAR(self,data,n) :
|
|
1511
|
-
if not JSAlgorithm.IsVaildArray(data) :
|
|
1512
|
-
return []
|
|
1513
|
-
|
|
1514
|
-
dataLen=len(data)
|
|
1515
|
-
if dataLen<n:
|
|
1516
|
-
return []
|
|
1517
|
-
|
|
1518
|
-
result=JSAlgorithm.CreateArray(dataLen)
|
|
1519
|
-
|
|
1520
|
-
for index in range(dataLen) :
|
|
1521
|
-
if JSAlgorithm.IsNumber(data[index]):
|
|
1522
|
-
result[index]=data[index]
|
|
1523
|
-
break
|
|
1524
|
-
|
|
1525
|
-
for index in range(index+1, dataLen):
|
|
1526
|
-
if JSAlgorithm.IsNumber(data[index]):
|
|
1527
|
-
result[index]=result[index-1]*data[index]
|
|
1528
|
-
else :
|
|
1529
|
-
result[index]=result[index-1]
|
|
1530
|
-
|
|
1531
|
-
return result
|
|
1532
|
-
|
|
1533
|
-
# 求总和.
|
|
1534
|
-
# 用法: SUM(X,N),统计N周期中X的总和,N=0则从第一个有效值开始.
|
|
1535
|
-
# 例如: SUM(VOL,0)表示统计从上市第一天以来的成交量总和
|
|
1536
|
-
# N 支持变量数组
|
|
1537
|
-
def SUM(self, data,n) :
|
|
1538
|
-
if not JSAlgorithm.IsVaildArray(data) :
|
|
1539
|
-
return []
|
|
1540
|
-
|
|
1541
|
-
dataLen=len(data)
|
|
1542
|
-
result=JSAlgorithm.CreateArray(dataLen)
|
|
1543
|
-
|
|
1544
|
-
if (JSAlgorithm.IsArray(n)) :
|
|
1545
|
-
for i in range(len(n)) :
|
|
1546
|
-
period=n[i]
|
|
1547
|
-
if (not JSAlgorithm.IsNumber(period)):
|
|
1548
|
-
continue
|
|
1549
|
-
|
|
1550
|
-
period=int(period)
|
|
1551
|
-
if (period<1) :
|
|
1552
|
-
period=i+1
|
|
1553
|
-
|
|
1554
|
-
value=0
|
|
1555
|
-
for j in range(period) :
|
|
1556
|
-
index=i-j
|
|
1557
|
-
if index<0 :
|
|
1558
|
-
break
|
|
1559
|
-
if (JSAlgorithm.IsNumber(data[i])) :
|
|
1560
|
-
value+=data[i]
|
|
1561
|
-
|
|
1562
|
-
result[i]=value
|
|
1563
|
-
|
|
1564
|
-
else :
|
|
1565
|
-
n=int(n)
|
|
1566
|
-
if dataLen<n:
|
|
1567
|
-
return []
|
|
1568
|
-
|
|
1569
|
-
if n==0 :
|
|
1570
|
-
result[0]=data[0]
|
|
1571
|
-
for i in range(1,dataLen) :
|
|
1572
|
-
result[i] = result[i-1]+data[i]
|
|
1573
|
-
|
|
1574
|
-
else :
|
|
1575
|
-
j=0
|
|
1576
|
-
for i in range(n-1, dataLen) :
|
|
1577
|
-
for k in range(n) :
|
|
1578
|
-
if k==0:
|
|
1579
|
-
result[i]=data[k+j]
|
|
1580
|
-
else :
|
|
1581
|
-
result[i]+=data[k+j]
|
|
1582
|
-
j+=1
|
|
1583
|
-
|
|
1584
|
-
return result
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
# BARSCOUNT 有效数据周期数
|
|
1588
|
-
# 求总的周期数。
|
|
1589
|
-
# 用法: BARSCOUNT(X) 第一个有效数据到当前的天数。
|
|
1590
|
-
# 例如: BARSCOUNT(CLOSE) 对于日线数据取得上市以来总交易日数,对于分笔成交取得当日成交笔数,对于1分钟线取得当日交易分钟数。
|
|
1591
|
-
def BARSCOUNT(self,data):
|
|
1592
|
-
if not JSAlgorithm.IsVaildArray(data) :
|
|
1593
|
-
return []
|
|
1594
|
-
dataLen=len(data)
|
|
1595
|
-
result=JSAlgorithm.CreateArray(dataLen,0)
|
|
1596
|
-
|
|
1597
|
-
days=None
|
|
1598
|
-
for i in range(dataLen) :
|
|
1599
|
-
if days==None :
|
|
1600
|
-
if not JSAlgorithm.IsNumber(data[i]) :
|
|
1601
|
-
continue
|
|
1602
|
-
days=0
|
|
1603
|
-
|
|
1604
|
-
result[i]=days
|
|
1605
|
-
days+=1
|
|
1606
|
-
|
|
1607
|
-
return result
|
|
1608
|
-
|
|
1609
|
-
# DEVSQ 数据偏差平方和
|
|
1610
|
-
# DEVSQ(X,N) 返回数据偏差平方和。
|
|
1611
|
-
def DEVSQ(self,data,n) :
|
|
1612
|
-
if not JSAlgorithm.IsVaildArray(data) :
|
|
1613
|
-
return []
|
|
1614
|
-
|
|
1615
|
-
num = n
|
|
1616
|
-
datanum = len(data)
|
|
1617
|
-
i,k = 0, 0
|
|
1618
|
-
DEV = 0
|
|
1619
|
-
for i in range(datanum) : # 第1个有效数
|
|
1620
|
-
if JSAlgorithm.IsNumber(data[i]) :
|
|
1621
|
-
break
|
|
1622
|
-
|
|
1623
|
-
if num < 1 or i+num>datanum:
|
|
1624
|
-
return []
|
|
1625
|
-
|
|
1626
|
-
result=JSAlgorithm.CreateArray(datanum)
|
|
1627
|
-
j, E = 0 ,0
|
|
1628
|
-
for i in range(i,datanum) :
|
|
1629
|
-
if j>=num :
|
|
1630
|
-
break
|
|
1631
|
-
E += data[i]/num
|
|
1632
|
-
j+=1
|
|
1633
|
-
|
|
1634
|
-
if j==num:
|
|
1635
|
-
DEV = 0
|
|
1636
|
-
i-=1
|
|
1637
|
-
for k in range(num) :
|
|
1638
|
-
DEV += (data[i-k]-E) * (data[i-k]-E)
|
|
1639
|
-
result[i] = DEV
|
|
1640
|
-
i+=1
|
|
1641
|
-
|
|
1642
|
-
for i in range(i,datanum) :
|
|
1643
|
-
E += (data[i] - data[i-num]) / num
|
|
1644
|
-
DEV=0
|
|
1645
|
-
for k in range(num) :
|
|
1646
|
-
DEV += (data[i-k]-E) * (data[i-k]-E)
|
|
1647
|
-
result[i] = DEV
|
|
1648
|
-
|
|
1649
|
-
return result
|
|
1650
|
-
|
|
1651
|
-
# NOT 取反
|
|
1652
|
-
# 求逻辑非。
|
|
1653
|
-
# 用法: NOT(X) 返回非X,即当X=0时返回1,否则返回0。
|
|
1654
|
-
# 例如: NOT(ISUP) 表示平盘或收阴。
|
|
1655
|
-
def NOT(self,data) :
|
|
1656
|
-
if JSAlgorithm.IsNumber(data) :
|
|
1657
|
-
return 0 if data else 1
|
|
1658
|
-
|
|
1659
|
-
if not JSAlgorithm.IsVaildArray(data) :
|
|
1660
|
-
return []
|
|
1661
|
-
|
|
1662
|
-
dataLen=len(data)
|
|
1663
|
-
result=JSAlgorithm.CreateArray(dataLen)
|
|
1664
|
-
|
|
1665
|
-
for i in range(dataLen) :
|
|
1666
|
-
if JSAlgorithm.IsNumber(data[i]) :
|
|
1667
|
-
result[i]=0 if data[i] else 1
|
|
1668
|
-
|
|
1669
|
-
return result
|
|
1670
|
-
|
|
1671
|
-
# FORCAST 线性回归预测值
|
|
1672
|
-
# FORCAST(X,N) 返回线性回归预测值。
|
|
1673
|
-
def FORCAST(self,data,n):
|
|
1674
|
-
if not JSAlgorithm.IsVaildArray(data) :
|
|
1675
|
-
return []
|
|
1676
|
-
|
|
1677
|
-
num = n
|
|
1678
|
-
datanum = len(data)
|
|
1679
|
-
if num < 1 or num >= datanum :
|
|
1680
|
-
return []
|
|
1681
|
-
|
|
1682
|
-
result=JSAlgorithm.CreateArray(datanum)
|
|
1683
|
-
|
|
1684
|
-
for j in range(datanum) :
|
|
1685
|
-
if JSAlgorithm.IsNumber(data[j]) :
|
|
1686
|
-
break
|
|
1687
|
-
|
|
1688
|
-
for i in range(j+num-1,datanum) :
|
|
1689
|
-
Ex, Ey, Sxy, Sxx =0, 0, 0, 0
|
|
1690
|
-
for j in range(num) :
|
|
1691
|
-
if j>i :
|
|
1692
|
-
break
|
|
1693
|
-
Ex += (i - j)
|
|
1694
|
-
Ey += data[i - j]
|
|
1695
|
-
Ex /= num
|
|
1696
|
-
Ey /= num
|
|
1697
|
-
for j in range(num) :
|
|
1698
|
-
if j>i :
|
|
1699
|
-
break
|
|
1700
|
-
Sxy += (i-j-Ex)*(data[i-j]-Ey)
|
|
1701
|
-
Sxx += (i-j-Ex)*(i-j-Ex)
|
|
1702
|
-
|
|
1703
|
-
Slope = Sxy / Sxx
|
|
1704
|
-
Const = (Ey - Ex*Slope) / num
|
|
1705
|
-
result[i] = Slope * num + Const
|
|
1706
|
-
|
|
1707
|
-
return result
|
|
1708
|
-
|
|
1709
|
-
# SLOPE 线性回归斜率
|
|
1710
|
-
# SLOPE(X,N) 返回线性回归斜率。
|
|
1711
|
-
def SLOPE(self,data,n) :
|
|
1712
|
-
if not JSAlgorithm.IsVaildArray(data) :
|
|
1713
|
-
return []
|
|
1714
|
-
|
|
1715
|
-
dataLen=len(data)
|
|
1716
|
-
if n<1 or n>=dataLen :
|
|
1717
|
-
return []
|
|
1718
|
-
|
|
1719
|
-
result=JSAlgorithm.CreateArray(dataLen)
|
|
1720
|
-
for start in range(dataLen) :
|
|
1721
|
-
if JSAlgorithm.IsNumber(data[start]) :
|
|
1722
|
-
break
|
|
1723
|
-
|
|
1724
|
-
for i in range(start+n-1,dataLen) :
|
|
1725
|
-
x, y, xy, xx = 0,0,0,0
|
|
1726
|
-
for j in range(n) :
|
|
1727
|
-
if j>i:
|
|
1728
|
-
break
|
|
1729
|
-
x+=(i-j) # 数据索引相加
|
|
1730
|
-
y+=data[i-j] # 数据相加
|
|
1731
|
-
|
|
1732
|
-
x=x/n
|
|
1733
|
-
y=y/n
|
|
1734
|
-
|
|
1735
|
-
for j in range(n) :
|
|
1736
|
-
if j>i :
|
|
1737
|
-
break
|
|
1738
|
-
xy+=(i-j-x)*(data[i-j]-y)
|
|
1739
|
-
xx+=(i-j-x)*(i-j-x)
|
|
1740
|
-
|
|
1741
|
-
if xx :
|
|
1742
|
-
result[i]= xy/xx
|
|
1743
|
-
elif i :
|
|
1744
|
-
result[i]=result[i-1]
|
|
1745
|
-
|
|
1746
|
-
return result
|
|
1747
|
-
|
|
1748
|
-
# STDP 总体标准差
|
|
1749
|
-
# STDP(X,N) 返回总体标准差。
|
|
1750
|
-
def STDP(self,data,n) :
|
|
1751
|
-
if not JSAlgorithm.IsVaildArray(data) :
|
|
1752
|
-
return []
|
|
1753
|
-
|
|
1754
|
-
num = n
|
|
1755
|
-
datanum = len(data)
|
|
1756
|
-
if num < 1 or num >= datanum :
|
|
1757
|
-
return []
|
|
1758
|
-
|
|
1759
|
-
result=JSAlgorithm.CreateArray(datanum)
|
|
1760
|
-
for i in range(datanum) :
|
|
1761
|
-
if JSAlgorithm.IsNumber(data[i]) :
|
|
1762
|
-
break
|
|
1763
|
-
|
|
1764
|
-
SigmaPowerX ,SigmaX, MidResult =0,0,0
|
|
1765
|
-
for j in range(num) :
|
|
1766
|
-
if i>=datanum :
|
|
1767
|
-
break
|
|
1768
|
-
SigmaPowerX += data[i] * data[i]
|
|
1769
|
-
SigmaX += data[i]
|
|
1770
|
-
i+=1
|
|
1771
|
-
|
|
1772
|
-
if j == num:
|
|
1773
|
-
MidResult = num*SigmaPowerX - SigmaX*SigmaX
|
|
1774
|
-
result[i-1] = math.sqrt(MidResult) / num
|
|
1775
|
-
|
|
1776
|
-
for i in range(i,datanum) :
|
|
1777
|
-
SigmaPowerX += data[i]*data[i] - data[i-num]*data[i-num]
|
|
1778
|
-
SigmaX += data[i] - data[i-num]
|
|
1779
|
-
MidResult = num*SigmaPowerX - SigmaX*SigmaX
|
|
1780
|
-
result[i] = math.sqrt(MidResult) / num
|
|
1781
|
-
|
|
1782
|
-
return result
|
|
1783
|
-
|
|
1784
|
-
# VAR 估算样本方差
|
|
1785
|
-
# VAR(X,N) 返回估算样本方差。
|
|
1786
|
-
def VAR(self,data,n) :
|
|
1787
|
-
if not JSAlgorithm.IsVaildArray(data) :
|
|
1788
|
-
return []
|
|
1789
|
-
|
|
1790
|
-
num = n
|
|
1791
|
-
datanum = len(data)
|
|
1792
|
-
if num <= 1 or num >= datanum :
|
|
1793
|
-
return []
|
|
1794
|
-
|
|
1795
|
-
result=JSAlgorithm.CreateArray(datanum)
|
|
1796
|
-
for i in range(datanum) :
|
|
1797
|
-
if JSAlgorithm.IsNumber(data[i]) :
|
|
1798
|
-
break
|
|
1799
|
-
|
|
1800
|
-
for i in range(i+num-1,datanum) :
|
|
1801
|
-
SigmaPowerX = SigmaX = 0
|
|
1802
|
-
for j in range(num) :
|
|
1803
|
-
if j>i :
|
|
1804
|
-
break
|
|
1805
|
-
SigmaPowerX += data[i-j] * data[i-j]
|
|
1806
|
-
SigmaX += data[i-j]
|
|
1807
|
-
|
|
1808
|
-
result[i] = (num*SigmaPowerX - SigmaX*SigmaX) / num * (num -1)
|
|
1809
|
-
|
|
1810
|
-
return result
|
|
1811
|
-
|
|
1812
|
-
# VARP 总体样本方差
|
|
1813
|
-
# VARP(X,N) 返回总体样本方差 。
|
|
1814
|
-
def VARP(self,data,n) :
|
|
1815
|
-
if not JSAlgorithm.IsVaildArray(data) :
|
|
1816
|
-
return []
|
|
1817
|
-
|
|
1818
|
-
num = n
|
|
1819
|
-
datanum = len(data)
|
|
1820
|
-
if num < 1 or num >= datanum :
|
|
1821
|
-
return []
|
|
1822
|
-
|
|
1823
|
-
result=JSAlgorithm.CreateArray(datanum)
|
|
1824
|
-
|
|
1825
|
-
for i in range(datanum) :
|
|
1826
|
-
if JSAlgorithm.IsNumber(data[i]) :
|
|
1827
|
-
break
|
|
1828
|
-
|
|
1829
|
-
SigmaPowerX , SigmaX = 0,0
|
|
1830
|
-
for j in range(num) :
|
|
1831
|
-
if i>=datanum :
|
|
1832
|
-
break
|
|
1833
|
-
SigmaPowerX += data[i] * data[i]
|
|
1834
|
-
SigmaX += data[i]
|
|
1835
|
-
i+=1
|
|
1836
|
-
|
|
1837
|
-
if j == num :
|
|
1838
|
-
result[i-1] = (num*SigmaPowerX - SigmaX*SigmaX) / (num*num)
|
|
1839
|
-
|
|
1840
|
-
for i in range(i,datanum) :
|
|
1841
|
-
SigmaPowerX += data[i]*data[i] - data[i-num]*data[i-num]
|
|
1842
|
-
SigmaX += data[i] - data[i-num]
|
|
1843
|
-
result[i] = (num*SigmaPowerX - SigmaX*SigmaX) / (num*num)
|
|
1844
|
-
|
|
1845
|
-
return result
|
|
1846
|
-
|
|
1847
|
-
# RANGE(A,B,C)表示A>B AND A<C;
|
|
1848
|
-
def RANGE(self, data,range,range2) :
|
|
1849
|
-
isNumber=JSAlgorithm.IsNumber(data)
|
|
1850
|
-
isNumber2=JSAlgorithm.IsNumber(range)
|
|
1851
|
-
isNumber3=JSAlgorithm.IsNumber(range2)
|
|
1852
|
-
|
|
1853
|
-
if isNumber and isNumber2 and isNumber3 :
|
|
1854
|
-
if data>min(range,range2) and data<max(range,range2):
|
|
1855
|
-
return 1
|
|
1856
|
-
else :
|
|
1857
|
-
return 0
|
|
1858
|
-
|
|
1859
|
-
if not JSAlgorithm.IsVaildArray(data) :
|
|
1860
|
-
return []
|
|
1861
|
-
|
|
1862
|
-
dataLen=len(data)
|
|
1863
|
-
result=JSAlgorithm.CreateArray(dataLen)
|
|
1864
|
-
|
|
1865
|
-
for i in range(dataLen) :
|
|
1866
|
-
value=data[i]
|
|
1867
|
-
if JSAlgorithm.IsNumber(value) :
|
|
1868
|
-
continue
|
|
1869
|
-
|
|
1870
|
-
if not isNumber2 :
|
|
1871
|
-
if i>=len(range) :
|
|
1872
|
-
continue
|
|
1873
|
-
rangeValue=range[i]
|
|
1874
|
-
else :
|
|
1875
|
-
rangeValue=range
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
if not JSAlgorithm.IsNumber(rangeValue) :
|
|
1879
|
-
continue
|
|
1880
|
-
|
|
1881
|
-
if not isNumber3 :
|
|
1882
|
-
if i>=len(range2) :
|
|
1883
|
-
continue
|
|
1884
|
-
|
|
1885
|
-
rangeValue2=range2[i]
|
|
1886
|
-
else :
|
|
1887
|
-
rangeValue2=range2
|
|
1888
|
-
|
|
1889
|
-
if not JSAlgorithm.IsNumber(rangeValue2) :
|
|
1890
|
-
continue
|
|
1891
|
-
|
|
1892
|
-
result[i]= 1 if value>min(rangeValue,rangeValue2) and value<max(rangeValue,rangeValue2) else 0
|
|
1893
|
-
|
|
1894
|
-
return result
|
|
1895
|
-
|
|
1896
|
-
def EXIST(self,data,n) :
|
|
1897
|
-
if not JSAlgorithm.IsVaildArray(data) :
|
|
1898
|
-
return []
|
|
1899
|
-
|
|
1900
|
-
if (JSAlgorithm.IsArray(n)) :
|
|
1901
|
-
dataLen = len(data)
|
|
1902
|
-
result=JSAlgorithm.CreateArray(dataLen,0)
|
|
1903
|
-
for i in range(len(n)) :
|
|
1904
|
-
if (i>=dataLen):
|
|
1905
|
-
break
|
|
1906
|
-
period=n[i]
|
|
1907
|
-
if (not JSAlgorithm.IsNumber(period)) :
|
|
1908
|
-
continue
|
|
1909
|
-
period=int(period)
|
|
1910
|
-
if (period<=0):
|
|
1911
|
-
continue
|
|
1912
|
-
if (period>i+1) :
|
|
1913
|
-
period=i+1
|
|
1914
|
-
|
|
1915
|
-
bFind=False
|
|
1916
|
-
for j in range(period):
|
|
1917
|
-
index=i-(period-j-1)
|
|
1918
|
-
value=data[index]
|
|
1919
|
-
if (JSAlgorithm.IsNumber(value) and value>0):
|
|
1920
|
-
bFind=True
|
|
1921
|
-
break
|
|
1922
|
-
if (bFind):
|
|
1923
|
-
result[i]=1
|
|
1924
|
-
else:
|
|
1925
|
-
result[i]=0
|
|
1926
|
-
|
|
1927
|
-
return result
|
|
1928
|
-
|
|
1929
|
-
else :
|
|
1930
|
-
dataLen = len(data)
|
|
1931
|
-
result=JSAlgorithm.CreateArray(dataLen)
|
|
1932
|
-
latestID=None # 最新满足条件的数据索引
|
|
1933
|
-
n=int(n)
|
|
1934
|
-
for i in range(dataLen) :
|
|
1935
|
-
value=data[i]
|
|
1936
|
-
if JSAlgorithm.IsNumber(value) and value>0:
|
|
1937
|
-
latestID=i # 最新满足条件的数据索引
|
|
1938
|
-
|
|
1939
|
-
if latestID!=None and i-latestID<n :
|
|
1940
|
-
result[i]=1
|
|
1941
|
-
else :
|
|
1942
|
-
result[i]=0
|
|
1943
|
-
|
|
1944
|
-
return result
|
|
1945
|
-
|
|
1946
|
-
def TFILTER(self, data,data2,n) :
|
|
1947
|
-
# TODO: 待完成
|
|
1948
|
-
return []
|
|
1949
|
-
|
|
1950
|
-
# 过滤连续出现的信号.
|
|
1951
|
-
# 用法:FILTER(X,N):X满足条件后,将其后N周期内的数据置为0,N为常量.
|
|
1952
|
-
# 例如: FILTER(CLOSE>OPEN,5)查找阳线,5天内再次出现的阳线不被记录在内
|
|
1953
|
-
def FILTER(self,data,n) :
|
|
1954
|
-
if not JSAlgorithm.IsVaildArray(data) :
|
|
1955
|
-
return []
|
|
1956
|
-
|
|
1957
|
-
dataLen = len(data)
|
|
1958
|
-
result=JSAlgorithm.CreateArray(dataLen)
|
|
1959
|
-
for i in range(dataLen) :
|
|
1960
|
-
if data[i] :
|
|
1961
|
-
result[i]=1
|
|
1962
|
-
for j in range(n) :
|
|
1963
|
-
if j+i+1>=dataLen :
|
|
1964
|
-
break
|
|
1965
|
-
result[j+i+1]=0
|
|
1966
|
-
i+=n
|
|
1967
|
-
else :
|
|
1968
|
-
result[i]=0
|
|
1969
|
-
|
|
1970
|
-
return result
|
|
1971
|
-
|
|
1972
|
-
def BARSLAST(self, data) :
|
|
1973
|
-
if not JSAlgorithm.IsVaildArray(data) :
|
|
1974
|
-
return []
|
|
1975
|
-
|
|
1976
|
-
dataLen = len(data)
|
|
1977
|
-
result=JSAlgorithm.CreateArray(dataLen)
|
|
1978
|
-
day=None
|
|
1979
|
-
for i in range(dataLen) :
|
|
1980
|
-
if data[i]>0:
|
|
1981
|
-
day=0
|
|
1982
|
-
elif day!=None :
|
|
1983
|
-
day+=1
|
|
1984
|
-
|
|
1985
|
-
if day!=None :
|
|
1986
|
-
result[i]=day
|
|
1987
|
-
|
|
1988
|
-
return result
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
# N周期内第一个条件成立到当前的周期数.
|
|
1992
|
-
# 用法: BARSSINCEN(X,N):N周期内第一次X不为0到现在的天数,N为常量
|
|
1993
|
-
# 例如: BARSSINCEN(HIGH>10,10)表示10个周期内股价超过10元时到当前的周期数
|
|
1994
|
-
def BARSSINCEN(self, data,n) :
|
|
1995
|
-
if not JSAlgorithm.IsVaildArray(data) :
|
|
1996
|
-
return []
|
|
1997
|
-
|
|
1998
|
-
dataLen = len(data)
|
|
1999
|
-
result=JSAlgorithm.CreateArray(dataLen)
|
|
2000
|
-
|
|
2001
|
-
day=None
|
|
2002
|
-
for i in range(dataLen) :
|
|
2003
|
-
if day==None :
|
|
2004
|
-
if data[i] :
|
|
2005
|
-
day=0
|
|
2006
|
-
else :
|
|
2007
|
-
if data[i] :
|
|
2008
|
-
if day+1<n :
|
|
2009
|
-
day+=1
|
|
2010
|
-
else :
|
|
2011
|
-
day=None
|
|
2012
|
-
|
|
2013
|
-
if day:
|
|
2014
|
-
result[i]=day
|
|
2015
|
-
|
|
2016
|
-
return result
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
# 第一个条件成立到当前的周期数.
|
|
2020
|
-
# 用法: BARSSINCE(X):第一次X不为0到现在的天数
|
|
2021
|
-
# 例如: BARSSINCE(HIGH>10)表示股价超过10元时到当前的周期数
|
|
2022
|
-
def BARSSINCE(self, data) :
|
|
2023
|
-
if not JSAlgorithm.IsVaildArray(data) :
|
|
2024
|
-
return []
|
|
2025
|
-
|
|
2026
|
-
dataLen = len(data)
|
|
2027
|
-
result=JSAlgorithm.CreateArray(dataLen)
|
|
2028
|
-
day=None
|
|
2029
|
-
for i in range(dataLen) :
|
|
2030
|
-
if day==None :
|
|
2031
|
-
if data[i] :
|
|
2032
|
-
day=0
|
|
2033
|
-
else :
|
|
2034
|
-
day+=1
|
|
2035
|
-
|
|
2036
|
-
if day :
|
|
2037
|
-
result[i]=day
|
|
2038
|
-
|
|
2039
|
-
return result
|
|
2040
|
-
|
|
2041
|
-
# 三角函数调用 func 三角函数
|
|
2042
|
-
# 反正切值. 用法: ATAN(X)返回X的反正切值
|
|
2043
|
-
# 反余弦值. 用法: ACOS(X)返回X的反余弦值
|
|
2044
|
-
# 反正弦值. 用法: ASIN(X)返回X的反正弦值
|
|
2045
|
-
# 余弦值. 用法: COS(X)返回X的余弦值
|
|
2046
|
-
# 正弦值. 用法: SIN(X)返回X的正弦值
|
|
2047
|
-
# 正切值. 用法: TAN(X)返回X的正切值
|
|
2048
|
-
#
|
|
2049
|
-
# 求自然对数. 用法: LN(X)以e为底的对数 例如: LN(CLOSE)求收盘价的对数
|
|
2050
|
-
# 求10为底的对数. 用法: LOG(X)取得X的对数 例如: LOG(100)等于2
|
|
2051
|
-
# 指数. 用法: EXP(X)为e的X次幂 例如: EXP(CLOSE)返回e的CLOSE次幂
|
|
2052
|
-
# 开平方. 用法: SQRT(X)为X的平方根 例如: SQRT(CLOSE)收盘价的平方根
|
|
2053
|
-
def Trigonometric(self, data,func) :
|
|
2054
|
-
if JSAlgorithm.IsNumber(data) :
|
|
2055
|
-
return func(data)
|
|
2056
|
-
|
|
2057
|
-
if not JSAlgorithm.IsVaildArray(data) :
|
|
2058
|
-
return []
|
|
2059
|
-
|
|
2060
|
-
dataLen=len(data)
|
|
2061
|
-
result=JSAlgorithm.CreateArray(dataLen)
|
|
2062
|
-
for i in range(dataLen) :
|
|
2063
|
-
item=data[i]
|
|
2064
|
-
if JSAlgorithm.IsNumber(item) :
|
|
2065
|
-
result[i]=func(item)
|
|
2066
|
-
|
|
2067
|
-
return result
|
|
2068
|
-
|
|
2069
|
-
# LAST(X,A,B):持续存在.
|
|
2070
|
-
# 用法: LAST(CLOSE>OPEN,10,5)
|
|
2071
|
-
# 表示从前10日到前5日内一直阳线
|
|
2072
|
-
# 若A为0,表示从第一天开始,B为0,表示到最后日止
|
|
2073
|
-
def LAST(self, data,n,n2) :
|
|
2074
|
-
if not JSAlgorithm.IsVaildArray(data) :
|
|
2075
|
-
return []
|
|
2076
|
-
|
|
2077
|
-
dataLen=len(data)
|
|
2078
|
-
if n2<=0:
|
|
2079
|
-
n2=dataLen-1
|
|
2080
|
-
if n2>n :
|
|
2081
|
-
return []
|
|
2082
|
-
|
|
2083
|
-
result=JSAlgorithm.CreateArray(dataLen,0)
|
|
2084
|
-
for i in range(dataLen) :
|
|
2085
|
-
day=0
|
|
2086
|
-
start=i-n
|
|
2087
|
-
end=i-n2
|
|
2088
|
-
if start<0 or end<0 :
|
|
2089
|
-
continue
|
|
2090
|
-
|
|
2091
|
-
for j in range(start, dataLen) :
|
|
2092
|
-
if j>end :
|
|
2093
|
-
break
|
|
2094
|
-
if not data[j] :
|
|
2095
|
-
break
|
|
2096
|
-
day+=1
|
|
2097
|
-
|
|
2098
|
-
if day==end-start+1 : #[start,end]
|
|
2099
|
-
result[i]=1
|
|
2100
|
-
|
|
2101
|
-
return result
|
|
2102
|
-
|
|
2103
|
-
# 返回是否连涨周期数.
|
|
2104
|
-
# 用法: UPNDAY(CLOSE,M)
|
|
2105
|
-
# 表示连涨M个周期,M为常量
|
|
2106
|
-
def UPNDAY(self, data,n) :
|
|
2107
|
-
if not JSAlgorithm.IsVaildArray(data) or n<1 :
|
|
2108
|
-
return []
|
|
2109
|
-
|
|
2110
|
-
dataLen=len(data)
|
|
2111
|
-
result=JSAlgorithm.CreateArray(dataLen,0)
|
|
2112
|
-
days=0
|
|
2113
|
-
for i in range(dataLen) :
|
|
2114
|
-
if i-1<0 :
|
|
2115
|
-
continue
|
|
2116
|
-
|
|
2117
|
-
if not JSAlgorithm.IsNumber(data[i]) or not JSAlgorithm.IsNumber(data[i-1]) : # 无效数都不算连涨
|
|
2118
|
-
days=0
|
|
2119
|
-
continue
|
|
2120
|
-
|
|
2121
|
-
if data[i]>data[i-1] :
|
|
2122
|
-
days+=1
|
|
2123
|
-
else :
|
|
2124
|
-
days=0
|
|
2125
|
-
|
|
2126
|
-
if days==n :
|
|
2127
|
-
result[i]=1
|
|
2128
|
-
days-=1
|
|
2129
|
-
|
|
2130
|
-
return result
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
# 返回是否连跌周期.
|
|
2134
|
-
# 用法: DOWNNDAY(CLOSE,M)
|
|
2135
|
-
# 表示连跌M个周期,M为常量
|
|
2136
|
-
def DOWNNDAY(self,data,n) :
|
|
2137
|
-
if not JSAlgorithm.IsVaildArray(data) or n<1 :
|
|
2138
|
-
return []
|
|
2139
|
-
|
|
2140
|
-
dataLen=len(data)
|
|
2141
|
-
result=JSAlgorithm.CreateArray(dataLen,0)
|
|
2142
|
-
days=0
|
|
2143
|
-
for i in range(dataLen) :
|
|
2144
|
-
if i-1<0 :
|
|
2145
|
-
continue
|
|
2146
|
-
if not JSAlgorithm.IsNumber(data[i]) or not JSAlgorithm.IsNumber(data[i-1]) : # 无效数都不算连涨
|
|
2147
|
-
days=0
|
|
2148
|
-
continue
|
|
2149
|
-
|
|
2150
|
-
if data[i]<data[i-1] :
|
|
2151
|
-
days+=1
|
|
2152
|
-
else :
|
|
2153
|
-
days=0
|
|
2154
|
-
|
|
2155
|
-
if days==n :
|
|
2156
|
-
result[i]=1
|
|
2157
|
-
days-=1
|
|
2158
|
-
|
|
2159
|
-
return result
|
|
2160
|
-
|
|
2161
|
-
#返回是否持续存在X>Y
|
|
2162
|
-
#用法:
|
|
2163
|
-
#NDAY(CLOSE,OPEN,3)
|
|
2164
|
-
#表示连续3日收阳线
|
|
2165
|
-
def NDAY(self,data,data2,n):
|
|
2166
|
-
if n<1:
|
|
2167
|
-
return []
|
|
2168
|
-
if not JSAlgorithm.IsArray(data) and not JSAlgorithm.IsArray(data2):
|
|
2169
|
-
return []
|
|
2170
|
-
|
|
2171
|
-
if JSAlgorithm.IsArray(data) and JSAlgorithm.IsArray(data2) :
|
|
2172
|
-
len1 , len2= len(data), len(data2)
|
|
2173
|
-
if n>=len1 or n>=len2 :
|
|
2174
|
-
return []
|
|
2175
|
-
|
|
2176
|
-
count=max(len1,len2)
|
|
2177
|
-
result=JSAlgorithm.CreateArray(count,0)
|
|
2178
|
-
days=0
|
|
2179
|
-
for i in range(count):
|
|
2180
|
-
if i>=len1 or i>=len2:
|
|
2181
|
-
continue
|
|
2182
|
-
if not JSAlgorithm.IsNumber(data[i]) or not JSAlgorithm.IsNumber(data2[i]) :
|
|
2183
|
-
days=0
|
|
2184
|
-
continue
|
|
2185
|
-
|
|
2186
|
-
if data[i]>data2[i] :
|
|
2187
|
-
days+=1
|
|
2188
|
-
else :
|
|
2189
|
-
days=0
|
|
2190
|
-
|
|
2191
|
-
if days==n :
|
|
2192
|
-
result[i]=1
|
|
2193
|
-
days-=1
|
|
2194
|
-
|
|
2195
|
-
elif JSAlgorithm.IsArray(data) and JSAlgorithm.IsNumber(data2) :
|
|
2196
|
-
len1=len(data)
|
|
2197
|
-
if n>=len1 :
|
|
2198
|
-
return []
|
|
2199
|
-
|
|
2200
|
-
result=JSAlgorithm.CreateArray(len1,0)
|
|
2201
|
-
days=0
|
|
2202
|
-
for i in range(len1) :
|
|
2203
|
-
if not JSAlgorithm.IsNumber(data[i]) :
|
|
2204
|
-
days=0
|
|
2205
|
-
continue
|
|
2206
|
-
|
|
2207
|
-
if data[i]>data2 :
|
|
2208
|
-
days+=1
|
|
2209
|
-
else :
|
|
2210
|
-
days=0
|
|
2211
|
-
|
|
2212
|
-
if days==n :
|
|
2213
|
-
result[i]=1
|
|
2214
|
-
days-=1
|
|
2215
|
-
|
|
2216
|
-
elif JSAlgorithm.IsNumber(data) and JSAlgorithm.IsArray(data2) :
|
|
2217
|
-
len2=len(data2)
|
|
2218
|
-
if n>=len2 :
|
|
2219
|
-
return []
|
|
2220
|
-
|
|
2221
|
-
result=JSAlgorithm.CreateArray(len2,0)
|
|
2222
|
-
days=0
|
|
2223
|
-
for i in range(len2) :
|
|
2224
|
-
if not JSAlgorithm.IsNumber(data2[i]) :
|
|
2225
|
-
days=0
|
|
2226
|
-
continue
|
|
2227
|
-
|
|
2228
|
-
if data>data2[i] :
|
|
2229
|
-
days+=1
|
|
2230
|
-
else :
|
|
2231
|
-
days=0
|
|
2232
|
-
|
|
2233
|
-
if days==n :
|
|
2234
|
-
result[i]=1
|
|
2235
|
-
days-=1
|
|
2236
|
-
|
|
2237
|
-
return result
|
|
2238
|
-
|
|
2239
|
-
# 两条线维持一定周期后交叉.
|
|
2240
|
-
# 用法:LONGCROSS(A,B,N)表示A在N周期内都小于B,本周期从下方向上穿过B时返回1,否则返回0
|
|
2241
|
-
def LONGCROSS(self,data,data2,n) :
|
|
2242
|
-
if not JSAlgorithm.IsArray(data) and not JSAlgorithm.IsArray(data2) :
|
|
2243
|
-
return []
|
|
2244
|
-
|
|
2245
|
-
if n<1 :
|
|
2246
|
-
return []
|
|
2247
|
-
|
|
2248
|
-
len1 , len2= len(data), len(data2)
|
|
2249
|
-
count=max(len1,len2)
|
|
2250
|
-
result=JSAlgorithm.CreateArray(count,0)
|
|
2251
|
-
for i in range(count) :
|
|
2252
|
-
if i-1<0:
|
|
2253
|
-
continue
|
|
2254
|
-
if i>=len1 or i>=len2 :
|
|
2255
|
-
continue
|
|
2256
|
-
|
|
2257
|
-
if not JSAlgorithm.Is2Number(data[i], data2[i]) or not JSAlgorithm.Is2Number(data[i-1],data2[i-1]) :
|
|
2258
|
-
continue
|
|
2259
|
-
|
|
2260
|
-
if data[i]>data2[i] and data[i-1]<data2[i-1] :
|
|
2261
|
-
result[i]=1
|
|
2262
|
-
|
|
2263
|
-
for i in range(count) :
|
|
2264
|
-
if not result[i] :
|
|
2265
|
-
continue
|
|
2266
|
-
for j in range(n) :
|
|
2267
|
-
if i-j<0 :
|
|
2268
|
-
break
|
|
2269
|
-
if data[i-j]>=data2[i-j] :
|
|
2270
|
-
result[i]=0
|
|
2271
|
-
break
|
|
2272
|
-
|
|
2273
|
-
return result
|
|
2274
|
-
|
|
2275
|
-
# EXISTR(X,A,B):是否存在(前几日到前几日间).
|
|
2276
|
-
# 例如: EXISTR(CLOSE>OPEN,10,5)
|
|
2277
|
-
# 表示从前10日内到前5日内存在着阳线
|
|
2278
|
-
# 若A为0,表示从第一天开始,B为0,表示到最后日止
|
|
2279
|
-
def EXISTR(self,data,n,n2) :
|
|
2280
|
-
if not JSAlgorithm.IsArray(data) :
|
|
2281
|
-
return []
|
|
2282
|
-
|
|
2283
|
-
dataLen=len(data)
|
|
2284
|
-
|
|
2285
|
-
if n<=0 :
|
|
2286
|
-
n=dataLen
|
|
2287
|
-
if n2<=0:
|
|
2288
|
-
n2=1
|
|
2289
|
-
if n2>n :
|
|
2290
|
-
return []
|
|
2291
|
-
|
|
2292
|
-
result=JSAlgorithm.CreateArray(dataLen)
|
|
2293
|
-
for i in range(dataLen) :
|
|
2294
|
-
if i-n<0 or i-n2<0 :
|
|
2295
|
-
continue
|
|
2296
|
-
|
|
2297
|
-
result[i]=0
|
|
2298
|
-
for j in range(n,n2-1,-1) :
|
|
2299
|
-
value=data[i-j]
|
|
2300
|
-
if JSAlgorithm.IsNumber(value) and value :
|
|
2301
|
-
result[i]=1
|
|
2302
|
-
break
|
|
2303
|
-
|
|
2304
|
-
return result
|
|
2305
|
-
|
|
2306
|
-
# RELATE(X,Y,N) 返回X和Y的N周期的相关系数
|
|
2307
|
-
# RELATE(X,Y,N)=(∑[(Xi-Avg(X))(Yi-Avg(y))])/N ÷ √((∑(Xi-Avg(X))^2)/N * (∑(Yi-Avg(Y))^2)/N)
|
|
2308
|
-
# 其中 avg(x)表示x的N周期均值: avg(X) = (∑Xi)/N
|
|
2309
|
-
# √(...)表示开平方
|
|
2310
|
-
def RELATE(self,data,data2,n) :
|
|
2311
|
-
if not JSAlgorithm.IsVaildArray(data) or not JSAlgorithm.IsVaildArray(data2) :
|
|
2312
|
-
return []
|
|
2313
|
-
|
|
2314
|
-
if n<1:
|
|
2315
|
-
n=1
|
|
2316
|
-
|
|
2317
|
-
dataAverage=JSAlgorithm.ArrayAverage(data,n)
|
|
2318
|
-
data2Average=JSAlgorithm.ArrayAverage(data2,n)
|
|
2319
|
-
|
|
2320
|
-
count=max(len(data),len(data2))
|
|
2321
|
-
result=JSAlgorithm.CreateArray(count)
|
|
2322
|
-
for i in range(count) :
|
|
2323
|
-
if i>=len(data) or i>=len(data2) or i>=len(dataAverage) or i>=len(data2Average) :
|
|
2324
|
-
continue
|
|
2325
|
-
|
|
2326
|
-
average=dataAverage[i]
|
|
2327
|
-
average2=data2Average[i]
|
|
2328
|
-
|
|
2329
|
-
total,total2,total3 = 0,0,0
|
|
2330
|
-
for j in range(i-n+1, i+1) :
|
|
2331
|
-
total+=(data[j]-average)*(data2[j]-average2) # ∑[(Xi-Avg(X))(Yi-Avg(y))])
|
|
2332
|
-
total2+=math.pow(data[j]-average,2) # ∑(Xi-Avg(X))^2
|
|
2333
|
-
total3+=math.pow(data2[j]-average2,2) # ∑(Yi-Avg(Y))^2)
|
|
2334
|
-
|
|
2335
|
-
result[i]=(total/n)/(math.sqrt(total2/n)*math.sqrt(total3/n))
|
|
2336
|
-
|
|
2337
|
-
return result
|
|
2338
|
-
|
|
2339
|
-
|
|
2340
|
-
# COVAR(X,Y,N) 返回X和Y的N周期的协方差
|
|
2341
|
-
def COVAR(self,data,data2,n) :
|
|
2342
|
-
if not JSAlgorithm.IsArray(data) or not JSAlgorithm.IsArray(data2) :
|
|
2343
|
-
return []
|
|
2344
|
-
|
|
2345
|
-
if n<1:
|
|
2346
|
-
n=1
|
|
2347
|
-
|
|
2348
|
-
dataAverage=JSAlgorithm.ArrayAverage(data,n)
|
|
2349
|
-
data2Average=JSAlgorithm.ArrayAverage(data2,n)
|
|
2350
|
-
len1, len2= len(data), len(data2)
|
|
2351
|
-
count=max(len1,len2)
|
|
2352
|
-
result=JSAlgorithm.CreateArray(count)
|
|
2353
|
-
|
|
2354
|
-
for i in range(count) :
|
|
2355
|
-
if i>=len1 or i>=len2 or i>=len(dataAverage) or i>=len(data2Average) :
|
|
2356
|
-
continue
|
|
2357
|
-
|
|
2358
|
-
average=dataAverage[i]
|
|
2359
|
-
average2=data2Average[i]
|
|
2360
|
-
|
|
2361
|
-
total=0
|
|
2362
|
-
for j in range(i-n+1, i+1) :
|
|
2363
|
-
total+=(data[j]-average)*(data2[j]-average2)
|
|
2364
|
-
result[i]=(total/n)
|
|
2365
|
-
|
|
2366
|
-
return result
|
|
2367
|
-
|
|
2368
|
-
|
|
2369
|
-
|
|
2370
|
-
# 求上一高点到当前的周期数.
|
|
2371
|
-
# 用法: HHVBARS(X,N):求N周期内X最高值到当前周期数,N=0表示从第一个有效值开始统计
|
|
2372
|
-
# 例如: HHVBARS(HIGH,0)求得历史新高到到当前的周期数
|
|
2373
|
-
def HHVBARS(self,data,n) :
|
|
2374
|
-
if not JSAlgorithm.IsVaildArray(data) :
|
|
2375
|
-
return []
|
|
2376
|
-
|
|
2377
|
-
dataLen=len(data)
|
|
2378
|
-
if n<1:
|
|
2379
|
-
n=dataLen
|
|
2380
|
-
|
|
2381
|
-
result=JSAlgorithm.CreateArray(dataLen)
|
|
2382
|
-
nMax=None # 最大值索引
|
|
2383
|
-
for i in range(dataLen) :
|
|
2384
|
-
if JSAlgorithm.IsNumber(data[i]) :
|
|
2385
|
-
nMax=i
|
|
2386
|
-
break
|
|
2387
|
-
|
|
2388
|
-
j=0
|
|
2389
|
-
for i in range(nMax+1,dataLen) : # 求第1个最大值
|
|
2390
|
-
if j>=n :
|
|
2391
|
-
break
|
|
2392
|
-
|
|
2393
|
-
if data[i]>=data[nMax]:
|
|
2394
|
-
nMax=i
|
|
2395
|
-
if n==dataLen :
|
|
2396
|
-
result[i]=(i-nMax)
|
|
2397
|
-
j+=1
|
|
2398
|
-
|
|
2399
|
-
for i in range(i,dataLen) :
|
|
2400
|
-
if i-nMax<n :
|
|
2401
|
-
if data[i]>=data[nMax] :
|
|
2402
|
-
nMax=i
|
|
2403
|
-
else :
|
|
2404
|
-
nMax=i-n+1
|
|
2405
|
-
for j in range(nMax, i+1) : # 计算区间最大值
|
|
2406
|
-
if data[j]>=data[nMax] :
|
|
2407
|
-
nMax=j
|
|
2408
|
-
|
|
2409
|
-
result[i]=i-nMax
|
|
2410
|
-
|
|
2411
|
-
return result
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
# 求上一低点到当前的周期数.
|
|
2415
|
-
# 用法: LLVBARS(X,N):求N周期内X最低值到当前周期数,N=0表示从第一个有效值开始统计
|
|
2416
|
-
# 例如: LLVBARS(HIGH,20)求得20日最低点到当前的周期数
|
|
2417
|
-
def LLVBARS(self, data,n) :
|
|
2418
|
-
if not JSAlgorithm.IsVaildArray(data) :
|
|
2419
|
-
return []
|
|
2420
|
-
|
|
2421
|
-
dataLen=len(data)
|
|
2422
|
-
if n<1 :
|
|
2423
|
-
n=dataLen
|
|
2424
|
-
|
|
2425
|
-
result=JSAlgorithm.CreateArray(dataLen)
|
|
2426
|
-
nMin=None # 最小值索引
|
|
2427
|
-
for i in range(dataLen) :
|
|
2428
|
-
if JSAlgorithm.IsNumber(data[i]) :
|
|
2429
|
-
nMin=i
|
|
2430
|
-
break
|
|
2431
|
-
|
|
2432
|
-
j=0
|
|
2433
|
-
for i in range(nMin+1,dataLen) : # 求第1个最大值
|
|
2434
|
-
if j>=n :
|
|
2435
|
-
break
|
|
2436
|
-
if data[i]<=data[nMin] :
|
|
2437
|
-
nMin=i
|
|
2438
|
-
if n==dataLen :
|
|
2439
|
-
result[i]=i-nMin
|
|
2440
|
-
j+=1
|
|
2441
|
-
|
|
2442
|
-
for i in range(i,dataLen) :
|
|
2443
|
-
if i-nMin<n :
|
|
2444
|
-
if data[i]<=data[nMin] :
|
|
2445
|
-
nMin=i
|
|
2446
|
-
else :
|
|
2447
|
-
nMin=i-n+1
|
|
2448
|
-
for j in range(nMin, i+1): # 计算区间最小值
|
|
2449
|
-
if data[j]<=data[nMin] :
|
|
2450
|
-
nMin=j
|
|
2451
|
-
|
|
2452
|
-
result[i]=i-nMin
|
|
2453
|
-
|
|
2454
|
-
return result
|
|
2455
|
-
|
|
2456
|
-
|
|
2457
|
-
# β(Beta)系数
|
|
2458
|
-
# BETA(N) 返回当前证券N周期收益与对应大盘指数收益相比的贝塔系数
|
|
2459
|
-
# 需要下载上证指数历史数据
|
|
2460
|
-
# 涨幅(X)=(现价-上一个交易日收盘价)/上一个交易日收盘价
|
|
2461
|
-
# 公式=股票和指数协方差/指数方差
|
|
2462
|
-
def BETA(self,n) :
|
|
2463
|
-
stockData=self.SymbolData.Data
|
|
2464
|
-
indexData=self.SymbolData.IndexData
|
|
2465
|
-
if n<=0 :
|
|
2466
|
-
n=1
|
|
2467
|
-
|
|
2468
|
-
dataLen=len(stockData.Data)
|
|
2469
|
-
stockProfit=JSAlgorithm.CreateArray(dataLen,0) # 股票涨幅
|
|
2470
|
-
indexProfit=JSAlgorithm.CreateArray(dataLen,0) # 指数涨幅
|
|
2471
|
-
for i in range(dataLen) :
|
|
2472
|
-
stockItem=stockData.Data[i]
|
|
2473
|
-
indexItem=indexData.Data[i]
|
|
2474
|
-
|
|
2475
|
-
if stockItem.Close>0 and stockItem.YClose>0 :
|
|
2476
|
-
stockProfit[i]=(stockItem.Close-stockItem.YClose)/stockItem.YClose
|
|
2477
|
-
if indexItem.Close>0 and indexItem.YClose>0 :
|
|
2478
|
-
indexProfit[i]=(indexItem.Close-indexItem.YClose)/indexItem.YClose
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
# 计算均值数组
|
|
2482
|
-
averageStockProfit=JSAlgorithm.ArrayAverage(stockProfit,n)
|
|
2483
|
-
averageIndexProfit=JSAlgorithm.ArrayAverage(indexProfit,n)
|
|
2484
|
-
|
|
2485
|
-
result=JSAlgorithm.CreateArray(dataLen)
|
|
2486
|
-
|
|
2487
|
-
for i in range(dataLen) :
|
|
2488
|
-
if i>=len(stockProfit) or i>=len(indexProfit) or i>=len(averageStockProfit) or i>=len(averageIndexProfit) :
|
|
2489
|
-
continue
|
|
2490
|
-
|
|
2491
|
-
averageStock=averageStockProfit[i]
|
|
2492
|
-
averageIndex=averageIndexProfit[i]
|
|
2493
|
-
|
|
2494
|
-
covariance=0 # 协方差
|
|
2495
|
-
variance=0 # 方差
|
|
2496
|
-
for j in range(i-n+1, i+1) :
|
|
2497
|
-
value=(indexProfit[j]-averageIndex)
|
|
2498
|
-
value2=(stockProfit[j]-averageStock)
|
|
2499
|
-
covariance+=value*value2
|
|
2500
|
-
variance+=value*value
|
|
2501
|
-
|
|
2502
|
-
if JSAlgorithm.IsDivideNumber(variance) and JSAlgorithm.IsNumber(covariance) :
|
|
2503
|
-
result[i]=covariance/variance # (covariance/n)/(variance/n)=covariance/variance;
|
|
2504
|
-
|
|
2505
|
-
return result
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
# 用法:BETA2(X,Y,N)为X与Y的N周期相关放大系数,表示Y变化1%,则X将变化N%
|
|
2509
|
-
# 例如:BETA2(CLOSE,INDEXC,10)表示收盘价与大盘指数之间的10周期相关放大率
|
|
2510
|
-
def BETA2(self,x,y,n) :
|
|
2511
|
-
if not JSAlgorithm.IsVaildArray(x) or not JSAlgorithm.IsVaildArray(y) :
|
|
2512
|
-
return []
|
|
2513
|
-
|
|
2514
|
-
xLen, yLen = len(x), len(y)
|
|
2515
|
-
if n<=0 :
|
|
2516
|
-
n=1
|
|
2517
|
-
|
|
2518
|
-
xProfit=JSAlgorithm.CreateArray(xLen,0) # x数据的涨幅
|
|
2519
|
-
yProfit=JSAlgorithm.CreateArray(yLen,0) # y数据的涨幅
|
|
2520
|
-
|
|
2521
|
-
count=max(xLen,yLen)
|
|
2522
|
-
|
|
2523
|
-
lastX, lastY = x[0], y[0]
|
|
2524
|
-
for i in range(count) :
|
|
2525
|
-
xItem=x[i]
|
|
2526
|
-
yItem=y[i]
|
|
2527
|
-
|
|
2528
|
-
if lastX>0 :
|
|
2529
|
-
xProfit[i]=(xItem-lastX)/lastX
|
|
2530
|
-
if lastY>0 :
|
|
2531
|
-
yProfit[i]=(yItem-lastY)/lastY
|
|
2532
|
-
|
|
2533
|
-
lastX=xItem
|
|
2534
|
-
lastY=yItem
|
|
2535
|
-
|
|
2536
|
-
# 计算均值数组
|
|
2537
|
-
averageXProfit=JSAlgorithm.ArrayAverage(xProfit,n)
|
|
2538
|
-
averageYProfit=JSAlgorithm.ArrayAverage(yProfit,n)
|
|
2539
|
-
|
|
2540
|
-
result=JSComplierHelper.CreateArray(count)
|
|
2541
|
-
|
|
2542
|
-
for i in range(count) :
|
|
2543
|
-
if i>=len(xProfit) or i>=len(yProfit) or i>=len(averageXProfit) or i>=len(averageYProfit) :
|
|
2544
|
-
continue
|
|
2545
|
-
|
|
2546
|
-
averageX=averageXProfit[i]
|
|
2547
|
-
averageY=averageYProfit[i]
|
|
2548
|
-
|
|
2549
|
-
covariance=0 # 协方差
|
|
2550
|
-
variance=0 # 方差
|
|
2551
|
-
for j in range(i-n+1, i+1) :
|
|
2552
|
-
value=(xProfit[j]-averageX)
|
|
2553
|
-
value2=(yProfit[j]-averageY)
|
|
2554
|
-
covariance+=value*value2
|
|
2555
|
-
variance+=value*value
|
|
2556
|
-
|
|
2557
|
-
if JSAlgorithm.IsDivideNumber(variance) and JSAlgorithm.IsNumber(covariance) :
|
|
2558
|
-
result[i]=covariance/variance # (covariance/n)/(variance/n)=covariance/variance;
|
|
2559
|
-
|
|
2560
|
-
return result
|
|
2561
|
-
|
|
2562
|
-
# 一直存在.
|
|
2563
|
-
# 例如: EVERY(CLOSE>OPEN,N)
|
|
2564
|
-
# 表示N日内一直阳线(N应大于0,小于总周期数,N支持变量)
|
|
2565
|
-
def EVERY(self,data,n):
|
|
2566
|
-
if n<1 or not JSAlgorithm.IsVaildArray(data) :
|
|
2567
|
-
return []
|
|
2568
|
-
|
|
2569
|
-
dataLen=len(data)
|
|
2570
|
-
result=JSComplierHelper.CreateArray(dataLen)
|
|
2571
|
-
for i in range(dataLen) :
|
|
2572
|
-
if JSAlgorithm.IsNumber(data[i]) :
|
|
2573
|
-
break
|
|
2574
|
-
|
|
2575
|
-
flag=0
|
|
2576
|
-
for i in range(i,dataLen) :
|
|
2577
|
-
if data[i]:
|
|
2578
|
-
flag+=1
|
|
2579
|
-
else :
|
|
2580
|
-
flag=0
|
|
2581
|
-
|
|
2582
|
-
if flag==n :
|
|
2583
|
-
result[i]=1
|
|
2584
|
-
flag-=1
|
|
2585
|
-
else :
|
|
2586
|
-
result[i]=0
|
|
2587
|
-
|
|
2588
|
-
return result
|
|
2589
|
-
|
|
2590
|
-
|
|
2591
|
-
# 抛物转向.
|
|
2592
|
-
# 用法: SAR(N,S,M),N为计算周期,S为步长,M为极值
|
|
2593
|
-
# 例如: SAR(10,2,20)表示计算10日抛物转向,步长为2%,极限值为20%
|
|
2594
|
-
def SAR(self,n,step,exValue) :
|
|
2595
|
-
stockData= self.SymbolData.Data
|
|
2596
|
-
dataLen=len(stockData.Data)
|
|
2597
|
-
if n>=dataLen :
|
|
2598
|
-
return []
|
|
2599
|
-
|
|
2600
|
-
result=JSComplierHelper.CreateArray(dataLen)
|
|
2601
|
-
high, low =None, None
|
|
2602
|
-
for i in range(n) :
|
|
2603
|
-
item=stockData.Data[i]
|
|
2604
|
-
if high==None:
|
|
2605
|
-
high=item.High
|
|
2606
|
-
elif high<item.High :
|
|
2607
|
-
high=item.High
|
|
2608
|
-
|
|
2609
|
-
if low==None :
|
|
2610
|
-
low=item.Low
|
|
2611
|
-
elif low>item.Low :
|
|
2612
|
-
low=item.Low
|
|
2613
|
-
|
|
2614
|
-
SAR_LONG=0
|
|
2615
|
-
SAR_SHORT=1
|
|
2616
|
-
position=SAR_LONG
|
|
2617
|
-
result[n-1]=low
|
|
2618
|
-
nextSar=low
|
|
2619
|
-
sip=stockData.Data[0].High
|
|
2620
|
-
af=step/100
|
|
2621
|
-
for i in range(n,dataLen) :
|
|
2622
|
-
ysip=sip
|
|
2623
|
-
item=stockData.Data[i]
|
|
2624
|
-
yitem=stockData.Data[i-1]
|
|
2625
|
-
|
|
2626
|
-
if (position==SAR_LONG) :
|
|
2627
|
-
if (item.Low<result[i-1]) :
|
|
2628
|
-
position=SAR_SHORT
|
|
2629
|
-
sip=item.Low
|
|
2630
|
-
af=step/100
|
|
2631
|
-
nextSar =max(item.High,yitem.High)
|
|
2632
|
-
nextSar =max(nextSar,ysip+af*(sip-ysip))
|
|
2633
|
-
else :
|
|
2634
|
-
position = SAR_LONG
|
|
2635
|
-
if (item.High>ysip) :
|
|
2636
|
-
sip=item.High
|
|
2637
|
-
af=min(af+step/100,exValue/100)
|
|
2638
|
-
nextSar=min(item.Low,yitem.Low)
|
|
2639
|
-
nextSar=min(nextSar,result[i-1]+af*(sip-result[i-1]))
|
|
2640
|
-
elif (position==SAR_SHORT) :
|
|
2641
|
-
if (item.High>result[i-1]) :
|
|
2642
|
-
position=SAR_LONG
|
|
2643
|
-
sip=item.High
|
|
2644
|
-
af=step/100
|
|
2645
|
-
nextSar =min(item.Low,yitem.Low)
|
|
2646
|
-
nextSar =min(nextSar,result[i-1]+af*(sip-ysip))
|
|
2647
|
-
else :
|
|
2648
|
-
position = SAR_SHORT
|
|
2649
|
-
if(item.Low<ysip) :
|
|
2650
|
-
sip=item.Low
|
|
2651
|
-
af=min(af+step/100,exValue/100)
|
|
2652
|
-
nextSar=max(item.High,yitem.High)
|
|
2653
|
-
nextSar=max(nextSar,result[i-1]+af*(sip-result[i-1]))
|
|
2654
|
-
|
|
2655
|
-
result[i]=nextSar
|
|
2656
|
-
|
|
2657
|
-
return result
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
# 抛物转向点.
|
|
2661
|
-
# 用法: SARTURN(N,S,M),N为计算周期,S为步长,M为极值,若发生向上转向则返回1,若发生向下转向则返回-1,否则为0
|
|
2662
|
-
# 其用法与SAR函数相同
|
|
2663
|
-
def SARTURN(self,n,step,exValue) :
|
|
2664
|
-
sar=self.SAR(n,step,exValue)
|
|
2665
|
-
stockData= self.SymbolData.Data
|
|
2666
|
-
dataLen=len(stockData)
|
|
2667
|
-
result=JSAlgorithm.CreateArray(dataLen)
|
|
2668
|
-
|
|
2669
|
-
for index in range(len(sar)) :
|
|
2670
|
-
if JSAlgorithm.IsNumber(sar[index]) :
|
|
2671
|
-
break
|
|
2672
|
-
|
|
2673
|
-
flag=0
|
|
2674
|
-
if index<dataLen :
|
|
2675
|
-
flag=stockData.Data[index].Close>sar[index]
|
|
2676
|
-
|
|
2677
|
-
for i in range(index+1,dataLen) :
|
|
2678
|
-
item=stockData.Data[i]
|
|
2679
|
-
if item.Close<sar[i] and flag :
|
|
2680
|
-
result[i]=-1
|
|
2681
|
-
else :
|
|
2682
|
-
result[i]= 1 if (item.Close>sar[i] and not flag) else 0
|
|
2683
|
-
|
|
2684
|
-
flag=item.Close>sar[i]
|
|
2685
|
-
|
|
2686
|
-
return result
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
# 属于未来函数,将当前位置到若干周期前的数据设为1.
|
|
2690
|
-
# 用法: BACKSET(X,N),若X非0,则将当前位置到N周期前的数值设为1.
|
|
2691
|
-
# 例如: BACKSET(CLOSE>OPEN,2)若收阳则将该周期及前一周期数值设为1,否则为0
|
|
2692
|
-
def BACKSET(self,condition,n) :
|
|
2693
|
-
if not condition :
|
|
2694
|
-
return []
|
|
2695
|
-
dataCount=len(condition)
|
|
2696
|
-
if dataCount<=0 :
|
|
2697
|
-
return []
|
|
2698
|
-
|
|
2699
|
-
result=JSAlgorithm.CreateArray(dataCount,0) # 初始化0
|
|
2700
|
-
|
|
2701
|
-
for pos in range(dataCount) :
|
|
2702
|
-
if JSAlgorithm.IsNumber(condition[pos]) :
|
|
2703
|
-
break
|
|
2704
|
-
|
|
2705
|
-
if pos==dataCount :
|
|
2706
|
-
return result
|
|
2707
|
-
|
|
2708
|
-
num=min(dataCount-pos,max(n,1))
|
|
2709
|
-
for i in range(dataCount-1, -1,-1) :
|
|
2710
|
-
value=condition[i]
|
|
2711
|
-
if JSAlgorithm.IsNumber(value) and value :
|
|
2712
|
-
for j in range(i, i-num,-1) :
|
|
2713
|
-
result[j]=1
|
|
2714
|
-
|
|
2715
|
-
if condition[i] :
|
|
2716
|
-
for j in range(i, pos+1) :
|
|
2717
|
-
result[j]=1
|
|
2718
|
-
|
|
2719
|
-
return result
|
|
2720
|
-
|
|
2721
|
-
|
|
2722
|
-
# 计算截至到某一天的历史所有筹码
|
|
2723
|
-
def CalculateChip(self,index,exchangeData,hisData,dRate) :
|
|
2724
|
-
result=Variant()
|
|
2725
|
-
result.Min, result.Max, result.Data = None, None, []
|
|
2726
|
-
seed=1 # 筹码历史衰减换手系数
|
|
2727
|
-
max, min= None, None
|
|
2728
|
-
result.Data=JSComplierHelper.CreateArray(index+1)
|
|
2729
|
-
for i in range(index, -1,-1) :
|
|
2730
|
-
item=Variant() # Vol:量 High:最高 Low:最低
|
|
2731
|
-
kData=hisData[i]
|
|
2732
|
-
if i==index :
|
|
2733
|
-
item.Vol=kData.Vol*exchangeData[i]
|
|
2734
|
-
else :
|
|
2735
|
-
item.Vol=kData.Vol*seed
|
|
2736
|
-
|
|
2737
|
-
item.Date=kData.Date
|
|
2738
|
-
item.High=kData.High
|
|
2739
|
-
item.Low=kData.Low
|
|
2740
|
-
|
|
2741
|
-
if max==None :
|
|
2742
|
-
max=item.High
|
|
2743
|
-
elif max<item.High :
|
|
2744
|
-
max=item.High
|
|
2745
|
-
if min==None :
|
|
2746
|
-
min=item.Low
|
|
2747
|
-
elif min<item.Low :
|
|
2748
|
-
min=item.Low
|
|
2749
|
-
|
|
2750
|
-
result.Data[i]=item
|
|
2751
|
-
|
|
2752
|
-
seed*=(1-(exchangeData[i]/100)*dRate) # 换手率累乘
|
|
2753
|
-
|
|
2754
|
-
result.Max=max
|
|
2755
|
-
result.Min=min
|
|
2756
|
-
return result
|
|
2757
|
-
|
|
2758
|
-
# 获利盘比例.
|
|
2759
|
-
# 用法: WINNER(CLOSE),表示以当前收市价卖出的获利盘比例,例如返回0.1表示10%获利盘;WINNER(10.5)表示10.5元价格的获利盘比例
|
|
2760
|
-
# 该函数仅对日线分析周期有效
|
|
2761
|
-
def WINNER(self,data,node) :
|
|
2762
|
-
kData=self.SymbolData.Data
|
|
2763
|
-
if (not kData or kData.GetCount()<=0) :
|
|
2764
|
-
return []
|
|
2765
|
-
dataLen=kData.GetCount()
|
|
2766
|
-
aryCapital=self.SymbolData.GetFinanceCacheData(7,node) # 流通股本
|
|
2767
|
-
result=JSAlgorithm.CreateArray(dataLen)
|
|
2768
|
-
|
|
2769
|
-
priceRange=kData.GetMaxMin()
|
|
2770
|
-
dMaxPrice, dMinPrice = priceRange["Max"], priceRange["Min"]
|
|
2771
|
-
if (dMinPrice > 1000 or dMinPrice < 0 or dMaxPrice>1000 or dMinPrice < 0) :
|
|
2772
|
-
self.ThrowUnexpectedNode(node,'WINNER() 历史K线最大最小值错误, 超出(0,1000)范围')
|
|
2773
|
-
|
|
2774
|
-
lMaxPrice=int(dMaxPrice*100 + 1)
|
|
2775
|
-
lMinPrice=int(dMinPrice*100 - 1)
|
|
2776
|
-
lLow, lHigh, lClose = 0, 0, 0
|
|
2777
|
-
dMaxPrice = lMaxPrice / 100.0
|
|
2778
|
-
dMinPrice = lMinPrice / 100.0
|
|
2779
|
-
lSpeed = lMaxPrice - lMinPrice + 1
|
|
2780
|
-
if (lSpeed < 1) :
|
|
2781
|
-
return result
|
|
2782
|
-
|
|
2783
|
-
aryVolPrice=JSAlgorithm.CreateArray(lSpeed,0)
|
|
2784
|
-
aryPerVol=JSAlgorithm.CreateArray(lSpeed,0)
|
|
2785
|
-
|
|
2786
|
-
dHSL, dTotalVol, dVol = 0, 0, 0
|
|
2787
|
-
for i in range(dataLen) :
|
|
2788
|
-
if (i >= len(aryCapital)) :
|
|
2789
|
-
continue
|
|
2790
|
-
if (aryCapital[i]<1):
|
|
2791
|
-
continue
|
|
2792
|
-
|
|
2793
|
-
kItem=kData.GetItem(i)
|
|
2794
|
-
dHSL = kItem.Vol/aryCapital[i]
|
|
2795
|
-
|
|
2796
|
-
for j in range(lSpeed) :
|
|
2797
|
-
aryVolPrice[j]*=(1-dHSL)
|
|
2798
|
-
|
|
2799
|
-
lLow=int(min(lMaxPrice,max(lMinPrice,kItem.Low *100)))-lMinPrice
|
|
2800
|
-
lHigh=int(min(lMaxPrice,max(lMinPrice,kItem.High*100)))-lMinPrice
|
|
2801
|
-
lClose=int(min(lMaxPrice,max(lMinPrice,kItem.Close*100)))-lMinPrice
|
|
2802
|
-
|
|
2803
|
-
for j in range(lSpeed) :
|
|
2804
|
-
aryPerVol[j]=0
|
|
2805
|
-
|
|
2806
|
-
lHalf =int((lLow + lHigh + 2 * lClose) / 4)
|
|
2807
|
-
if (lHalf == lHigh or lHalf == lLow) :
|
|
2808
|
-
aryPerVol[lHalf] += kItem.Vol
|
|
2809
|
-
else :
|
|
2810
|
-
dVH = kItem.Vol / (lHalf - lLow)
|
|
2811
|
-
for k in range(lLow,lHalf) :
|
|
2812
|
-
aryPerVol[k] += (k - lLow)*(dVH / (lHalf - lLow))
|
|
2813
|
-
for k in range(lHalf,lHigh+1) :
|
|
2814
|
-
aryPerVol[k] += (k - lHigh)*(dVH / (lHalf - lHigh))
|
|
2815
|
-
|
|
2816
|
-
dTotalVol = 0
|
|
2817
|
-
for j in range(lLow,lHigh+1) :
|
|
2818
|
-
aryVolPrice[j] += aryPerVol[j]
|
|
2819
|
-
|
|
2820
|
-
for j in range(lSpeed) :
|
|
2821
|
-
dTotalVol += aryVolPrice[j]
|
|
2822
|
-
|
|
2823
|
-
if isinstance(data,list):
|
|
2824
|
-
lHigh = int(min((data[i] * 100) - lMinPrice, lSpeed - 1))
|
|
2825
|
-
else :
|
|
2826
|
-
lHigh = int(min((data * 100) - lMinPrice, lSpeed - 1))
|
|
2827
|
-
|
|
2828
|
-
dVol=0
|
|
2829
|
-
for j in range(lHigh+1) :
|
|
2830
|
-
dVol += aryVolPrice[j]
|
|
2831
|
-
|
|
2832
|
-
if (dTotalVol > 0) :
|
|
2833
|
-
result[i]=dVol / dTotalVol
|
|
2834
|
-
elif (i - 1 >= 0) :
|
|
2835
|
-
result[i] = result[i - 1]
|
|
2836
|
-
|
|
2837
|
-
return result
|
|
2838
|
-
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
'''
|
|
2842
|
-
def WINNER(self,data,node) :
|
|
2843
|
-
exchangeID=201
|
|
2844
|
-
exchangeData=self.SymbolData.GetFinanceCacheData(exchangeID,node) # 换手率
|
|
2845
|
-
if not exchangeData :
|
|
2846
|
-
return []
|
|
2847
|
-
|
|
2848
|
-
isNumber=JSComplierHelper.IsNumber(data)
|
|
2849
|
-
singleData=None
|
|
2850
|
-
if isNumber :
|
|
2851
|
-
singleData=int(float(data)*100)
|
|
2852
|
-
compareData=None
|
|
2853
|
-
klineData=self.SymbolData.Data.Data
|
|
2854
|
-
klineLen=len(klineData)
|
|
2855
|
-
result=JSComplierHelper.CreateArray(klineLen)
|
|
2856
|
-
for i in range(klineLen-1, -1, -1) :
|
|
2857
|
-
chipData=self.CalculateChip(i,exchangeData,klineData,1)
|
|
2858
|
-
if ( chipData.Max==None or chipData.Min==None or chipData.Max<=0 or chipData.Min<=0) :
|
|
2859
|
-
continue
|
|
2860
|
-
|
|
2861
|
-
# max=int(chipData.Max*100)
|
|
2862
|
-
# min=int(chipData.Min*100)
|
|
2863
|
-
|
|
2864
|
-
if (singleData!=None) :
|
|
2865
|
-
compareData=singleData
|
|
2866
|
-
else :
|
|
2867
|
-
if i>=len(data) :
|
|
2868
|
-
continue
|
|
2869
|
-
compareData=int(data[i]*100)
|
|
2870
|
-
|
|
2871
|
-
totalVol, vol= 0,0
|
|
2872
|
-
for j in range(i, -1, -1) :
|
|
2873
|
-
item=chipData.Data[j]
|
|
2874
|
-
start=int(item.Low*100)
|
|
2875
|
-
end=int(item.High*100)
|
|
2876
|
-
if ((end-start+1)<=0):
|
|
2877
|
-
continue
|
|
2878
|
-
|
|
2879
|
-
iAverageVolume=item.Vol
|
|
2880
|
-
iAverageVolume=iAverageVolume/(end-start+1)
|
|
2881
|
-
if (iAverageVolume<=0):
|
|
2882
|
-
continue
|
|
2883
|
-
|
|
2884
|
-
profitVol=0 # 获利的成交量
|
|
2885
|
-
if (compareData>end) :
|
|
2886
|
-
profitVol=item.Vol
|
|
2887
|
-
elif (compareData<start) :
|
|
2888
|
-
profitVol=0
|
|
2889
|
-
else :
|
|
2890
|
-
profitVol=item.Vol*(compareData-start+1)/(end-start+1)
|
|
2891
|
-
|
|
2892
|
-
vol+=profitVol
|
|
2893
|
-
totalVol+=item.Vol
|
|
2894
|
-
|
|
2895
|
-
if (totalVol>0) :
|
|
2896
|
-
result[i]=vol/totalVol
|
|
2897
|
-
|
|
2898
|
-
return result
|
|
2899
|
-
'''
|
|
2900
|
-
|
|
2901
|
-
# 成本分布情况.
|
|
2902
|
-
# 用法: COST(10),表示10%获利盘的价格是多少,即有10%的持仓量在该价格以下,其余90%在该价格以上,为套牢盘
|
|
2903
|
-
# 该函数仅对日线分析周期有效
|
|
2904
|
-
def COST(self,data, node) :
|
|
2905
|
-
rate=data/100
|
|
2906
|
-
if (rate<0.000001 or rate>1) :
|
|
2907
|
-
return []
|
|
2908
|
-
|
|
2909
|
-
kData=self.SymbolData.Data
|
|
2910
|
-
if (not kData or kData.GetCount()<=0) :
|
|
2911
|
-
return []
|
|
2912
|
-
dataLen=kData.GetCount()
|
|
2913
|
-
aryCapital=self.SymbolData.GetFinanceCacheData(7,node) # 流通股本
|
|
2914
|
-
result=JSAlgorithm.CreateArray(dataLen)
|
|
2915
|
-
|
|
2916
|
-
priceRange=kData.GetMaxMin()
|
|
2917
|
-
dMaxPrice, dMinPrice = priceRange["Max"], priceRange["Min"]
|
|
2918
|
-
if (dMinPrice > 1000 or dMinPrice < 0 or dMaxPrice>1000 or dMinPrice < 0) :
|
|
2919
|
-
self.ThrowUnexpectedNode(node,'WINNER() 历史K线最大最小值错误, 超出(0,1000)范围')
|
|
2920
|
-
|
|
2921
|
-
lMaxPrice=int(dMaxPrice*100 + 1)
|
|
2922
|
-
lMinPrice=int(dMinPrice*100 - 1)
|
|
2923
|
-
lLow, lHigh, lClose = 0, 0, 0
|
|
2924
|
-
dMaxPrice = lMaxPrice / 100.0
|
|
2925
|
-
dMinPrice = lMinPrice / 100.0
|
|
2926
|
-
lSpeed = lMaxPrice - lMinPrice + 1
|
|
2927
|
-
if (lSpeed < 1) :
|
|
2928
|
-
return result
|
|
2929
|
-
|
|
2930
|
-
aryVolPrice=JSAlgorithm.CreateArray(lSpeed,0)
|
|
2931
|
-
aryPerVol=JSAlgorithm.CreateArray(lSpeed,0)
|
|
2932
|
-
|
|
2933
|
-
dHSL, dTotalVol, dVol, dCost = 0, 0, 0,0
|
|
2934
|
-
for i in range(dataLen) :
|
|
2935
|
-
if (i >= len(aryCapital)) :
|
|
2936
|
-
continue
|
|
2937
|
-
|
|
2938
|
-
if (aryCapital[i]>1):
|
|
2939
|
-
kItem=kData.GetItem(i)
|
|
2940
|
-
dHSL = kItem.Vol/aryCapital[i]
|
|
2941
|
-
|
|
2942
|
-
for j in range(lSpeed) :
|
|
2943
|
-
aryVolPrice[j]*=(1-dHSL)
|
|
2944
|
-
|
|
2945
|
-
lLow=int(min(lMaxPrice,max(lMinPrice,kItem.Low *100)))-lMinPrice
|
|
2946
|
-
lHigh=int(min(lMaxPrice,max(lMinPrice,kItem.High*100)))-lMinPrice
|
|
2947
|
-
lClose=int(min(lMaxPrice,max(lMinPrice,kItem.Close*100)))-lMinPrice
|
|
2948
|
-
|
|
2949
|
-
for j in range(lSpeed) :
|
|
2950
|
-
aryPerVol[j]=0
|
|
2951
|
-
|
|
2952
|
-
lHalf =int((lLow + lHigh + 2 * lClose) / 4)
|
|
2953
|
-
if (lHalf == lHigh or lHalf == lLow) :
|
|
2954
|
-
aryPerVol[lHalf] += kItem.Vol
|
|
2955
|
-
else :
|
|
2956
|
-
dVH = kItem.Vol / (lHalf - lLow)
|
|
2957
|
-
for k in range(lLow,lHalf) :
|
|
2958
|
-
aryPerVol[k] += (k - lLow)*(dVH / (lHalf - lLow))
|
|
2959
|
-
for k in range(lHalf,lHigh+1) :
|
|
2960
|
-
aryPerVol[k] += (k - lHigh)*(dVH / (lHalf - lHigh))
|
|
2961
|
-
|
|
2962
|
-
dTotalVol = 0
|
|
2963
|
-
for j in range(lLow,lHigh+1) :
|
|
2964
|
-
aryVolPrice[j] += aryPerVol[j]
|
|
2965
|
-
|
|
2966
|
-
for j in range(lSpeed) :
|
|
2967
|
-
dTotalVol += aryVolPrice[j]
|
|
2968
|
-
|
|
2969
|
-
dCost, dVol = 0,0
|
|
2970
|
-
for j in range(lSpeed) :
|
|
2971
|
-
dVol+=aryVolPrice[j]
|
|
2972
|
-
if (dVol>=dTotalVol*rate) :
|
|
2973
|
-
dCost=(dMaxPrice-dMinPrice)*j/lSpeed+dMinPrice
|
|
2974
|
-
break
|
|
2975
|
-
|
|
2976
|
-
result[i]=dCost
|
|
2977
|
-
|
|
2978
|
-
return result
|
|
2979
|
-
|
|
2980
|
-
|
|
2981
|
-
'''
|
|
2982
|
-
def COST(self,data, node) :
|
|
2983
|
-
exchangeID=201
|
|
2984
|
-
exchangeData=self.SymbolData.GetFinanceCacheData(exchangeID,node) # 换手率
|
|
2985
|
-
if not exchangeData :
|
|
2986
|
-
return []
|
|
2987
|
-
|
|
2988
|
-
isNumber=JSComplierHelper.IsNumber(data)
|
|
2989
|
-
singleData=None
|
|
2990
|
-
if (isNumber) :
|
|
2991
|
-
singleData=float(data)
|
|
2992
|
-
compareData=None
|
|
2993
|
-
klineData=self.SymbolData.Data.Data
|
|
2994
|
-
klineLen=len(self.SymbolData.Data.Data)
|
|
2995
|
-
result=JSComplierHelper.CreateArray(klineLen)
|
|
2996
|
-
for i in range(klineLen-1,-1,-1) :
|
|
2997
|
-
chipData=self.CalculateChip(i,exchangeData,klineData,1)
|
|
2998
|
-
if (chipData.Max==None or chipData.Min==None or chipData.Max<=0 or chipData.Min<=0) :
|
|
2999
|
-
continue
|
|
3000
|
-
|
|
3001
|
-
max=int(chipData.Max*100)
|
|
3002
|
-
# min=int(chipData.Min*100)
|
|
3003
|
-
|
|
3004
|
-
if (singleData!=None) :
|
|
3005
|
-
compareData=singleData
|
|
3006
|
-
else :
|
|
3007
|
-
if (i>=data.length) :
|
|
3008
|
-
continue
|
|
3009
|
-
compareData=data[i]
|
|
3010
|
-
|
|
3011
|
-
totalVol,vol= 0,0
|
|
3012
|
-
aryMap={}
|
|
3013
|
-
for j in range(i,-1,-1) :
|
|
3014
|
-
item=chipData.Data[j]
|
|
3015
|
-
start=int(item.Low*100)
|
|
3016
|
-
end=int(item.High*100)
|
|
3017
|
-
if ((end-start+1)<=0) :
|
|
3018
|
-
continue
|
|
3019
|
-
|
|
3020
|
-
iAverageVolume=item.Vol
|
|
3021
|
-
iAverageVolume=iAverageVolume/(end-start+1)
|
|
3022
|
-
if iAverageVolume<=0 :
|
|
3023
|
-
continue
|
|
3024
|
-
|
|
3025
|
-
k=start # 起始价格
|
|
3026
|
-
while k<end and k<=max :
|
|
3027
|
-
if k in aryMap :
|
|
3028
|
-
vol=aryMap[k]
|
|
3029
|
-
aryMap[k]=vol+iAverageVolume
|
|
3030
|
-
else :
|
|
3031
|
-
aryMap[k]=iAverageVolume
|
|
3032
|
-
k+=1
|
|
3033
|
-
|
|
3034
|
-
totalVol+=item.Vol
|
|
3035
|
-
|
|
3036
|
-
# 计算获利盘
|
|
3037
|
-
vol=0
|
|
3038
|
-
for key, value in aryMap.items() :
|
|
3039
|
-
vol+=value
|
|
3040
|
-
result[i]=key/100
|
|
3041
|
-
if (vol/totalVol*100>compareData) :
|
|
3042
|
-
break
|
|
3043
|
-
|
|
3044
|
-
return result
|
|
3045
|
-
'''
|
|
3046
|
-
|
|
3047
|
-
# 远期成本分布比例.
|
|
3048
|
-
# 用法: PPART(10),表示10前的成本占总成本的比例,0.2表示20%
|
|
3049
|
-
def PPART(self, n, node) :
|
|
3050
|
-
startDay=int(n)
|
|
3051
|
-
if (startDay<0):
|
|
3052
|
-
return []
|
|
3053
|
-
|
|
3054
|
-
kData=self.SymbolData.Data
|
|
3055
|
-
if (not kData or kData.GetCount()<=0) :
|
|
3056
|
-
return []
|
|
3057
|
-
|
|
3058
|
-
dataLen=kData.GetCount()
|
|
3059
|
-
aryCapital=self.SymbolData.GetFinanceCacheData(7,node) # 流通股本
|
|
3060
|
-
result=JSAlgorithm.CreateArray(dataLen)
|
|
3061
|
-
|
|
3062
|
-
for i in range(startDay, dataLen) :
|
|
3063
|
-
start = i - startDay
|
|
3064
|
-
if (start < 0) :
|
|
3065
|
-
continue
|
|
3066
|
-
|
|
3067
|
-
#前n日成交量和
|
|
3068
|
-
partVol = 0
|
|
3069
|
-
for j in range(startDay) :
|
|
3070
|
-
kItem=kData.GetItem(j + start)
|
|
3071
|
-
partVol += kItem.Vol
|
|
3072
|
-
|
|
3073
|
-
if i < len(aryCapital) :
|
|
3074
|
-
if (aryCapital[i]>0) :
|
|
3075
|
-
value=1 - (partVol / aryCapital[i])
|
|
3076
|
-
result[i]=value
|
|
3077
|
-
|
|
3078
|
-
return result
|
|
3079
|
-
|
|
3080
|
-
# 区间成本.
|
|
3081
|
-
# 用法: 例如COSTEX(CLOSE,REF(CLOSE,1)),表示近两日收盘价格间筹码的成本
|
|
3082
|
-
# 该函数仅对日线分析周期有效
|
|
3083
|
-
def COSTEX(self,data, data2, node):
|
|
3084
|
-
kData=self.SymbolData.Data
|
|
3085
|
-
if (not kData or kData.GetCount()<=0) :
|
|
3086
|
-
return []
|
|
3087
|
-
dataLen=kData.GetCount()
|
|
3088
|
-
aryCapital=self.SymbolData.GetFinanceCacheData(7,node) # 流通股本
|
|
3089
|
-
result=JSAlgorithm.CreateArray(dataLen)
|
|
3090
|
-
|
|
3091
|
-
priceRange=kData.GetMaxMin()
|
|
3092
|
-
dMaxPrice, dMinPrice = priceRange["Max"], priceRange["Min"]
|
|
3093
|
-
if (dMinPrice > 1000 or dMinPrice < 0 or dMaxPrice>1000 or dMinPrice < 0) :
|
|
3094
|
-
self.ThrowUnexpectedNode(node,'COSTEX() 历史K线最大最小值错误, 超出(0,1000)范围')
|
|
3095
|
-
|
|
3096
|
-
lMaxPrice=int(dMaxPrice*100 + 1)
|
|
3097
|
-
lMinPrice=int(dMinPrice*100 - 1)
|
|
3098
|
-
lLow, lHigh, lClose = 0, 0, 0
|
|
3099
|
-
dMaxPrice = lMaxPrice / 100.0
|
|
3100
|
-
dMinPrice = lMinPrice / 100.0
|
|
3101
|
-
lSpeed = lMaxPrice - lMinPrice + 1
|
|
3102
|
-
if (lSpeed < 1) :
|
|
3103
|
-
return result
|
|
3104
|
-
|
|
3105
|
-
aryVolPrice=JSAlgorithm.CreateArray(lSpeed,0)
|
|
3106
|
-
aryPerVol=JSAlgorithm.CreateArray(lSpeed,0)
|
|
3107
|
-
|
|
3108
|
-
dHSL, dTotalVol, dVol, dVola, dPerVola, dVolb, dPerVolb = 0, 0, 0, 0, 0, 0, 0
|
|
3109
|
-
for i in range(dataLen) :
|
|
3110
|
-
if (i >= len(aryCapital)) :
|
|
3111
|
-
continue
|
|
3112
|
-
|
|
3113
|
-
if (aryCapital[i]>1):
|
|
3114
|
-
kItem=kData.GetItem(i)
|
|
3115
|
-
dHSL = kItem.Vol/aryCapital[i]
|
|
3116
|
-
|
|
3117
|
-
for j in range(lSpeed) :
|
|
3118
|
-
aryVolPrice[j]*=(1-dHSL)
|
|
3119
|
-
|
|
3120
|
-
lLow=int(min(lMaxPrice,max(lMinPrice,kItem.Low *100)))-lMinPrice
|
|
3121
|
-
lHigh=int(min(lMaxPrice,max(lMinPrice,kItem.High*100)))-lMinPrice
|
|
3122
|
-
lClose=int(min(lMaxPrice,max(lMinPrice,kItem.Close*100)))-lMinPrice
|
|
3123
|
-
|
|
3124
|
-
for j in range(lSpeed) :
|
|
3125
|
-
aryPerVol[j]=0
|
|
3126
|
-
|
|
3127
|
-
lHalf =int((lLow + lHigh + 2 * lClose) / 4)
|
|
3128
|
-
if (lHalf == lHigh or lHalf == lLow) :
|
|
3129
|
-
aryPerVol[lHalf] += kItem.Vol
|
|
3130
|
-
else :
|
|
3131
|
-
dVH = kItem.Vol / (lHalf - lLow)
|
|
3132
|
-
for k in range(lLow,lHalf) :
|
|
3133
|
-
aryPerVol[k] += (k - lLow)*(dVH / (lHalf - lLow))
|
|
3134
|
-
for k in range(lHalf,lHigh+1) :
|
|
3135
|
-
aryPerVol[k] += (k - lHigh)*(dVH / (lHalf - lHigh))
|
|
3136
|
-
|
|
3137
|
-
dTotalVol = 0
|
|
3138
|
-
for j in range(lLow,lHigh+1) :
|
|
3139
|
-
aryVolPrice[j] += aryPerVol[j]
|
|
3140
|
-
|
|
3141
|
-
for j in range(lSpeed) :
|
|
3142
|
-
dTotalVol += aryVolPrice[j]
|
|
3143
|
-
|
|
3144
|
-
if isinstance(data,list):
|
|
3145
|
-
if (data[i]==None) :
|
|
3146
|
-
continue
|
|
3147
|
-
lHigh = int(min((data[i] * 100) - lMinPrice, lSpeed - 1))
|
|
3148
|
-
else :
|
|
3149
|
-
lHigh = int(min((data * 100) - lMinPrice, lSpeed - 1))
|
|
3150
|
-
|
|
3151
|
-
dVola, dPerVola = 0,0
|
|
3152
|
-
for j in range(lHigh+1):
|
|
3153
|
-
dVola += aryVolPrice[j]
|
|
3154
|
-
dPerVola += (0.01*(j + lMinPrice))*aryVolPrice[j]
|
|
3155
|
-
|
|
3156
|
-
if isinstance(data2,list) :
|
|
3157
|
-
if (data2[i]==None):
|
|
3158
|
-
continue
|
|
3159
|
-
lHigh = int(min((data2[i] * 100) - lMinPrice, lSpeed - 1))
|
|
3160
|
-
else :
|
|
3161
|
-
lHigh = int(min((data2 * 100) - lMinPrice, lSpeed - 1))
|
|
3162
|
-
|
|
3163
|
-
dVolb, dPerVolb = 0, 0
|
|
3164
|
-
for j in range(lHigh+1) :
|
|
3165
|
-
dVolb += aryVolPrice[j]
|
|
3166
|
-
dPerVolb += (0.01*(j + lMinPrice))*aryVolPrice[j]
|
|
3167
|
-
|
|
3168
|
-
dVol = dVola - dVolb
|
|
3169
|
-
dPerVolRange = dPerVola - dPerVolb
|
|
3170
|
-
if abs(dPerVolRange)>0.001 and dVol!=0 :
|
|
3171
|
-
result[i]=dPerVolRange / dVol
|
|
3172
|
-
elif (i-1>=0) :
|
|
3173
|
-
result[i] = result[i - 1]
|
|
3174
|
-
|
|
3175
|
-
return result
|
|
3176
|
-
|
|
3177
|
-
# 近期获利盘比例.
|
|
3178
|
-
# 用法: LWINNER(5,CLOSE),表示最近5天的那部分成本以当前收市价卖出的获利盘比例
|
|
3179
|
-
# 例如: 返回0.1表示10%获利盘
|
|
3180
|
-
def LWINNER(self, n, data, node) :
|
|
3181
|
-
return []
|
|
3182
|
-
|
|
3183
|
-
def PWINNER(self, n, data, node) :
|
|
3184
|
-
return []
|
|
3185
|
-
|
|
3186
|
-
# 属于未来函数,之字转向.
|
|
3187
|
-
# 用法: ZIG(K,N),当价格变化量超过N%时转向,K表示0:开盘价,1:最高价,2:最低价,3:收盘价,其余:数组信息
|
|
3188
|
-
# 例如: ZIG(3,5)表示收盘价的5%的ZIG转向
|
|
3189
|
-
def ZIG(self,data,n) :
|
|
3190
|
-
hisData=self.SymbolData.Data
|
|
3191
|
-
if JSComplierHelper.IsNumber(data):
|
|
3192
|
-
if data==0 :
|
|
3193
|
-
data=hisData.GetOpen()
|
|
3194
|
-
elif data==1 :
|
|
3195
|
-
data=hisData.GetHigh()
|
|
3196
|
-
elif data==2 :
|
|
3197
|
-
data=hisData.GetLow()
|
|
3198
|
-
elif data==3:
|
|
3199
|
-
data=hisData.GetClose()
|
|
3200
|
-
else :
|
|
3201
|
-
return []
|
|
3202
|
-
|
|
3203
|
-
return self.ZIG_Calculate(data,n)
|
|
3204
|
-
|
|
3205
|
-
# 获取第1个有效数据索引
|
|
3206
|
-
def GetFirstVaildIndex(self, data):
|
|
3207
|
-
count=len(data)
|
|
3208
|
-
for i in range(count):
|
|
3209
|
-
if (JSComplierHelper.IsNumber(data[i])):
|
|
3210
|
-
return i
|
|
3211
|
-
|
|
3212
|
-
return count
|
|
3213
|
-
|
|
3214
|
-
def ZIG_Calculate(self, data,dRate):
|
|
3215
|
-
nDataCount=len(data)
|
|
3216
|
-
dest=JSAlgorithm.CreateArray(nDataCount)
|
|
3217
|
-
m=self.GetFirstVaildIndex(data)
|
|
3218
|
-
i, lLastPos, lState, j = 0, 0, 0, 0
|
|
3219
|
-
dif = 0
|
|
3220
|
-
lLastPos, lState = m, m
|
|
3221
|
-
for i in range(m+1, nDataCount-1) :
|
|
3222
|
-
if (lState==m):
|
|
3223
|
-
break
|
|
3224
|
-
if abs(data[i] - data[m]) * 100 >= dRate*data[m]:
|
|
3225
|
-
if (data[i]>data[m]) :
|
|
3226
|
-
lState=i
|
|
3227
|
-
else :
|
|
3228
|
-
lState=-1
|
|
3229
|
-
else :
|
|
3230
|
-
lState=m
|
|
3231
|
-
|
|
3232
|
-
for i in range(i, nDataCount-1) :
|
|
3233
|
-
if (data[i] >= data[i - 1] and data[i] >= data[i + 1]) :
|
|
3234
|
-
if (lState<0) :
|
|
3235
|
-
if ((data[i] - data[-lState]) * 100<dRate*data[-lState]) :
|
|
3236
|
-
continue
|
|
3237
|
-
else :
|
|
3238
|
-
j = -lState
|
|
3239
|
-
dif = (data[lLastPos] - data[j]) / (-lState - lLastPos)
|
|
3240
|
-
dest[j]=data[-lState]
|
|
3241
|
-
j-=1
|
|
3242
|
-
for j in range(j,lLastPos-1,-1): # for (; j >= lLastPos; j--)
|
|
3243
|
-
dest[j]=data[-lState] + (-lState - j)*dif
|
|
3244
|
-
lLastPos = -lState
|
|
3245
|
-
lState = i
|
|
3246
|
-
|
|
3247
|
-
elif (data[i]>data[lState]):
|
|
3248
|
-
lState = i
|
|
3249
|
-
elif (data[i] <= data[i - 1] and data[i] <= data[i + 1]) :
|
|
3250
|
-
if (lState>0) :
|
|
3251
|
-
if ((data[lState] - data[i]) * 100<dRate*data[lState]):
|
|
3252
|
-
continue
|
|
3253
|
-
else :
|
|
3254
|
-
j = lLastPos
|
|
3255
|
-
dif = (data[lState] - data[j]) / (lState - lLastPos)
|
|
3256
|
-
dest[j]=data[lLastPos]
|
|
3257
|
-
j+=1
|
|
3258
|
-
for j in range(j,lState+1) :
|
|
3259
|
-
dest[j]=data[lLastPos] + (j - lLastPos)*dif
|
|
3260
|
-
lLastPos = lState
|
|
3261
|
-
lState = -i
|
|
3262
|
-
elif (data[i]<data[-lState]) :
|
|
3263
|
-
lState = -i
|
|
3264
|
-
|
|
3265
|
-
if (abs(lState) >= nDataCount - 2) :
|
|
3266
|
-
if (lState>0 and data[nDataCount - 1] >= data[lState]) :
|
|
3267
|
-
lState = nDataCount - 1
|
|
3268
|
-
if (lState<0 and data[nDataCount - 1] <= data[-lState]) :
|
|
3269
|
-
lState = 1 - nDataCount
|
|
3270
|
-
|
|
3271
|
-
if (lState>0) :
|
|
3272
|
-
j = lLastPos
|
|
3273
|
-
dif = (data[lState] - data[j]) / (lState - lLastPos )
|
|
3274
|
-
dest[j]=data[lLastPos]
|
|
3275
|
-
j+=1
|
|
3276
|
-
for j in range(j, lState+1) :
|
|
3277
|
-
dest[j]=data[lLastPos] + (j - lLastPos)*dif
|
|
3278
|
-
else :
|
|
3279
|
-
j = -lState
|
|
3280
|
-
dif = (data[lLastPos] - data[j]) / (-lState - lLastPos)
|
|
3281
|
-
dest[j]=data[-lState]
|
|
3282
|
-
j-=1
|
|
3283
|
-
for j in range(j,lLastPos-1,-1) : # for (; j >= lLastPos; j--)
|
|
3284
|
-
dest[j]=(data[-lState] + (-lState - j)*dif)
|
|
3285
|
-
|
|
3286
|
-
lState = abs(lState)
|
|
3287
|
-
if (lState<nDataCount - 1) :
|
|
3288
|
-
if (data[nDataCount - 1] >= data[lState]) :
|
|
3289
|
-
j = lState
|
|
3290
|
-
dif = (data[nDataCount - 1] - data[j]) / (nDataCount - lState)
|
|
3291
|
-
dest[j]=(data[lState])
|
|
3292
|
-
j+=1
|
|
3293
|
-
for j in range(j, nDataCount):
|
|
3294
|
-
dest[j]=(data[lState] + (j - lState)*dif)
|
|
3295
|
-
else :
|
|
3296
|
-
j = nDataCount - 1
|
|
3297
|
-
dif = (data[lState] - data[j]) / (nDataCount - lState)
|
|
3298
|
-
dest[j]=(data[nDataCount - 1])
|
|
3299
|
-
j-=1
|
|
3300
|
-
for j in range(j, lState-1, -1) : #for (; j >= lState; j--)
|
|
3301
|
-
dest[j]=(data[nDataCount - 1] + (nDataCount - j)*dif)
|
|
3302
|
-
|
|
3303
|
-
return dest
|
|
3304
|
-
|
|
3305
|
-
# 属于未来函数,前M个ZIG转向波谷值.
|
|
3306
|
-
# 用法: TROUGH(K,N,M)表示之字转向ZIG(K,N)的前M个波谷的数值,M必须大于等于1
|
|
3307
|
-
# 例如: TROUGH(2,5,2)表示%5最低价ZIG转向的前2个波谷的数值
|
|
3308
|
-
def TROUGH(self,data,n,n2):
|
|
3309
|
-
zigData=self.ZIG(data,n) # 计算ZIG
|
|
3310
|
-
lEnd=n2
|
|
3311
|
-
if (lEnd<1) :
|
|
3312
|
-
return []
|
|
3313
|
-
|
|
3314
|
-
nDataCount = len(zigData)
|
|
3315
|
-
dest=JSAlgorithm.CreateArray(nDataCount)
|
|
3316
|
-
trough = JSAlgorithm.CreateArray(lEnd,0)
|
|
3317
|
-
lFlag = 0
|
|
3318
|
-
i = self.GetFirstVaildIndex(zigData) + 1
|
|
3319
|
-
lEnd-=1
|
|
3320
|
-
while i<nDataCount and zigData[i]>zigData[i - 1] :
|
|
3321
|
-
i+=1
|
|
3322
|
-
|
|
3323
|
-
while i<nDataCount and zigData[i]<zigData[i - 1] :
|
|
3324
|
-
i+=1
|
|
3325
|
-
|
|
3326
|
-
i-=1
|
|
3327
|
-
trough[0] = i
|
|
3328
|
-
for i in range(i, nDataCount - 1) :
|
|
3329
|
-
if (zigData[i]<zigData[i + 1]) :
|
|
3330
|
-
if (lFlag) :
|
|
3331
|
-
if (lEnd) :
|
|
3332
|
-
tempTrough=copy.deepcopy(trough)
|
|
3333
|
-
for j in range(lEnd) :
|
|
3334
|
-
trough[j+1]=tempTrough[j]
|
|
3335
|
-
lFlag = 0
|
|
3336
|
-
trough[lFlag] = i
|
|
3337
|
-
else :
|
|
3338
|
-
lFlag = 1
|
|
3339
|
-
if (trough[lEnd]):
|
|
3340
|
-
dest[i]=zigData[trough[lEnd]]
|
|
3341
|
-
|
|
3342
|
-
if (trough[lEnd]) :
|
|
3343
|
-
dest[i]=zigData[trough[lEnd]]
|
|
3344
|
-
|
|
3345
|
-
return dest
|
|
3346
|
-
|
|
3347
|
-
# 属于未来函数,前M个ZIG转向波谷到当前距离.
|
|
3348
|
-
# 用法: TROUGHBARS(K,N,M)表示之字转向ZIG(K,N)的前M个波谷到当前的周期数,M必须大于等于1
|
|
3349
|
-
# 例如: TROUGHBARS(2,5,2)表示%5最低价ZIG转向的前2个波谷到当前的周期数
|
|
3350
|
-
def TROUGHBARS(self,data,n,n2) :
|
|
3351
|
-
zigData=self.ZIG(data,n) # 计算ZIG
|
|
3352
|
-
lEnd=n2
|
|
3353
|
-
if (lEnd<1) :
|
|
3354
|
-
return []
|
|
3355
|
-
|
|
3356
|
-
nDataCount = len(zigData)
|
|
3357
|
-
dest=JSAlgorithm.CreateArray(nDataCount)
|
|
3358
|
-
trough = JSAlgorithm.CreateArray(lEnd,0)
|
|
3359
|
-
lFlag = 0
|
|
3360
|
-
i = self.GetFirstVaildIndex(zigData) + 1
|
|
3361
|
-
lEnd-=1
|
|
3362
|
-
while i<nDataCount and zigData[i]>zigData[i - 1] :
|
|
3363
|
-
i+=1
|
|
3364
|
-
|
|
3365
|
-
while i<nDataCount and zigData[i]<zigData[i - 1] :
|
|
3366
|
-
i+=1
|
|
3367
|
-
|
|
3368
|
-
i-=1
|
|
3369
|
-
trough[0] = i
|
|
3370
|
-
for i in range(i, nDataCount - 1) :
|
|
3371
|
-
if (zigData[i]<zigData[i + 1]) :
|
|
3372
|
-
if (lFlag) :
|
|
3373
|
-
if (lEnd) :
|
|
3374
|
-
tempTrough=copy.deepcopy(trough)
|
|
3375
|
-
for j in range(lEnd) :
|
|
3376
|
-
trough[j+1]=tempTrough[j]
|
|
3377
|
-
lFlag = 0
|
|
3378
|
-
trough[lFlag] = i
|
|
3379
|
-
else :
|
|
3380
|
-
lFlag = 1
|
|
3381
|
-
if (trough[lEnd]) :
|
|
3382
|
-
dest[i]=(i - trough[lEnd])
|
|
3383
|
-
|
|
3384
|
-
if (trough[lEnd]) :
|
|
3385
|
-
dest[i]=(i - trough[lEnd])
|
|
3386
|
-
|
|
3387
|
-
return dest
|
|
3388
|
-
|
|
3389
|
-
|
|
3390
|
-
# 属于未来函数,前M个ZIG转向波峰值.
|
|
3391
|
-
#用法: PEAK(K,N,M)表示之字转向ZIG(K,N)的前M个波峰的数值,M必须大于等于1
|
|
3392
|
-
# 例如: PEAK(1,5,1)表示%5最高价ZIG转向的上一个波峰的数值
|
|
3393
|
-
def PEAK(self, data,n,n2) :
|
|
3394
|
-
zigData=self.ZIG(data,n) # 计算ZIG
|
|
3395
|
-
lEnd=n2
|
|
3396
|
-
if (lEnd<1) :
|
|
3397
|
-
return []
|
|
3398
|
-
|
|
3399
|
-
nDataCount = len(zigData)
|
|
3400
|
-
dest=JSAlgorithm.CreateArray(nDataCount)
|
|
3401
|
-
trough = JSAlgorithm.CreateArray(lEnd,0)
|
|
3402
|
-
lFlag = 0
|
|
3403
|
-
i = self.GetFirstVaildIndex(zigData) + 1
|
|
3404
|
-
lEnd-=1
|
|
3405
|
-
while i<nDataCount and zigData[i]>zigData[i - 1] :
|
|
3406
|
-
i+=1
|
|
3407
|
-
|
|
3408
|
-
while i<nDataCount and zigData[i]<zigData[i - 1] :
|
|
3409
|
-
i+=1
|
|
3410
|
-
|
|
3411
|
-
i-=1
|
|
3412
|
-
trough[0] = i
|
|
3413
|
-
for i in range(i, nDataCount - 1) :
|
|
3414
|
-
if (zigData[i]<zigData[i + 1]) :
|
|
3415
|
-
if (lFlag) :
|
|
3416
|
-
if (lEnd) :
|
|
3417
|
-
tempTrough=copy.deepcopy(trough)
|
|
3418
|
-
for j in range(lEnd) :
|
|
3419
|
-
trough[j+1]=tempTrough[j]
|
|
3420
|
-
lFlag = 0
|
|
3421
|
-
trough[lFlag] = i
|
|
3422
|
-
else :
|
|
3423
|
-
lFlag = 1
|
|
3424
|
-
if(trough[lEnd]) :
|
|
3425
|
-
dest[i]=zigData[trough[lEnd]]
|
|
3426
|
-
|
|
3427
|
-
if (trough[lEnd]) :
|
|
3428
|
-
dest[i]=zigData[trough[lEnd]]
|
|
3429
|
-
|
|
3430
|
-
return dest
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
# 属于未来函数,前M个ZIG转向波峰到当前距离.
|
|
3434
|
-
# 用法:
|
|
3435
|
-
# PEAKBARS(K,N,M)表示之字转向ZIG(K,N)的前M个波峰到当前的周期数,M必须大于等于1
|
|
3436
|
-
# 例如: PEAKBARS(0,5,1)表示%5开盘价ZIG转向的上一个波峰到当前的周期数
|
|
3437
|
-
def PEAKBARS(self, data,n,n2) :
|
|
3438
|
-
zigData=self.ZIG(data,n) # 计算ZIG
|
|
3439
|
-
lEnd=n2
|
|
3440
|
-
if (lEnd<1) :
|
|
3441
|
-
return []
|
|
3442
|
-
|
|
3443
|
-
nDataCount = len(zigData)
|
|
3444
|
-
dest=JSAlgorithm.CreateArray(nDataCount)
|
|
3445
|
-
trough = JSAlgorithm.CreateArray(lEnd,0)
|
|
3446
|
-
lFlag = 0
|
|
3447
|
-
i = self.GetFirstVaildIndex(zigData) + 1
|
|
3448
|
-
lEnd-=1
|
|
3449
|
-
while i<nDataCount and zigData[i]>zigData[i - 1] :
|
|
3450
|
-
i+=1
|
|
3451
|
-
|
|
3452
|
-
while i<nDataCount and zigData[i]<zigData[i - 1] :
|
|
3453
|
-
i+=1
|
|
3454
|
-
|
|
3455
|
-
i-=1
|
|
3456
|
-
trough[0] = i
|
|
3457
|
-
for i in range(i, nDataCount - 1) :
|
|
3458
|
-
if (zigData[i]<zigData[i + 1]) :
|
|
3459
|
-
if (lFlag) :
|
|
3460
|
-
if (lEnd) :
|
|
3461
|
-
tempTrough=copy.deepcopy(trough)
|
|
3462
|
-
for j in range(lEnd) :
|
|
3463
|
-
trough[j+1]=tempTrough[j]
|
|
3464
|
-
lFlag = 0
|
|
3465
|
-
trough[lFlag] = i
|
|
3466
|
-
else :
|
|
3467
|
-
lFlag = 1
|
|
3468
|
-
if(trough[lEnd]) :
|
|
3469
|
-
dest[i]=dest[i]=(i - trough[lEnd])
|
|
3470
|
-
|
|
3471
|
-
if (trough[lEnd]) :
|
|
3472
|
-
dest[i]=(i - trough[lEnd])
|
|
3473
|
-
|
|
3474
|
-
return dest
|
|
3475
|
-
|
|
3476
|
-
|
|
3477
|
-
|
|
3478
|
-
# 函数调用
|
|
3479
|
-
def CallFunction(self,name,args,node,symbolData=None) :
|
|
3480
|
-
if name=='MAX':
|
|
3481
|
-
return self.MAX(args[0], args[1])
|
|
3482
|
-
elif name=='MIN':
|
|
3483
|
-
return self.MIN(args[0], args[1])
|
|
3484
|
-
elif name=='REF':
|
|
3485
|
-
return self.REF(args[0], args[1])
|
|
3486
|
-
elif name=='REFV':
|
|
3487
|
-
return self.REFV(args[0], args[1])
|
|
3488
|
-
elif name=='REFX':
|
|
3489
|
-
return self.REFX(args[0], args[1])
|
|
3490
|
-
elif name=='REFXV':
|
|
3491
|
-
return self.REFXV(args[0], args[1])
|
|
3492
|
-
elif name=='ABS':
|
|
3493
|
-
return self.ABS(args[0])
|
|
3494
|
-
elif name=='MA':
|
|
3495
|
-
return self.MA(args[0], args[1])
|
|
3496
|
-
elif name=="EMA":
|
|
3497
|
-
return self.EMA(args[0], args[1])
|
|
3498
|
-
elif name=="SMA":
|
|
3499
|
-
return self.SMA(args[0], args[1],args[2])
|
|
3500
|
-
elif name=="DMA":
|
|
3501
|
-
return self.DMA(args[0], args[1])
|
|
3502
|
-
elif name=='EXPMA':
|
|
3503
|
-
return self.EXPMA(args[0], int(args[1]))
|
|
3504
|
-
elif name=='EXPMEMA':
|
|
3505
|
-
return self.EXPMEMA(args[0], int(args[1]))
|
|
3506
|
-
elif name=='COUNT':
|
|
3507
|
-
return self.COUNT(args[0], args[1])
|
|
3508
|
-
elif name=='LLV':
|
|
3509
|
-
return self.LLV(args[0], args[1])
|
|
3510
|
-
elif name=='LLVBARS':
|
|
3511
|
-
return self.LLVBARS(args[0], int(args[1]))
|
|
3512
|
-
elif name=='HHV':
|
|
3513
|
-
return self.HHV(args[0], args[1])
|
|
3514
|
-
elif name=='HHVBARS':
|
|
3515
|
-
return self.HHVBARS(args[0], int(args[1]))
|
|
3516
|
-
elif name=='MULAR':
|
|
3517
|
-
return self.MULAR(args[0], int(args[1]))
|
|
3518
|
-
elif name=='CROSS':
|
|
3519
|
-
return self.CROSS(args[0], args[1])
|
|
3520
|
-
elif name=='LONGCROSS':
|
|
3521
|
-
return self.LONGCROSS(args[0], args[1], int(args[2]))
|
|
3522
|
-
elif name=='AVEDEV':
|
|
3523
|
-
return self.AVEDEV(args[0], int(args[1]))
|
|
3524
|
-
elif name=='STD':
|
|
3525
|
-
return self.STD(args[0], int(args[1]))
|
|
3526
|
-
elif name in ('IF','IFF'):
|
|
3527
|
-
return self.IF(args[0], args[1], args[2])
|
|
3528
|
-
elif name=='IFN':
|
|
3529
|
-
return self.IFN(args[0], args[1], args[2])
|
|
3530
|
-
elif name=='NOT':
|
|
3531
|
-
return self.NOT(args[0])
|
|
3532
|
-
elif name=='SUM':
|
|
3533
|
-
return self.SUM(args[0], args[1])
|
|
3534
|
-
elif name=='RANGE':
|
|
3535
|
-
return self.RANGE(args[0],args[1],args[2])
|
|
3536
|
-
elif name=='EXIST':
|
|
3537
|
-
return self.EXIST(args[0],args[1])
|
|
3538
|
-
elif name=='EXISTR':
|
|
3539
|
-
return self.EXISTR(args[0],int(args[1]),int(args[2]))
|
|
3540
|
-
elif name=='FILTER':
|
|
3541
|
-
return self.FILTER(args[0],int(args[1]))
|
|
3542
|
-
elif name=='TFILTER':
|
|
3543
|
-
return self.TFILTER(args[0],args[1],int(args[2]))
|
|
3544
|
-
elif name=='SLOPE':
|
|
3545
|
-
return self.SLOPE(args[0],int(args[1]))
|
|
3546
|
-
elif name=='BARSLAST':
|
|
3547
|
-
return self.BARSLAST(args[0])
|
|
3548
|
-
elif name=='BARSCOUNT':
|
|
3549
|
-
return self.BARSCOUNT(args[0])
|
|
3550
|
-
elif name=='BARSSINCEN':
|
|
3551
|
-
return self.BARSSINCEN(args[0],int(args[1]))
|
|
3552
|
-
elif name=='BARSSINCE':
|
|
3553
|
-
return self.BARSSINCE(args[0])
|
|
3554
|
-
elif name=='LAST':
|
|
3555
|
-
return self.LAST(args[0],int(args[1]),int(args[2]))
|
|
3556
|
-
elif name=='EVERY':
|
|
3557
|
-
return self.EVERY(args[0],int(args[1]))
|
|
3558
|
-
elif name=='DEVSQ':
|
|
3559
|
-
return self.DEVSQ(args[0], int(args[1]))
|
|
3560
|
-
elif name=='ZIG':
|
|
3561
|
-
return self.ZIG(args[0],args[1])
|
|
3562
|
-
elif name=='TROUGH':
|
|
3563
|
-
return self.TROUGH(args[0],args[1],int(args[2]))
|
|
3564
|
-
elif name=='TROUGHBARS':
|
|
3565
|
-
return self.TROUGHBARS(args[0],args[1],int(args[2]))
|
|
3566
|
-
elif name=='PEAK':
|
|
3567
|
-
return self.PEAK(args[0],args[1],int(args[2]))
|
|
3568
|
-
elif name=='PEAKBARS':
|
|
3569
|
-
return self.PEAKBARS(args[0],args[1],int(args[2]))
|
|
3570
|
-
elif name=='COST':
|
|
3571
|
-
return self.COST(args[0],node)
|
|
3572
|
-
elif name=='WINNER':
|
|
3573
|
-
return self.WINNER(args[0],node)
|
|
3574
|
-
elif name=='PPART':
|
|
3575
|
-
return self.PPART(args[0],node)
|
|
3576
|
-
elif name=='COSTEX':
|
|
3577
|
-
return self.COSTEX(args[0],args[1],node)
|
|
3578
|
-
elif name=='LWINNER':
|
|
3579
|
-
return self.LWINNER(args[0],args[1],node)
|
|
3580
|
-
elif name=='PWINNER':
|
|
3581
|
-
return self.PWINNER(args[0],args[1],node)
|
|
3582
|
-
elif name=='FORCAST':
|
|
3583
|
-
return self.FORCAST(args[0], int(args[1]))
|
|
3584
|
-
elif name=='STDP':
|
|
3585
|
-
return self.STDP(args[0], int(args[1]))
|
|
3586
|
-
elif name=='VAR':
|
|
3587
|
-
return self.VAR(args[0], int(args[1]))
|
|
3588
|
-
elif name=='VARP':
|
|
3589
|
-
return self.VARP(args[0], int(args[1]))
|
|
3590
|
-
elif name=='UPNDAY':
|
|
3591
|
-
return self.UPNDAY(args[0],int(args[1]))
|
|
3592
|
-
elif name=='DOWNNDAY':
|
|
3593
|
-
return self.DOWNNDAY(args[0],int(args[1]))
|
|
3594
|
-
elif name=='NDAY':
|
|
3595
|
-
return self.NDAY(args[0],args[1],int(args[2]))
|
|
3596
|
-
elif name=='RELATE':
|
|
3597
|
-
return self.RELATE(args[0],args[1],int(args[2]))
|
|
3598
|
-
elif name=='COVAR':
|
|
3599
|
-
return self.COVAR(args[0],args[1],int(args[2]))
|
|
3600
|
-
elif name=='BETA':
|
|
3601
|
-
return self.BETA(int(args[0]))
|
|
3602
|
-
elif name=='BETA2':
|
|
3603
|
-
return self.BETA2(args[0],args[1],int(args[2]))
|
|
3604
|
-
elif name=='WMA':
|
|
3605
|
-
return self.WMA(args[0], args[1])
|
|
3606
|
-
elif name=='MEMA':
|
|
3607
|
-
return self.MEMA(args[0], int(args[1]))
|
|
3608
|
-
elif name=='SUMBARS':
|
|
3609
|
-
return self.SUMBARS(args[0], args[1])
|
|
3610
|
-
elif name=='REVERSE':
|
|
3611
|
-
return self.REVERSE(args[0])
|
|
3612
|
-
elif name=='SAR':
|
|
3613
|
-
return self.SAR(int(args[0]), args[1], args[2])
|
|
3614
|
-
elif name=='SARTURN':
|
|
3615
|
-
return self.SARTURN(int(args[0]), args[1], args[2])
|
|
3616
|
-
elif name=='BACKSET':
|
|
3617
|
-
return self.BACKSET(args[0], int(args[1]))
|
|
3618
|
-
# 三角函数
|
|
3619
|
-
elif name=='ATAN':
|
|
3620
|
-
return self.Trigonometric(args[0],math.atan)
|
|
3621
|
-
elif name=='ACOS':
|
|
3622
|
-
return self.Trigonometric(args[0],math.acos)
|
|
3623
|
-
elif name=='ASIN':
|
|
3624
|
-
return self.Trigonometric(args[0],math.asin)
|
|
3625
|
-
elif name=='COS':
|
|
3626
|
-
return self.Trigonometric(args[0],math.cos)
|
|
3627
|
-
elif name=='SIN':
|
|
3628
|
-
return self.Trigonometric(args[0],math.sin)
|
|
3629
|
-
elif name=='TAN':
|
|
3630
|
-
return self.Trigonometric(args[0],math.tan)
|
|
3631
|
-
elif name=='LN':
|
|
3632
|
-
return self.Trigonometric(args[0],math.log)
|
|
3633
|
-
elif name=='LOG':
|
|
3634
|
-
return self.Trigonometric(args[0],math.log10)
|
|
3635
|
-
elif name=='EXP':
|
|
3636
|
-
return self.Trigonometric(args[0],math.exp)
|
|
3637
|
-
elif name=='SQRT':
|
|
3638
|
-
return self.Trigonometric(args[0],math.sqrt)
|
|
3639
|
-
else:
|
|
3640
|
-
self.ThrowUnexpectedNode(node,'函数'+name+'不存在')
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
def ThrowUnexpectedNode(self, node,message='执行异常') :
|
|
3644
|
-
marker=node.Marker
|
|
3645
|
-
msg=message
|
|
3646
|
-
return self.ErrorHandler.ThrowError(marker.Index,marker.Line,marker.Column,msg)
|
|
3647
|
-
|
|
3648
|
-
|
|
3649
|
-
#######################################################################################################
|
|
3650
|
-
#
|
|
3651
|
-
# 绘图函数
|
|
3652
|
-
#
|
|
3653
|
-
#######################################################################################################
|
|
3654
|
-
|
|
3655
|
-
class DrawItem:
|
|
3656
|
-
def __init__(self, drawType, drawData=[], text=None) :
|
|
3657
|
-
self.DrawType=drawType
|
|
3658
|
-
self.DrawData=drawData
|
|
3659
|
-
self.Text=None
|
|
3660
|
-
|
|
3661
|
-
class JSDraw():
|
|
3662
|
-
def __init__(self, errorHandler, symbolData) :
|
|
3663
|
-
self.ErrorHandler=errorHandler
|
|
3664
|
-
self.SymbolData=symbolData
|
|
3665
|
-
|
|
3666
|
-
@staticmethod
|
|
3667
|
-
def IsDrawFunction(name) :
|
|
3668
|
-
return name in ("STICKLINE","DRAWTEXT",'SUPERDRAWTEXT','DRAWLINE','DRAWBAND','DRAWKLINE','DRAWKLINE_IF',
|
|
3669
|
-
'PLOYLINE','POLYLINE','DRAWNUMBER','DRAWICON','DRAWCHANNEL')
|
|
3670
|
-
|
|
3671
|
-
def DRAWTEXT(self, condition,price,text) :
|
|
3672
|
-
result=DrawItem(drawType='DRAWTEXT', text=text)
|
|
3673
|
-
if (len(condition)<=0) :
|
|
3674
|
-
return result
|
|
3675
|
-
|
|
3676
|
-
dataLen=len(condition)
|
|
3677
|
-
drawData=JSComplierHelper.CreateArray(dataLen)
|
|
3678
|
-
IsNumber=JSComplierHelper.IsNumber(price)
|
|
3679
|
-
|
|
3680
|
-
for i in range(dataLen) :
|
|
3681
|
-
if JSComplierHelper.IsNaN(condition[i]) or not condition[i] :
|
|
3682
|
-
continue
|
|
3683
|
-
|
|
3684
|
-
if (IsNumber) :
|
|
3685
|
-
drawData[i]=price
|
|
3686
|
-
else :
|
|
3687
|
-
if (JSComplierHelper.IsNumber(price[i])) :
|
|
3688
|
-
drawData[i]=price[i]
|
|
3689
|
-
|
|
3690
|
-
result.DrawData=drawData
|
|
3691
|
-
return result
|
|
3692
|
-
|
|
3693
|
-
# direction 文字Y轴位置 0=middle 1=价格的顶部 2=价格的底部
|
|
3694
|
-
# offset 文字Y轴偏移
|
|
3695
|
-
def SUPERDRAWTEXT(self,condition,price,text,direction,offset) :
|
|
3696
|
-
result=DrawItem(drawType='SUPERDRAWTEXT', text=text)
|
|
3697
|
-
result.YOffset=offset
|
|
3698
|
-
result.Direction=direction
|
|
3699
|
-
result.TextAlign='center'
|
|
3700
|
-
if len(condition)<=0 :
|
|
3701
|
-
return result
|
|
3702
|
-
|
|
3703
|
-
dataLen=len(condition)
|
|
3704
|
-
drawData=JSComplierHelper.CreateArray(dataLen)
|
|
3705
|
-
IsNumber=JSComplierHelper.IsNumber(price)
|
|
3706
|
-
|
|
3707
|
-
for i in range(dataLen) :
|
|
3708
|
-
if JSComplierHelper.IsNaN(condition[i]) or not condition[i] :
|
|
3709
|
-
continue
|
|
3710
|
-
|
|
3711
|
-
if IsNumber :
|
|
3712
|
-
drawData[i]=price
|
|
3713
|
-
else :
|
|
3714
|
-
if JSComplierHelper.IsNumber(price[i]) :
|
|
3715
|
-
drawData[i]=price[i]
|
|
3716
|
-
|
|
3717
|
-
result.DrawData=drawData
|
|
3718
|
-
return result
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
# STICKLINE 绘制柱线
|
|
3722
|
-
# 在图形上绘制柱线。
|
|
3723
|
-
# 用法: STICKLINE(COND,PRICE1,PRICE2,WIDTH,EMPTY),当COND条件满足时,在PRICE1和PRICE2位置之间画柱状线,宽度为WIDTH(10为标准间距),EMPTH不为0则画空心柱。
|
|
3724
|
-
# 例如: STICKLINE(CLOSE>OPEN,CLOSE,OPEN,0.8,1)表示画K线中阳线的空心柱体部分。
|
|
3725
|
-
def STICKLINE(self, condition,data,data2,width,type) :
|
|
3726
|
-
result=DrawItem(drawType='STICKLINE')
|
|
3727
|
-
result.Width=width
|
|
3728
|
-
result.Type=int(type)
|
|
3729
|
-
|
|
3730
|
-
if len(condition)<=0 :
|
|
3731
|
-
return result
|
|
3732
|
-
|
|
3733
|
-
dataLen=len(condition)
|
|
3734
|
-
drawData=JSComplierHelper.CreateArray(dataLen)
|
|
3735
|
-
isNumber=JSComplierHelper.IsNumber(data)
|
|
3736
|
-
isNumber2=JSComplierHelper.IsNumber(data2)
|
|
3737
|
-
|
|
3738
|
-
for i in range(dataLen) :
|
|
3739
|
-
if JSComplierHelper.IsNaN(condition[i]) or not condition[i] :
|
|
3740
|
-
continue
|
|
3741
|
-
|
|
3742
|
-
if isNumber and isNumber2 :
|
|
3743
|
-
item=Variant()
|
|
3744
|
-
item.Value,item.Value2 = data,data2
|
|
3745
|
-
drawData[i]=item
|
|
3746
|
-
elif isNumber and not isNumber2 :
|
|
3747
|
-
if JSComplierHelper.IsNaN(data2[i]) :
|
|
3748
|
-
continue
|
|
3749
|
-
item=Variant()
|
|
3750
|
-
item.Value,item.Value2 = data,data2[i]
|
|
3751
|
-
drawData[i]=item
|
|
3752
|
-
elif not isNumber and isNumber2 :
|
|
3753
|
-
if JSComplierHelper.IsNaN(data[i]) :
|
|
3754
|
-
continue
|
|
3755
|
-
item=Variant()
|
|
3756
|
-
item.Value,item.Value2 = data[i],data2
|
|
3757
|
-
drawData[i]=item
|
|
3758
|
-
else :
|
|
3759
|
-
if JSComplierHelper.IsNaN(data[i]) or JSComplierHelper.IsNaN(data2[i]) :
|
|
3760
|
-
continue
|
|
3761
|
-
item=Variant()
|
|
3762
|
-
item.Value,item.Value2 = data[i],data2[i]
|
|
3763
|
-
drawData[i]=item
|
|
3764
|
-
|
|
3765
|
-
result.DrawData=drawData
|
|
3766
|
-
return result
|
|
3767
|
-
|
|
3768
|
-
# 画出带状线.
|
|
3769
|
-
# 用法: DRAWBAND(VAL1,COLOR1,VAL2,COLOR2),当VAL1>VAL2时,在VAL1和VAL2之间填充COLOR1;当VAL1<VAL2时,填充COLOR2,这里的颜色均使用RGB函数计算得到.
|
|
3770
|
-
# 例如: DRAWBAND(OPEN,RGB(0,224,224),CLOSE,RGB(255,96,96));
|
|
3771
|
-
def DRAWBAND(self,data,color,data2,color2) :
|
|
3772
|
-
result=DrawItem(drawType='DRAWBAND')
|
|
3773
|
-
result.Color=[color.lower(),color2.lower()] # 颜色使用小写字符串
|
|
3774
|
-
len1, len2=len(data), len(data2)
|
|
3775
|
-
count=max(len1, len2)
|
|
3776
|
-
|
|
3777
|
-
drawData=[]
|
|
3778
|
-
for i in range(count) :
|
|
3779
|
-
item=Variant()
|
|
3780
|
-
item.Value, item.Value2 = None, None
|
|
3781
|
-
if (i<len1) :
|
|
3782
|
-
item.Value=data[i]
|
|
3783
|
-
if (i<len2) :
|
|
3784
|
-
item.Value2=data2[i]
|
|
3785
|
-
|
|
3786
|
-
drawData.append(item)
|
|
3787
|
-
|
|
3788
|
-
result.DrawData=drawData
|
|
3789
|
-
return result
|
|
3790
|
-
|
|
3791
|
-
def DRAWKLINE(self,high,open,low,close) :
|
|
3792
|
-
result=DrawItem(drawType='DRAWKLINE')
|
|
3793
|
-
highLen, openLen, lowLen, closeLen=len(high),len(open), len(low), len(close)
|
|
3794
|
-
count=max(highLen, openLen,lowLen,closeLen)
|
|
3795
|
-
drawData=JSComplierHelper.CreateArray(count)
|
|
3796
|
-
for i in range(count) :
|
|
3797
|
-
item=Variant()
|
|
3798
|
-
item.Open, item.High, item.Low,item.Close = None, None, None, None
|
|
3799
|
-
if (i<highLen and i<openLen and i<lowLen and i<closeLen) :
|
|
3800
|
-
item.Open=open[i]
|
|
3801
|
-
item.High=high[i]
|
|
3802
|
-
item.Low=low[i]
|
|
3803
|
-
item.Close=close[i]
|
|
3804
|
-
|
|
3805
|
-
drawData[i]=item
|
|
3806
|
-
|
|
3807
|
-
result.DrawData=drawData
|
|
3808
|
-
return result
|
|
3809
|
-
|
|
3810
|
-
# 满足条件画一根K线
|
|
3811
|
-
def DRAWKLINE_IF(self, condition,high,open,low,close) :
|
|
3812
|
-
result=DrawItem(drawType='DRAWKLINE_IF')
|
|
3813
|
-
highLen, openLen, lowLen, closeLen=len(high),len(open), len(low), len(close)
|
|
3814
|
-
count=max(highLen, openLen,lowLen,closeLen)
|
|
3815
|
-
drawData=JSComplierHelper.CreateArray(count)
|
|
3816
|
-
|
|
3817
|
-
for i in range(count) :
|
|
3818
|
-
item=Variant()
|
|
3819
|
-
item.Open, item.High, item.Low,item.Close = None, None, None, None
|
|
3820
|
-
|
|
3821
|
-
if (i<highLen and i<openLen and i<lowLen and i<closeLen and i<len(condition)) :
|
|
3822
|
-
if (condition[i]) :
|
|
3823
|
-
item.Open=open[i]
|
|
3824
|
-
item.High=high[i]
|
|
3825
|
-
item.Low=low[i]
|
|
3826
|
-
item.Close=close[i]
|
|
3827
|
-
|
|
3828
|
-
drawData[i]=item
|
|
3829
|
-
|
|
3830
|
-
result.DrawData=drawData
|
|
3831
|
-
return result
|
|
3832
|
-
|
|
3833
|
-
|
|
3834
|
-
# 画出数字.
|
|
3835
|
-
# 用法: DRAWNUMBER(COND,PRICE,NUMBER),当COND条件满足时,在PRICE位置书写数字NUMBER.
|
|
3836
|
-
# 例如: DRAWNUMBER(CLOSE/OPEN>1.08,LOW,C)表示当日实体阳线大于8%时在最低价位置显示收盘价.
|
|
3837
|
-
def DRAWNUMBER(self, condition,data,data2) :
|
|
3838
|
-
drawData=Variant()
|
|
3839
|
-
drawData.Value, drawData.Text = [], []
|
|
3840
|
-
result=DrawItem(drawType='DRAWNUMBER', drawData=drawData)
|
|
3841
|
-
|
|
3842
|
-
isNumber=JSComplierHelper.IsNumber(data2)
|
|
3843
|
-
if (isNumber) :
|
|
3844
|
-
text= '%.2f' % data2
|
|
3845
|
-
|
|
3846
|
-
count=len(condition)
|
|
3847
|
-
drawData.Value=JSComplierHelper.CreateArray(count)
|
|
3848
|
-
drawData.Text=JSComplierHelper.CreateArray(count)
|
|
3849
|
-
|
|
3850
|
-
for i in range(count) :
|
|
3851
|
-
if not condition[i] :
|
|
3852
|
-
continue
|
|
3853
|
-
if i>=len(data) or not JSComplierHelper.IsNumber(data[i]) :
|
|
3854
|
-
continue
|
|
3855
|
-
|
|
3856
|
-
if (isNumber) :
|
|
3857
|
-
drawData.Value[i]=data[i]
|
|
3858
|
-
drawData.Text[i]=text
|
|
3859
|
-
else :
|
|
3860
|
-
if i>=len(data2) or data2[i]==None :
|
|
3861
|
-
continue
|
|
3862
|
-
drawData.Value[i]=data[i]
|
|
3863
|
-
if JSComplierHelper.IsNumber(data2[i]) :
|
|
3864
|
-
drawData.Text[i] = '%.2f' % data2[i]
|
|
3865
|
-
else :
|
|
3866
|
-
drawData.Text[i] = str(data2[i])
|
|
3867
|
-
|
|
3868
|
-
result.DrawData=drawData
|
|
3869
|
-
return result
|
|
3870
|
-
|
|
3871
|
-
# 在图形上绘制小图标.
|
|
3872
|
-
# 用法: DRAWICON(COND,PRICE,TYPE),当COND条件满足时,在PRICE位置画TYPE号图标(TYPE为1--41).
|
|
3873
|
-
# 例如: DRAWICON(CLOSE>OPEN,LOW,1)表示当收阳时在最低价位置画1号图标.
|
|
3874
|
-
def DRAWICON(self, condition,data,type) :
|
|
3875
|
-
icon=Variant()
|
|
3876
|
-
if (type not in g_JSComplierResource.DrawIcon.Data) :
|
|
3877
|
-
type=11 #默认图标
|
|
3878
|
-
iconfont=g_JSComplierResource.DrawIcon.Data[type]
|
|
3879
|
-
icon=Variant()
|
|
3880
|
-
icon.Symbol, icon.Color, icon.Family, icon.IconFont, icon.ID = iconfont.Text, iconfont.Color, g_JSComplierResource.DrawIcon.Family, True, type
|
|
3881
|
-
|
|
3882
|
-
result=DrawItem(drawType='DRAWICON')
|
|
3883
|
-
result.Icon=icon
|
|
3884
|
-
if (len(condition)<=0) :
|
|
3885
|
-
return result
|
|
3886
|
-
|
|
3887
|
-
isNumber=JSComplierHelper.IsNumber(data)
|
|
3888
|
-
if JSComplierHelper.IsNumber(condition) :
|
|
3889
|
-
if not condition :
|
|
3890
|
-
return result
|
|
3891
|
-
|
|
3892
|
-
drawData=JSComplierHelper.CreateArray(len(self.SymbolData.Data.Data))
|
|
3893
|
-
for i in range(len(self.SymbolData.Data.Data)) :
|
|
3894
|
-
if isNumber :
|
|
3895
|
-
drawData[i]=data
|
|
3896
|
-
else :
|
|
3897
|
-
if i<len(data) and JSComplierHelper.IsNumber(data[i]) :
|
|
3898
|
-
drawData[i]=data[i]
|
|
3899
|
-
return result
|
|
3900
|
-
|
|
3901
|
-
drawData=JSComplierHelper.CreateArray(len(condition))
|
|
3902
|
-
for i in range(len(condition)) :
|
|
3903
|
-
if not condition[i] :
|
|
3904
|
-
continue
|
|
3905
|
-
|
|
3906
|
-
if isNumber :
|
|
3907
|
-
drawData[i]=data
|
|
3908
|
-
else :
|
|
3909
|
-
if JSComplierHelper.IsNumber(data[i]) :
|
|
3910
|
-
drawData[i]=data[i]
|
|
3911
|
-
|
|
3912
|
-
result.DrawData=drawData
|
|
3913
|
-
return result
|
|
3914
|
-
|
|
3915
|
-
# PLOYLINE 折线段
|
|
3916
|
-
# 在图形上绘制折线段。
|
|
3917
|
-
# 用法: PLOYLINE(COND,PRICE),当COND条件满足时,以PRICE位置为顶点画折线连接。
|
|
3918
|
-
# 例如: PLOYLINE(HIGH>=HHV(HIGH,20),HIGH)表示在创20天新高点之间画折线。
|
|
3919
|
-
def POLYLINE(self, condition,data) :
|
|
3920
|
-
result=DrawItem(drawType='POLYLINE')
|
|
3921
|
-
isNumber=JSComplierHelper.IsNumber(data)
|
|
3922
|
-
|
|
3923
|
-
drawData=JSComplierHelper.CreateArray(len(condition))
|
|
3924
|
-
bFirstPoint=False
|
|
3925
|
-
bSecondPont=False
|
|
3926
|
-
if isNumber :
|
|
3927
|
-
for i in range(len(condition)) :
|
|
3928
|
-
if bFirstPoint==False :
|
|
3929
|
-
if not condition[i] :
|
|
3930
|
-
continue
|
|
3931
|
-
|
|
3932
|
-
drawData[i]=data
|
|
3933
|
-
bFirstPoint=True
|
|
3934
|
-
else :
|
|
3935
|
-
drawData[i]=data
|
|
3936
|
-
|
|
3937
|
-
else :
|
|
3938
|
-
lineCache=Variant()
|
|
3939
|
-
lineCache.Start, lineCache.End, lineCache.List = Variant(), Variant(), []
|
|
3940
|
-
for i in range (len(condition)) :
|
|
3941
|
-
if (bFirstPoint==False and bSecondPont==False) :
|
|
3942
|
-
if condition[i]==None or not condition[i] :
|
|
3943
|
-
continue
|
|
3944
|
-
if i>=len(data) or not JSComplierHelper.IsNumber(data[i]) :
|
|
3945
|
-
continue
|
|
3946
|
-
|
|
3947
|
-
bFirstPoint=True
|
|
3948
|
-
# 第1个点
|
|
3949
|
-
lineCache.Start.ID=int(i)
|
|
3950
|
-
lineCache.Start.Value=data[i]
|
|
3951
|
-
|
|
3952
|
-
elif (bFirstPoint==True and bSecondPont==False) :
|
|
3953
|
-
if condition[i]==None or not condition[i] :
|
|
3954
|
-
continue
|
|
3955
|
-
if i>=len(data) or not JSComplierHelper.IsNumber(data[i]) :
|
|
3956
|
-
continue
|
|
3957
|
-
|
|
3958
|
-
# 第2个点
|
|
3959
|
-
lineCache.End.ID=int(i)
|
|
3960
|
-
lineCache.End.Value=data[i]
|
|
3961
|
-
# 根据起始点和结束点 计算中间各个点的数据
|
|
3962
|
-
lineData=JSComplierHelper.CalculateDrawLine(lineCache) # 计算2个点的线上 其他点的数值
|
|
3963
|
-
|
|
3964
|
-
for item in lineData :
|
|
3965
|
-
drawData[item.ID]=item.Value
|
|
3966
|
-
|
|
3967
|
-
start=Variant()
|
|
3968
|
-
start.ID, start.Value = lineCache.End.ID, lineCache.End.Value
|
|
3969
|
-
lineCache=Variant()
|
|
3970
|
-
lineCache.Start, lineCache.End = start, Variant()
|
|
3971
|
-
|
|
3972
|
-
result.DrawData=drawData
|
|
3973
|
-
return result
|
|
3974
|
-
|
|
3975
|
-
|
|
3976
|
-
# DRAWLINE 绘制直线段
|
|
3977
|
-
# 在图形上绘制直线段。
|
|
3978
|
-
# 用法: DRAWLINE(COND1,PRICE1,COND2,PRICE2,EXPAND)
|
|
3979
|
-
# 当COND1条件满足时,在PRICE1位置画直线起点,当COND2条件满足时,在PRICE2位置画直线终点,EXPAND为延长类型。
|
|
3980
|
-
# 例如: DRAWLINE(HIGH>=HHV(HIGH,20),HIGH,LOW<=LLV(LOW,20),LOW,1) 表示在创20天新高与创20天新低之间画直线并且向右延长。
|
|
3981
|
-
def DRAWLINE(self, condition,data,condition2,data2,expand) :
|
|
3982
|
-
result=DrawItem(drawType='DRAWLINE')
|
|
3983
|
-
result.Expand=expand
|
|
3984
|
-
|
|
3985
|
-
if len(condition)<=0 :
|
|
3986
|
-
return result
|
|
3987
|
-
|
|
3988
|
-
condLen1, condLen2 = len(condition), len(condition2)
|
|
3989
|
-
count=max(condLen1,condLen2)
|
|
3990
|
-
|
|
3991
|
-
drawData=JSComplierHelper.CreateArray(count)
|
|
3992
|
-
bFirstPoint=False
|
|
3993
|
-
bSecondPont=False
|
|
3994
|
-
lineCache=Variant()
|
|
3995
|
-
lineCache.Start, lineCache.End, lineCache.List = Variant(), Variant(), []
|
|
3996
|
-
|
|
3997
|
-
for i in range(count) :
|
|
3998
|
-
if (i<condLen1 and i<condLen2) :
|
|
3999
|
-
if (bFirstPoint==False and bSecondPont==False) :
|
|
4000
|
-
if condition[i]==None or not condition[i] :
|
|
4001
|
-
continue
|
|
4002
|
-
|
|
4003
|
-
bFirstPoint=True
|
|
4004
|
-
# 第1个点
|
|
4005
|
-
lineCache.Start.ID=i
|
|
4006
|
-
lineCache.Start.Value=data[i]
|
|
4007
|
-
|
|
4008
|
-
elif (bFirstPoint==True and bSecondPont==False) :
|
|
4009
|
-
bCondition=(condition[i]!=None and condition[i]) # 条件1
|
|
4010
|
-
bCondition2=(condition2[i]!=None and condition2[i]) # 条件2
|
|
4011
|
-
|
|
4012
|
-
if not bCondition and not bCondition2 :
|
|
4013
|
-
continue
|
|
4014
|
-
|
|
4015
|
-
if bCondition :
|
|
4016
|
-
# 移动第1个点
|
|
4017
|
-
lineCache.Start.ID=i
|
|
4018
|
-
lineCache.Start.Value=data[i]
|
|
4019
|
-
elif bCondition2:
|
|
4020
|
-
bSecondPont=True
|
|
4021
|
-
# 第2个点
|
|
4022
|
-
lineCache.End.ID=i
|
|
4023
|
-
lineCache.End.Value=data2[i]
|
|
4024
|
-
|
|
4025
|
-
elif (bFirstPoint==True and bSecondPont==True) : # 2个点都有了, 等待下一次的点出现
|
|
4026
|
-
bCondition=(condition[i]!=None and condition[i]) # 条件1
|
|
4027
|
-
bCondition2=(condition2[i]!=None and condition2[i]) # 条件2
|
|
4028
|
-
|
|
4029
|
-
if bCondition :
|
|
4030
|
-
lineData=JSComplierHelper.CalculateDrawLine(lineCache) # 计算2个点的线上 其他点的数值
|
|
4031
|
-
|
|
4032
|
-
for item in lineData :
|
|
4033
|
-
drawData[item.ID]=item.Value
|
|
4034
|
-
|
|
4035
|
-
bFirstPoint=bSecondPont=False
|
|
4036
|
-
lineCache=Variant()
|
|
4037
|
-
lineCache.Start, lineCache.End = Variant(), Variant()
|
|
4038
|
-
elif bCondition2 :
|
|
4039
|
-
lineCache.End.ID=i
|
|
4040
|
-
lineCache.End.Value=data2[i] # 移动第2个点
|
|
4041
|
-
|
|
4042
|
-
if bFirstPoint==True and bSecondPont==True : # 最后一组数据
|
|
4043
|
-
lineData=JSComplierHelper.CalculateDrawLine(lineCache)
|
|
4044
|
-
for item in lineData :
|
|
4045
|
-
drawData[item.ID]=item.Value
|
|
4046
|
-
|
|
4047
|
-
result.DrawData=drawData
|
|
4048
|
-
return result
|
|
4049
|
-
|
|
4050
|
-
|
|
4051
|
-
# 绘制通道
|
|
4052
|
-
# condition:条件
|
|
4053
|
-
# data,data2:通道顶部和底部
|
|
4054
|
-
# borderColor: 通道顶部和底部线段颜色RGB(24,30,40) 不填就不画
|
|
4055
|
-
# borderWidth: 通道顶部和底部线段宽度
|
|
4056
|
-
# areaColor: 通道面积颜色 RGB(200,30,44) 不填使用默认颜色
|
|
4057
|
-
# dotted: 通道顶部和底部虚线设置 '3,4' , 不填默认 3,3
|
|
4058
|
-
def DRAWCHANNEL(self,condition, data, data2, borderColor, borderWidth, dotted, areaColor) :
|
|
4059
|
-
result=DrawItem(drawType='DRAWCHANNEL')
|
|
4060
|
-
result.Border=Variant()
|
|
4061
|
-
|
|
4062
|
-
if borderColor:
|
|
4063
|
-
result.Border.Color=borderColor
|
|
4064
|
-
if borderWidth>0:
|
|
4065
|
-
result.Border.Width=borderWidth
|
|
4066
|
-
if areaColor:
|
|
4067
|
-
result.AreaColor=areaColor
|
|
4068
|
-
|
|
4069
|
-
if dotted :
|
|
4070
|
-
ary=dotted.split(',')
|
|
4071
|
-
result.Border.Dotted=[]
|
|
4072
|
-
for item in ary :
|
|
4073
|
-
if not item :
|
|
4074
|
-
continue
|
|
4075
|
-
value=int(item)
|
|
4076
|
-
if value<=0 :
|
|
4077
|
-
continue
|
|
4078
|
-
result.Border.Dotted.append(value)
|
|
4079
|
-
if len(result.Border.Dotted)<=0:
|
|
4080
|
-
result.Border.Dotted=None
|
|
4081
|
-
|
|
4082
|
-
isNumber=JSComplierHelper.IsNumber(data)
|
|
4083
|
-
isNumber2=JSComplierHelper.IsNumber(data2)
|
|
4084
|
-
if JSComplierHelper.IsNumber(condition) :
|
|
4085
|
-
if not condition :
|
|
4086
|
-
return result # 条件是否
|
|
4087
|
-
|
|
4088
|
-
drawData=JSComplierHelper.CreateArray(len(self.SymbolData.Data.Data))
|
|
4089
|
-
for i in range(len(self.SymbolData.Data.Data)) :
|
|
4090
|
-
if (isNumber and isNumber2) :
|
|
4091
|
-
item=Variant()
|
|
4092
|
-
item.Value, item.Value2 = data, data2
|
|
4093
|
-
drawData[i]=item
|
|
4094
|
-
elif (isNumber and not isNumber2) :
|
|
4095
|
-
if JSComplierHelper.IsNaN(data2[i]) :
|
|
4096
|
-
continue
|
|
4097
|
-
item=Variant()
|
|
4098
|
-
item.Value, item.Value2 = data, data2[i]
|
|
4099
|
-
drawData[i]=item
|
|
4100
|
-
elif (not isNumber and isNumber2) :
|
|
4101
|
-
if JSComplierHelper.IsNaN(data[i]):
|
|
4102
|
-
continue
|
|
4103
|
-
item=Variant()
|
|
4104
|
-
item.Value, item.Value2 = data[i], data2
|
|
4105
|
-
drawData[i]=item
|
|
4106
|
-
else :
|
|
4107
|
-
if JSComplierHelper.IsNaN(data[i]) or JSComplierHelper.IsNaN(data2[i]) :
|
|
4108
|
-
continue
|
|
4109
|
-
item=Variant()
|
|
4110
|
-
item.Value, item.Value2 = data[i], data2[i]
|
|
4111
|
-
drawData[i]=item
|
|
4112
|
-
else :
|
|
4113
|
-
drawData=JSComplierHelper.CreateArray(len(condition))
|
|
4114
|
-
for i in range(len(condition)) :
|
|
4115
|
-
if JSComplierHelper.IsNaN(condition[i]) or not condition[i] :
|
|
4116
|
-
continue
|
|
4117
|
-
|
|
4118
|
-
if isNumber and isNumber2 :
|
|
4119
|
-
item=Variant()
|
|
4120
|
-
item.Value, item.Value2 = data, data2
|
|
4121
|
-
drawData[i]=item
|
|
4122
|
-
elif (isNumber and not isNumber2) :
|
|
4123
|
-
if JSComplierHelper.IsNaN(data2[i]) :
|
|
4124
|
-
continue
|
|
4125
|
-
item=Variant()
|
|
4126
|
-
item.Value, item.Value2 = data, data2[i]
|
|
4127
|
-
drawData[i]=item
|
|
4128
|
-
elif (not isNumber and isNumber2) :
|
|
4129
|
-
if JSComplierHelper.IsNaN(data[i]) :
|
|
4130
|
-
continue
|
|
4131
|
-
item=Variant()
|
|
4132
|
-
item.Value, item.Value2 = data[i], data2
|
|
4133
|
-
drawData[i]=item
|
|
4134
|
-
else :
|
|
4135
|
-
if JSComplierHelper.IsNaN(data[i]) or JSComplierHelper.IsNaN(data2[i]) :
|
|
4136
|
-
continue
|
|
4137
|
-
item=Variant()
|
|
4138
|
-
item.Value, item.Value2 = data[i], data2[i]
|
|
4139
|
-
drawData[i]=item
|
|
4140
|
-
|
|
4141
|
-
result.DrawData=drawData
|
|
4142
|
-
return result
|
|
4143
|
-
|
|
4144
|
-
|