提交 c1641cf0 编写于 作者: J jones

ver 6207

上级 fe7eba15
......@@ -93,6 +93,62 @@ class JSComplierHelper:
return result
@staticmethod # result 数组长度由外部创建
def CalculateZIGLine(firstData,secondData,thridData,data,result) :
isUp=secondData.Up
findData=firstData
if (isUp) :
for i in range(firstData.ID+1, thridData.ID) : # 查找最高点
subItem=data[i]
if not JSComplierHelper.IsNumber(subItem) :
continue
if findData.Value<subItem :
findData=Variant()
findData.ID=i
findData.Value=subItem
else :
for i in range(firstData.ID+1, thridData.ID) : #查找最低点
subItem=data[i]
if not JSComplierHelper.IsNumber(subItem) :
continue
if findData.Value>subItem :
findData=Variant()
findData.ID=i
findData.Value=subItem
secondData.Value=findData.Value
secondData.ID=findData.ID
lineCache=Variant()
lineCache.Start, lineCache.End =Variant(), Variant()
lineCache.Start.ID=firstData.ID
lineCache.Start.Value=firstData.Value
lineCache.End.ID=secondData.ID
lineCache.End.Value=secondData.Value
lineData=JSComplierHelper.CalculateDrawLine(lineCache) #计算2个点的线上 其他点的数值
for lineItem in lineData :
result[lineItem.ID]=lineItem.Value
if thridData.ID==data.length-1: # 最后一组数据
# 最后2个点的数据连成线
lineCache=Variant()
lineCache.Start, lineCache.End = Variant(), Variant()
lineCache.Start.ID=secondData.ID
lineCache.Start.Value=secondData.Value
lineCache.End.ID=thridData.ID
lineCache.End.Value=thridData.Value
lineData=JSComplierHelper.CalculateDrawLine(lineCache) # 计算2个点的线上 其他点的数值
for lineItem in lineData :
result[lineItem.ID]=lineItem.Value
else :
firstData.ID=secondData.ID
firstData.Value=secondData.Value
secondData.ID=thridData.ID
secondData.Value=thridData.Value
secondData.Up=firstData.Value < secondData.Value
class Variant:
def __init__(self) :
......
......@@ -2493,6 +2493,160 @@ class JSAlgorithm() :
return result
# 属于未来函数,之字转向.
# 用法: ZIG(K,N),当价格变化量超过N%时转向,K表示0:开盘价,1:最高价,2:最低价,3:收盘价,其余:数组信息
# 例如: ZIG(3,5)表示收盘价的5%的ZIG转向
def ZIG(self,data,n) :
hisData=self.SymbolData.Data
result=[]
if JSComplierHelper.IsNumber(data):
if data==0 :
data=hisData.GetOpen()
elif data==1 :
data=hisData.GetHigh()
elif data==2 :
data=hisData.GetLow()
elif data==3:
data=hisData.GetClose()
else :
return []
bFirstPoint=False
bSecondPont=False
firstData, secondData, thridData = Variant(), Variant(), Variant()
lastData=Variant()
dataLen=len(data)
result=JSComplierHelper.CreateArray(dataLen)
for i in range(dataLen) :
item=data[i]
if not JSComplierHelper.IsNumber(item) :
continue
if bFirstPoint==False :
bFirstPoint=True
firstData.ID=i # 第1个点
firstData.Value=item
elif bFirstPoint==True and bSecondPont==False :
temp=(item-firstData.Value)/firstData.Value*100
if temp>n :
secondData.ID, secondData.Value, secondData.Up= i, item, True
lastData.ID, lastData.Value=i, item
bSecondPont=True
elif temp<-n :
secondData.ID, secondData.Value, secondData.Up =i, item, False
lastData.ID, lastData.Value=i, item
bSecondPont=True
elif bFirstPoint==True and bSecondPont==True :
temp=(item-lastData.Value)/lastData.Value*100
if secondData.Up==True : # 找下跌的点
if temp<-n :
thridData.ID, thridData.Value, thridData.Up =i, item, False
JSComplierHelper.CalculateZIGLine(firstData,secondData,thridData,data,result)
lastData.ID, lastData.Value =i, item
else :
if item>lastData.Value :
lastData.ID, lastData.Value = i, item
else :
if temp>n :
thridData.ID, thridData.Value,thridData.Up = i, item, True
JSComplierHelper.CalculateZIGLine(firstData,secondData,thridData,data,result)
lastData.ID, lastData.Value = i, item
else :
if item<lastData.Value :
lastData.ID, lastData.Value =i, item
# 计算最后1组数据
thridData.ID=data.length-1,
thridData.Value=data[data.length-1],
thridData.Up=not secondData.Up
JSComplierHelper.CalculateZIGLine(firstData,secondData,thridData,data,result)
return result
# 属于未来函数,前M个ZIG转向波谷到当前距离.
# 用法: TROUGHBARS(K,N,M)表示之字转向ZIG(K,N)的前M个波谷到当前的周期数,M必须大于等于1
# 例如: TROUGHBARS(2,5,2)表示%5最低价ZIG转向的前2个波谷到当前的周期数
def TROUGHBARS(self,data,n,n2) :
zigData=self.ZIG(data,n) # 计算ZIG
zigDataLen=len(zigData)
dataLen=len(data)
result=JSComplierHelper.CreateArray(dataLen)
for i in range(len(zigDataLen)) :
if JSComplierHelper.IsNumber(zigData[i]) :
break
trough=JSComplierHelper.CreateArray(dataLen)
start=i
for i in range(i,zigDataLen ) : # 第1个波谷
if (i+1<zigDataLen and i-1>=0 and zigData[i]<zigData[i-1] and zigData[i]<zigData[i+1]) : #波谷
trough[0]=i
break
j=0
for i in range(i+1,zigDataLen) :
if (i+1<zigDataLen and i-1>=0 and zigData[i]<zigData[i-1] and zigData[i]<zigData[i+1]) : # 波谷
# console.log('[TROUGHBARS] i',i,zigData[i]);
j+=1
trough[j]=i
if j+1==n2 :
result[i]=i-start
elif j+1>n2 :
trough.pop(0) # 大于计算的波谷数,去掉第1个波谷
start=trough[0]
j-=1
result[i]=i-start
else :
if j+1==n2 :
result[i]=i-start
return result
# 属于未来函数,前M个ZIG转向波峰到当前距离.
# 用法:
# PEAKBARS(K,N,M)表示之字转向ZIG(K,N)的前M个波峰到当前的周期数,M必须大于等于1
# 例如: PEAKBARS(0,5,1)表示%5开盘价ZIG转向的上一个波峰到当前的周期数
def PEAKBARS(self, data,n,n2) :
zigData=self.ZIG(data,n) # 计算ZIG
zigDataLen=len(zigData)
dataLen=len(data)
result=JSComplierHelper.CreateArray(dataLen)
for i in range(len(zigDataLen)) :
if JSComplierHelper.IsNumber(zigData[i]) :
break
trough=JSComplierHelper.CreateArray(dataLen)
start=i
for i in range(i, zigDataLen) : # 第1个波峰
if (i+1<zigDataLen and i-1>=0 and zigData[i]>zigData[i-1] and zigData[i]>zigData[i+1]) : # 波峰
trough[0]=i
break
j=0
for i in range(i+1, zigDataLen) :
if (i+1<zigDataLen and i-1>=0 and zigData[i]>zigData[i-1] and zigData[i]>zigData[i+1]) : # 波峰
# console.log('[TROUGHBARS] i',i,zigData[i]);
j+=1
trough[j]=i
if j+1==n2 :
result[i]=i-start
elif j+1>n2 :
trough.pop(0) # 大于计算的波谷数,去掉第1个波谷
start=trough[0]
j-=1
result[i]=i-start
else :
if j+1==n2 :
result[i]=i-start
return result
# 函数调用
def CallFunction(self,name,args,node,symbolData=None) :
if name=='MAX':
......@@ -2572,9 +2726,9 @@ class JSAlgorithm() :
elif name=='ZIG':
return self.ZIG(args[0],args[1])
elif name=='TROUGHBARS':
return self.TROUGHBARS(args[0],args[1],args[2])
return self.TROUGHBARS(args[0],args[1],int(args[2]))
elif name=='PEAKBARS':
return self.PEAKBARS(args[0],args[1],args[2])
return self.PEAKBARS(args[0],args[1],int(args[2]))
elif name=='COST':
return self.COST(args[0],node)
elif name=='WINNER':
......
import pandas as pd
import numpy as np
class JSComplierPandasHelper :
@staticmethod # 把指标结果数据转化为pandas格式的时间序列
def ToDateTimeSeries(data) :
result={}
if data.Time : # 分钟K线
aryIndex=[]
for i in range(len(data.Date)) :
date=data.Date[i]
time=data.Time[i]
year, month, day = int(date/10000), int(date%10000/100),int(date%100)
hour, minute= int(time/100), int(time%100)
aryIndex.append(pd.Timestamp(year=year,month=month,day=day,hour=hour, minute=minute))
else : # 日线K线
aryIndex=[]
for item in data.Date :
year, month, day = int(item/10000), int(item%10000/100),int(item%100)
aryIndex.append(pd.Timestamp(year=year,month=month,day=day))
for outItem in data.OutVar :
indexName=outItem.Name
aryValue=[]
for item in outItem.Data:
if item==None :
aryValue.append(np.NaN)
else :
aryValue.append(item)
result[indexName]=pd.Series(aryValue, index=pd.to_datetime(aryIndex))
print('[JSComplierPandasHelper::ToDateTimeSeries] name=' ,indexName)
print(result[indexName])
return result
@staticmethod # 转化为DataFrame格式
def ToDataFrame(data) :
if data.Time : # 分钟K线
aryIndex=[]
for i in range(len(data.Date)) :
date=data.Date[i]
time=data.Time[i]
year, month, day = int(date/10000), int(date%10000/100),int(date%100)
hour, minute= int(time/100), int(time%100)
aryIndex.append(pd.Timestamp(year=year,month=month,day=day,hour=hour, minute=minute))
else : # 日线K线
aryIndex=[]
for item in data.Date :
year, month, day = int(item/10000), int(item%10000/100),int(item%100)
aryIndex.append(pd.Timestamp(year=year,month=month,day=day))
df=pd.DataFrame(index=pd.to_datetime(aryIndex))
for outItem in data.OutVar :
indexName=outItem.Name
aryValue=[]
for item in outItem.Data:
if item==None :
aryValue.append(np.NaN)
else :
aryValue.append(item)
df[indexName]=aryValue
print('[JSComplierPandasHelper::ToDateTimeSeries] dispaly data\n' ,df)
return df
\ No newline at end of file
......@@ -6,6 +6,7 @@ import webbrowser
from umychart_complier_jscomplier import JSComplier, SymbolOption, HQ_DATA_TYPE
from umychart_complier_jscomplier import ScriptIndexConsole, ScriptIndexItem, SymbolOption, RequestOption, HQ_DATA_TYPE, ArgumentItem
from umychart_webtemplate import *
from umychart_complier_pandas_help import JSComplierPandasHelper
class TestCase :
def __init__(self, code, option=SymbolOption()) :
......@@ -279,7 +280,7 @@ def Test_ScriptIndexConsole():
symbol='000001.sz',
right=1, # 复权 0 不复权 1 前复权 2 后复权
period=0, # 周期 0=日线 1=周线 2=月线 3=年线 4=1分钟 5=5分钟 6=15分钟 7=30分钟 8=60分钟
request=RequestOption(maxDataCount=500)
request=RequestOption(maxDataCount=500,maxMinuteDayCount=3)
)
result=indexConsole.ExecuteScript(option)
......@@ -287,6 +288,9 @@ def Test_ScriptIndexConsole():
return
print('run successfully.')
JSComplierPandasHelper.ToDateTimeSeries(result) # 转化为pandas Series 数据格式
JSComplierPandasHelper.ToDataFrame(result) # 转化为pandas DataFrame 数据格式
jsonData=result.ToJson()
varName='jsonData' # 数据变量名字
......
......@@ -948,6 +948,12 @@ function JSChart(divElement)
}
}
this.SaveToImage = function (format,colorGB) //format=保存的文件格式, colorGB=背景色
{
if (this.JSChartContainer && typeof (this.JSChartContainer.SaveToImage) == 'function')
return this.JSChartContainer.SaveToImage(format,colorGB);
}
//事件回调
this.AddEventCallback=function(obj)
{
......@@ -2368,6 +2374,114 @@ function JSChartContainer(uielement)
return false;
}
// 保存图片
this.SaveToImage = function (format,colorGB)
{
if (this.UIElement.width<=0 || this.UIElement.height<=0) return null;
if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash) return null; // 数据加载中不能保存
console.log('[JSChartContainer::SaveToImage]', this.UIElement);
clrBG='rgb(255,255,255)';
if (colorGB) clrBG=colorGB;
this.Canvas.clearRect(0,0,this.UIElement.width,this.UIElement.height);
this.Canvas.fillStyle=clrBG;
this.Canvas.fillRect(0,0,this.UIElement.width,this.UIElement.height); //画一个背景色, 不然是一个黑的背景
var pixelTatio = GetDevicePixelRatio(); //获取设备的分辨率
this.Canvas.lineWidth=pixelTatio; //手机端需要根据分辨率比调整线段宽度
this.Frame.Draw(); //框架
for (var i in this.ChartPaint) //框架内图形
{
var item=this.ChartPaint[i];
if (item.IsDrawFirst)
item.Draw();
}
for(var i in this.ChartPaint)
{
var item=this.ChartPaint[i];
if (!item.IsDrawFirst)
item.Draw();
}
for(var i in this.ChartPaintEx)
{
var item=this.ChartPaintEx[i];
item.Draw();
}
for(var i in this.OverlayChartPaint) //叠加股票
{
var item=this.OverlayChartPaint[i];
item.Draw();
}
for(var i in this.ExtendChartPaint) //固定扩展图形
{
var item=this.ExtendChartPaint[i];
if (!item.IsDynamic && item.IsAnimation==false) item.Draw();
}
if (this.Frame.DrawInsideHorizontal) this.Frame.DrawInsideHorizontal();
this.Frame.DrawLock();
for(var i in this.ExtendChartPaint) //动态扩展图形
{
var item=this.ExtendChartPaint[i];
if (item.IsDynamic && item.DrawAfterTitle===false) item.Draw();
}
if (this.LastPoint.X!=null || this.LastPoint.Y!=null)
{
if (this.ChartCorssCursor) //十字光标不画
{
this.ChartCorssCursor.LastPoint=this.LastPoint;
this.ChartCorssCursor.CursorIndex=this.CursorIndex;
}
}
for(var i in this.TitlePaint)
{
var item=this.TitlePaint[i];
if (!item.IsDynamic) continue;
item.CursorIndex=this.CursorIndex;
item.Draw();
}
for(var i in this.ExtendChartPaint) //动态扩展图形
{
var item=this.ExtendChartPaint[i];
if (item.IsDynamic && item.DrawAfterTitle===true && item.IsAnimation==false) item.Draw();
}
if (this.EnableAnimation)
{
for(var i in this.ExtendChartPaint) //动画
{
var item=this.ExtendChartPaint[i];
if (item.IsAnimation===true) item.Draw();
}
}
for(var i in this.ChartDrawPicture)
{
var item=this.ChartDrawPicture[i];
item.Draw();
}
if (this.CurrentChartDrawPicture && this.CurrentChartDrawPicture.Status!=10)
{
this.CurrentChartDrawPicture.Draw();
}
var dataURL=this.UIElement.toDataURL(format ? format:'image/png', 1.0);
console.log('[JSChartContainer::SaveToImage] data= ', dataURL);
return dataURL;
}
}
function GetDevicePixelRatio()
......
......@@ -948,6 +948,12 @@ function JSChart(divElement)
}
}
this.SaveToImage = function (format,colorGB) //format=保存的文件格式, colorGB=背景色
{
if (this.JSChartContainer && typeof (this.JSChartContainer.SaveToImage) == 'function')
return this.JSChartContainer.SaveToImage(format,colorGB);
}
//事件回调
this.AddEventCallback=function(obj)
{
......@@ -2368,6 +2374,114 @@ function JSChartContainer(uielement)
return false;
}
// 保存图片
this.SaveToImage = function (format,colorGB)
{
if (this.UIElement.width<=0 || this.UIElement.height<=0) return null;
if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash) return null; // 数据加载中不能保存
console.log('[JSChartContainer::SaveToImage]', this.UIElement);
clrBG='rgb(255,255,255)';
if (colorGB) clrBG=colorGB;
this.Canvas.clearRect(0,0,this.UIElement.width,this.UIElement.height);
this.Canvas.fillStyle=clrBG;
this.Canvas.fillRect(0,0,this.UIElement.width,this.UIElement.height); //画一个背景色, 不然是一个黑的背景
var pixelTatio = GetDevicePixelRatio(); //获取设备的分辨率
this.Canvas.lineWidth=pixelTatio; //手机端需要根据分辨率比调整线段宽度
this.Frame.Draw(); //框架
for (var i in this.ChartPaint) //框架内图形
{
var item=this.ChartPaint[i];
if (item.IsDrawFirst)
item.Draw();
}
for(var i in this.ChartPaint)
{
var item=this.ChartPaint[i];
if (!item.IsDrawFirst)
item.Draw();
}
for(var i in this.ChartPaintEx)
{
var item=this.ChartPaintEx[i];
item.Draw();
}
for(var i in this.OverlayChartPaint) //叠加股票
{
var item=this.OverlayChartPaint[i];
item.Draw();
}
for(var i in this.ExtendChartPaint) //固定扩展图形
{
var item=this.ExtendChartPaint[i];
if (!item.IsDynamic && item.IsAnimation==false) item.Draw();
}
if (this.Frame.DrawInsideHorizontal) this.Frame.DrawInsideHorizontal();
this.Frame.DrawLock();
for(var i in this.ExtendChartPaint) //动态扩展图形
{
var item=this.ExtendChartPaint[i];
if (item.IsDynamic && item.DrawAfterTitle===false) item.Draw();
}
if (this.LastPoint.X!=null || this.LastPoint.Y!=null)
{
if (this.ChartCorssCursor) //十字光标不画
{
this.ChartCorssCursor.LastPoint=this.LastPoint;
this.ChartCorssCursor.CursorIndex=this.CursorIndex;
}
}
for(var i in this.TitlePaint)
{
var item=this.TitlePaint[i];
if (!item.IsDynamic) continue;
item.CursorIndex=this.CursorIndex;
item.Draw();
}
for(var i in this.ExtendChartPaint) //动态扩展图形
{
var item=this.ExtendChartPaint[i];
if (item.IsDynamic && item.DrawAfterTitle===true && item.IsAnimation==false) item.Draw();
}
if (this.EnableAnimation)
{
for(var i in this.ExtendChartPaint) //动画
{
var item=this.ExtendChartPaint[i];
if (item.IsAnimation===true) item.Draw();
}
}
for(var i in this.ChartDrawPicture)
{
var item=this.ChartDrawPicture[i];
item.Draw();
}
if (this.CurrentChartDrawPicture && this.CurrentChartDrawPicture.Status!=10)
{
this.CurrentChartDrawPicture.Draw();
}
var dataURL=this.UIElement.toDataURL(format ? format:'image/png', 1.0);
console.log('[JSChartContainer::SaveToImage] data= ', dataURL);
return dataURL;
}
}
function GetDevicePixelRatio()
......
......@@ -948,6 +948,12 @@ function JSChart(divElement)
}
}
this.SaveToImage = function (format,colorGB) //format=保存的文件格式, colorGB=背景色
{
if (this.JSChartContainer && typeof (this.JSChartContainer.SaveToImage) == 'function')
return this.JSChartContainer.SaveToImage(format,colorGB);
}
//事件回调
this.AddEventCallback=function(obj)
{
......@@ -2368,6 +2374,114 @@ function JSChartContainer(uielement)
return false;
}
// 保存图片
this.SaveToImage = function (format,colorGB)
{
if (this.UIElement.width<=0 || this.UIElement.height<=0) return null;
if (this.ChartSplashPaint && this.ChartSplashPaint.IsEnableSplash) return null; // 数据加载中不能保存
console.log('[JSChartContainer::SaveToImage]', this.UIElement);
clrBG='rgb(255,255,255)';
if (colorGB) clrBG=colorGB;
this.Canvas.clearRect(0,0,this.UIElement.width,this.UIElement.height);
this.Canvas.fillStyle=clrBG;
this.Canvas.fillRect(0,0,this.UIElement.width,this.UIElement.height); //画一个背景色, 不然是一个黑的背景
var pixelTatio = GetDevicePixelRatio(); //获取设备的分辨率
this.Canvas.lineWidth=pixelTatio; //手机端需要根据分辨率比调整线段宽度
this.Frame.Draw(); //框架
for (var i in this.ChartPaint) //框架内图形
{
var item=this.ChartPaint[i];
if (item.IsDrawFirst)
item.Draw();
}
for(var i in this.ChartPaint)
{
var item=this.ChartPaint[i];
if (!item.IsDrawFirst)
item.Draw();
}
for(var i in this.ChartPaintEx)
{
var item=this.ChartPaintEx[i];
item.Draw();
}
for(var i in this.OverlayChartPaint) //叠加股票
{
var item=this.OverlayChartPaint[i];
item.Draw();
}
for(var i in this.ExtendChartPaint) //固定扩展图形
{
var item=this.ExtendChartPaint[i];
if (!item.IsDynamic && item.IsAnimation==false) item.Draw();
}
if (this.Frame.DrawInsideHorizontal) this.Frame.DrawInsideHorizontal();
this.Frame.DrawLock();
for(var i in this.ExtendChartPaint) //动态扩展图形
{
var item=this.ExtendChartPaint[i];
if (item.IsDynamic && item.DrawAfterTitle===false) item.Draw();
}
if (this.LastPoint.X!=null || this.LastPoint.Y!=null)
{
if (this.ChartCorssCursor) //十字光标不画
{
this.ChartCorssCursor.LastPoint=this.LastPoint;
this.ChartCorssCursor.CursorIndex=this.CursorIndex;
}
}
for(var i in this.TitlePaint)
{
var item=this.TitlePaint[i];
if (!item.IsDynamic) continue;
item.CursorIndex=this.CursorIndex;
item.Draw();
}
for(var i in this.ExtendChartPaint) //动态扩展图形
{
var item=this.ExtendChartPaint[i];
if (item.IsDynamic && item.DrawAfterTitle===true && item.IsAnimation==false) item.Draw();
}
if (this.EnableAnimation)
{
for(var i in this.ExtendChartPaint) //动画
{
var item=this.ExtendChartPaint[i];
if (item.IsAnimation===true) item.Draw();
}
}
for(var i in this.ChartDrawPicture)
{
var item=this.ChartDrawPicture[i];
item.Draw();
}
if (this.CurrentChartDrawPicture && this.CurrentChartDrawPicture.Status!=10)
{
this.CurrentChartDrawPicture.Draw();
}
var dataURL=this.UIElement.toDataURL(format ? format:'image/png', 1.0);
console.log('[JSChartContainer::SaveToImage] data= ', dataURL);
return dataURL;
}
}
function GetDevicePixelRatio()
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册