代码拉取完成,页面将自动刷新
同步操作将从 jack/缠论程序化交易系统 强制同步,此操作会覆盖自 Fork 仓库以来所做的任何修改,且无法恢复!!!
确定后同步将在后台操作,完成时将刷新页面,请耐心等待。
clear;clc;
%1. import dataset
assetFull = readtable('windA.xlsx');
%assetFull = assetFull(400:end,:);
%assetFull = flip(assetFull); %如果数据倒过来
%assetFull = assetFull(6000:end,:);
%assetFull = renamevars(assetFull, ["Adj_Close"], ["AdjClose"]); %change variable names
Average = (assetFull.Close + assetFull.High + assetFull.Low + assetFull.Open) ./ 4;
assetFull.Average = Average;%加入均价
tc = 0.003;
% 顶底扫描定位函数
asset = assetFull;
asset.Date = datenum(asset.Date);
asset = table2array(asset);
%third column High
%fourth column Low
%因为数据开头如果有包含关系的话
%无从检查 j - 1 的上升下降关系,去掉
x = 1;
Needcheck = true;
tempHigh = asset(:, 3);
tempLow = asset(:, 4);
while Needcheck %如果 true 就一直检查
nCurrTop = tempHigh(x);
nNextTop = tempHigh(x + 1);
nCurrBot = tempLow(x);
nNextBot = tempLow(x + 1);
if nCurrTop >= nNextTop && nCurrBot <= nNextBot || ...
nCurrTop <= nNextTop && nCurrBot >= nNextBot
Needcheck = false; %停止检查
else
x = x + 1;
end
end
if x == 1 %如果第一根和第二根有包含关系,去掉第一根
asset(1, :) = [];
end
j = 1;
while j <= size(asset, 1) - 2
%先检查是否有包含关系
Needcheck = true;
tempHigh = asset(:, 3);
tempLow = asset(:, 4);
j = 1;
while Needcheck %如果 true 就一直检查
nCurrTop = tempHigh(j);
nNextTop = tempHigh(j + 1);
nCurrBot = tempLow(j);
nNextBot = tempLow(j + 1);
if nCurrTop >= nNextTop && nCurrBot <= nNextBot || ...
nCurrTop <= nNextTop && nCurrBot >= nNextBot
Needcheck = false; %停止检查
elseif j == size(asset, 1) - 1 %如果检查到数据末尾都没问题
Needcheck = false; %停止检查
else %如果没到数据末尾,也没有包含关系
j = j + 1; %继续检查
end
end
%包含关系 while loop 在两个条件下会退出
%1. 还有包含关系
%2. 到数据末尾了还没有包含关系
%如果1 => 在退出 while loop 的位置 => j 和 j + 1 之间有包含关系
%查看 j - 1 和 j 的上升下降关系
if ~Needcheck && j ~= size(asset, 1) - 1
if asset(j - 1, 3) <= asset(j, 3) && ...
asset(j - 1, 4) <= asset(j, 4) %如果是上升关系
%如果向上包含,取两K线中高点最高为高点,低点最高为低点
Top1 = asset(j, 3);
Top2 = asset(j + 1, 3);
Bot1 = asset(j, 4);
Bot2 = asset(j + 1, 4);
if Top1 >= Top2 && Bot1 <= Bot2 || ...
Top2 >= Top1 && Bot2 <= Bot1 %如果有包含关系
asset(j + 1, 3) = max(asset(j, 3), asset(j + 1, 3));
asset(j + 1, 4) = max(asset(j, 4), asset(j + 1, 4));
asset(j, :) = []; %只合并第三根K线,第二根去掉
end
elseif asset(j - 1, 3) >= asset(j, 3) && ...
asset(j - 1, 4) >= asset(j, 4) %如果是下降关系
%如果向下包含,取两K线中高点最低为高点,低点最低为低点
Top1 = asset(j, 3);
Top2 = asset(j + 1, 3);
Bot1 = asset(j, 4);
Bot2 = asset(j + 1, 4);
if Top1 >= Top2 && Bot1 <= Bot2 || ...
Top2 >= Top1 && Bot2 <= Bot1 %如果有包含关系
asset(j + 1, 3) = min(asset(j, 3), asset(j + 1, 3));
asset(j + 1, 4) = min(asset(j, 4), asset(j + 1, 4));
asset(j, :) = []; %只合并第三根K线,第二根去掉
end
end
end
end
check = NaN(size(asset, 1), 1);
for i = 1 : size(asset, 1) - 1
Top1 = asset(i, 3);
Top2 = asset(i + 1, 3);
Bot1 = asset(i, 4);
Bot2 = asset(i + 1, 4);
if Top1 >= Top2 && Bot1 <= Bot2 || ...
Top2 >= Top1 && Bot2 <= Bot1 %如果有包含关系
check(i) = 1;
end
end
checkResult = find(check == 1);
%修改K线画图
%因为存在处理完最高最低价之后,最高价<开盘价 或者 最低价 > 收盘价 的情况,导致画图错误
asset(:, 2) = asset(:, 4); %收盘价 = 最低价
asset(:, 5) = asset(:, 3); %开盘价 = 最高价
%中枢高点算法模块
nCount = size(asset,1);
nState = -1;
nHigh = 1;
nLow = 1;
pHigh = asset(:, 3);
pLow = asset(:, 4);
pOut = [];
%先找到所有的 Temp 高低点
for i = 1:nCount
%i 为当前位置
%nHigh nLow 为 当前位置左边的第一个顶底分型
% 设定默认输出为零
pOut(i) = 0;
% 寻找高点模式
if nState == 1
% 如果当前最高大于之前最高,更新位置信息
if (pHigh(i) >= pHigh(nHigh))
pOut(nHigh) = 0;
nHigh = i;
pOut(nHigh) = 1;
end
% 确认转向(当前最高价 < 顶分型最高价 并且 当前最低价 < 顶分型最低价)
% 上升趋势 转向 下降趋势
if ((pHigh(i) < pHigh(nHigh)) && (pLow(i) < pLow(nHigh)))
pOut(nHigh) = 1;
nState = -1;
nLow = i;
end
% 寻找低点模式
elseif nState == -1
% 如果当前最低小于之前最低,更新位置信息
if (pLow(i) <= pLow(nLow))
pOut(nLow) = 0;
nLow = i;
pOut(nLow) = -1;
end
% 确认转向(当前最低价 > 底分型最低价 并且 当前最高价 > 底分型最高价)
% 下降趋势 转向 上升趋势
if ((pLow(i) > pLow(nLow)) && (pHigh(i) > pHigh(nLow)))
pOut(nLow) = -1;
nState = 1;
nHigh = i;
end
end
end
%画笔
%处理数据头部
%手动找到第一个能够确认趋势的actual point
%和之后的一个 temp point
t = 2;
tempPos = find(pOut ~= 0); %找到所有分型位置
while tempPos(t) - tempPos(t - 1) < 4
%已知pOut中不可能有重复的分型
%如果后一个分型和前一个分型之间距离 < 4
%就继续 while loop
t = t + 1;
end
ActualstartPos = tempPos(t - 1); %第一个分型位置
ActualstartVal = pOut(ActualstartPos); %第一个分型是顶还是底
if ActualstartVal == 1
pOut(ActualstartPos) = 11;
TempstartPos = ActualstartPos; %寻找之后第一个temp 分型位置
while pOut(TempstartPos) ~= -1
TempstartPos = TempstartPos + 1;
end
pattern = "looking for a top";
else
pOut(ActualstartPos) = -11;
TempstartPos = ActualstartPos;
while pOut(TempstartPos) ~= 1
TempstartPos = TempstartPos + 1;
end
pattern = "looking for a bot";
end
i = TempstartPos; %从第一个之前已经确认actual 的 temp 分型开始
while i < length(pOut)
%该判断pattern框架下会出现在当前已经找到temp 低点(高点)的情况下继续寻找低点(高点)的情况
%该想法虽然比较直观,但是基于程序算法设计 遵循以下原则:
%找到temp低点(高点)的情况下应该立即开始寻找高点(低点),如果出现更低(更高)的低点(高点)即 改正
%而不是主动先去寻找下一个低点(高点)
if pOut(i) == -1 && pattern == "looking for a bot"
pattern = "looking for a top";
elseif pOut(i) == 1 && pattern == "looking for a top"
pattern = "looking for a bot";
end
%如果目前为Temp 低点 并且 为寻找高点模式
if pOut(i) == -1 && pattern == "looking for a top" && i < length(pOut)
j = i + 1;
%当最高价一直为上升趋势时
while pHigh(j) >= pHigh(j - 1) && j < size(asset, 1)
%如果在目前 i 位置的temp低点之后发现一个 temp 高点
if pOut(j) == 1
%计算 j 位置的Temp高点 与 i 位置的Temp低点之间距离
spacing = j - i;
%如果间隔 >= 4
if spacing >= 4
%i 位置的temp低点变成 actual 低点
pOut(i) = -11;
end
end
j = j + 1;
end
%如果上方 while loop 退出时 i 位置为actual 低点
%则 已经找到一个暂时符合要求的temp高点
if pOut(i) == -11
%从找到的 符合要求的 temp 高点开始
%试图找到 符合要求的 temp 低点
pattern = "looking for a top";
i = j - 1;
%如果上方 while loop 退出时 i 位置为temp 低点
%则 i 位置的 temp 低点还不能成为新一笔的开始
%并且 i 位置的 temp 低点右侧 必然有一个 与之距离 < 4 的temp 高点
%并且中间不会有其他的顶或底
else
BotX1 = i;
TopX1 = j - 1;
%处理尾部:如果 i 位置 之后 < 6根 K线就虚线连到最后一根k线的高点
if length(pOut) - BotX1 < 6
pOut(end) = 10; %虚线
end
%处理局部
BotY = TopX1;
while pOut(BotY) ~= -1 && BotY < size(asset, 1)
%找到TopX1 右侧第一个低点
BotY = BotY + 1;
end
TopY = BotY;
while pOut(TopY) ~= 1 && TopY < size(asset, 1)
TopY = TopY + 1;
end
%1. 如果 BotY 左侧满足TopX1 的距离
% 并且 BotY 右侧 不满足 TopY 的距离
%if BotY - TopX1 >= 4 && TopY - BotY < 4
if BotY - TopX1 >= 4
%如果BotY 低点低于 BotX1
if pLow(BotY) <= pLow(BotX1)
%BotX1 的temp 低点取消
pOut(BotX1) = 0;
%BotY 变成目前判断的低点
i = BotY;
%寻找下一个高点,pattern: BotX1 - TopX1
pattern = "looking for a top";
%如果BotY 低点 高于 BotX1
else
%确认BotX1为新生线段的开头
pOut(BotX1) = -11;
%从最近高点 TopY 开始判断
i = TopY;
pattern = "looking for a bot";
end
%2. 如果BotY 左侧以及 右侧都不满足
% 分两种情况
elseif BotY - TopX1 < 4 && TopY - BotY < 4
%2.1 TopY 左侧满足 BotX1 距离
if TopY - BotX1 >= 4
%并且 TopY 低点 > BotX1 低点
%属于正常走势
if pLow(TopY) > pLow(BotX1)
%确认BotX1为新生线段的开头
pOut(BotX1) = -11;
%TopY变成目前判断的高点
i = TopY;
%寻找下一个低点,pattern = "TopX2 - BotX2"
pattern = "looking for a bot";
%如果 TopY 高点 < BotX1 低点 或者 BotY低点 < BotX1低点
%极端走势,跳空低走
elseif pHigh(TopY) < pLow(BotX1) || pLow(BotY) < pLow(BotX1)
pOut(BotX1) = 0;
%pOut(BotY) = -11;
%BotY 变成目前判断的低点
i = BotY;
%寻找下一个高点,pattern = "BotX1 - TopX1"
pattern = "looking for a top";
end
%2.2 TopY 左侧不满足 BotX1 距离
%也就是BotY 左右两侧都不满足距离 且
%BotX1 不满足 TopY
%即:最小级别,在TopY 位置 + 2的k线一定会满足
else
%如果是 U1
%不需要关心最低价的情况因为不存在包含关系
if pHigh(TopY + 2) >= pHigh(TopY + 1) && (TopY + 2) < size(asset, 1)
U1 = TopY + 2;
pOut(BotX1) = -11;
%等U1变成高点之后从U1开始
while pOut(U1) ~= 1 && U1 < size(asset, 1)
U1 = U1 + 1;
end
i = U1;
%如果是 D1
%不需要关心最高价的情况因为不存在包含关系
elseif pLow(TopY + 2) <= pLow(TopY + 1) && (TopY + 2) < size(asset, 1)
D1 = TopY + 2;
pOut(BotX1) = -11;
%等 D1 变成低点之后从D1开始
while pOut(D1) ~= -1 && D1 < size(asset, 1)
D1 = D1 + 1;
end
i = D1;
end
end
%3. 如果BotY 右侧 满足TopY的距离
% 并且BotY 左侧不满足 TopX1 的距离
elseif TopY - BotY >= 4 && BotY - TopX1 < 4
%BoTX1 比较 BotY, 连接低的那个
if pLow(BotX1) <= pLow(BotY)
pOut(BotX1) = -11;
else
pOut(BotY) = -11;
end
%TopY 变成目前判断的高点
i = TopY;
%pattern: = TopX2 - BotX2
pattern = "looking for a bot";
end
end
end
%如果目前为 Temp 高点 并且 为 寻找低点模式
if pOut(i) == 1 && pattern == "looking for a bot" && i < length(pOut)
j = i + 1;
%当最低价一直为下降趋势时
while pLow(j) <= pLow(j - 1) && j < size(asset, 1)
%如果在目前 i 位置的temp高点之后发现一个 temp 低点
if pOut(j) == -1
%计算 j 位置的 temp低点 与 i 位置的temp 高点之间距离
spacing = j - i;
%如果间隔 >= 4
if spacing >= 4
%i 位置的temp 高点变成actual 高点
pOut(i) = 11;
end
end
j = j + 1;
end
%如果上方while loop 退出时 i 位置为 actual 高点
%则 已经找到一个暂时符合要求的 temp 低点
if pOut(i) == 11
%从找到的 符合要求的 temp低点 开始
%试图找到 符合要求的 temp 高点
pattern = "looking for a bot";
i = j - 1;
%如果上方 while loop 退出时 i 位置为 temp 高点
%则 i 位置的temp 高点 还不能成为 新一笔的开始
%并且 i 位置的 temp 高点右侧 必然有一个 与之距离 < 4 的 temp低点
%并且中间不会有其他的顶或底
else
TopX2 = i;
BotX2 = j - 1;
%处理尾部: 如果 i 位置 之后 < 6 根 K线就虚线连到最后一根k线的低点
if length(pOut) - TopX2 < 6
pOut(end) = -10; %虚线
end
%处理局部
TopY = BotX2;
while pOut(TopY) ~= 1 && TopY < size(asset, 1)
%找到 BotX2 右侧 第一个高点
TopY = TopY + 1;
end
BotY = TopY;
while pOut(BotY) ~= -1 && BotY < size(asset, 1)
BotY = BotY + 1;
end
%1. 如果TopY 左侧满足 BotX2 的距离
% 并且 TopY 右侧 不满足 BotY的距离
%if TopY - BotX2 >= 4 && BotY - TopY < 4
if TopY - BotX2 >= 4
%如果TopY 高点 高于TopX2高点
if pHigh(TopY) >= pHigh(TopX2)
%TopX2 的 temp 低点取消
pOut(TopX2) = 0;
%TopY 变成目前判断的高点
i = TopY;
%寻找下一个低点, pattern: TopX2 - BotX2
pattern = "looking for a bot";
%如果TopY高点 低于 TopX2
else
%确认TopX2为新生线段的开头
pOut(TopX2) = 11;
%从最近低点BotY 开始判断
i = BotY;
pattern = "looking for a top";
end
%2. 如果TopY 左侧以及 右侧 都不满足
% 分两种情况
elseif TopY - BotX2 < 4 && BotY - TopY < 4
%2.1 BotY 左侧满足 TopX2 距离
if BotY - TopX2 >= 4
%并且 BotY 高点 < TopX2 高点
%属于正常走势
if pHigh(BotY) < pHigh(TopX2)
%确认TopX2为新生线段的开头
pOut(TopX2) = 11;
%BotY变成目前判断的低点
i = BotY;
%寻找下一个高点,pattern = "BotX1 - TopX1"
pattern = "looking for a top";
%如果 BotY低点 > TopX2 高点 或者 BotY高点 > TopX2高点
%极端走势,跳空高走
elseif pLow(BotY) > pHigh(TopX2) || pHigh(BotY) > pHigh(TopX2)
pOut(TopX2) = 0;
%pOut(TopY) = 11;
%TopY 变成目前判断的高点
i = TopY;
%寻找下一个低点,pattern = "TopX2 - BotX2"
pattern = "looking for a bot";
end
%2.2 BotY 左侧不满足 TopX2 距离
%也就是 TopY 左右两侧都不满足距离 且
%TopX2 不满足 BotY
%即:最小级别,在BotY的位置 + 2 的k线一定会满足
else
%如果是D2
%不需要关心最高价的情况因为不存在包含关系
if pLow(BotY + 2) <= pLow(BotY + 1) && BotY + 2 < size(asset, 1)
D2 = BotY + 2;
pOut(TopX2) = 11;
%等D2变成低点之后从D2开始
while pOut(D2) ~= -1 && D2 < size(asset, 1)
D2 = D2 + 1;
end
i = D2;
%如果是U2
%不需要关心最低价的情况因为不存在包含关系
elseif pHigh(BotY + 2) >= pHigh(BotY + 1) && BotY + 2 < size(asset, 1)
U2 = BotY + 2;
pOut(TopX2) = 11;
%等 U2变成高点之后从 U2开始
while pOut(U2) ~= 1 && U2 < size(asset, 1)
U2 = U2 + 1;
end
i = U2;
end
end
%3. 如果TopY 右侧满足 BotY的距离
% 并且TopY 左侧不满足 BotX2 的距离
elseif BotY - TopY >= 4 && TopY - BotX2 < 4
%TopX2 比较 TopY, 连接高的那个
if pHigh(TopX2) >= pHigh(TopY)
pOut(TopX2) = 11;
else
pOut(TopY) = 11;
end
%BotY 变成目前判断的低点
i = BotY;
%pattern = BotX1 - TopX1
pattern = "looking for a top";
end
end
end
end
%画笔程序结束后,会有重复的高低点
%基于算法设计:对于 i 以及 i + 1 个高点
%来说,选择 i + 1 个高点
ActualTopPos = find(pOut == 11);
ActualTopPos(2, :) = 11;
ActualBotPos = find(pOut == -11);
ActualBotPos(2, :) = -11;
ActualPos = [ActualTopPos, ActualBotPos];
[B, I] = sort(ActualPos(1, :));
ActualPos(1, :) = B; %第一行位置
ActualPos(2, :) = ActualPos(2, I); %第二行 11 -11 高低点指示
repetition = find(diff(ActualPos(2, :)) == 0);
pOut(ActualPos(1, repetition)) = 0;
%算法设计为事前视角
%加入事后视角修正模块
%针对处理过的 没有重复高低点的pOut数据
%再找一遍actual 高低点
ActualTopPos = find(pOut == 11);
ActualTopPos(2, :) = 11;
ActualBotPos = find(pOut == -11);
ActualBotPos(2, :) = -11;
ActualPos = [ActualTopPos, ActualBotPos];
[B, I] = sort(ActualPos(1, :));
ActualPos(1, :) = B;
ActualPos(2, :) = ActualPos(2, I);
for i = 1 : size(ActualPos, 2) - 2
%假设有 1 2 3 4 5 6 个高低点
%检查顺序为 (123) (234) (345) (456)
if ActualPos(2, i) == 11
%11 -11 11, 查看 -11 是否为区间段内local min
intervalLow = pLow(ActualPos(1, i) : ActualPos(1, i + 2));
localMin = min(intervalLow);
localMinPos = find(localMin == pLow, 1, 'first'); %找到区间内最低价在pOut中的第一个位置,设置第一个防止重复
%如果该 底分型比 local min 要高
if pLow(ActualPos(1, i + 1)) > localMin
%如果该 local min 的位置对于左右两边的 actual top 都满足距离
if localMinPos - ActualPos(1, i) >= 4 && ActualPos(1, i + 2) - localMinPos >= 4
%该 local min成为新的底分型
%去掉原来的底分型
pOut(localMinPos) = -11;
pOut(ActualPos(1, i + 1)) = 0;
end
end
else
%-11 11 -11 查看 11 是否为区间段内的 local max
intervalHigh = pHigh(ActualPos(1, i) : ActualPos(1, i + 2));
localMax = max(intervalHigh);
localMaxPos = find(localMax == pHigh, 1, 'first');
%如果该 顶分型比 local max 要低
if pHigh(ActualPos(1, i + 1)) < localMax
%如果该 local max 的位置对于左右两边 的 actual bot 都满足距离
if localMaxPos - ActualPos(1, i) >= 4 && ActualPos(1, i + 2) - localMaxPos >= 4
%该 local max 成为新的顶分型
%去掉原来的顶分型
pOut(localMaxPos) = 11;
pOut(ActualPos(1, i + 1)) = 0;
end
end
end
end
%处理尾部虚线
if ActualPos(2, end) == -11
if pHigh(end) > pHigh(ActualPos(1, end))
pOut(end) = 10;
end
else
if pLow(end) < pLow(ActualPos(1, end))
pOut(end) = -10;
end
end
%线段
%以向上笔开始的线段的特征序列,只考察顶分型
%以向下笔开始的线段的特征序列,只考察底分型
%线段的构成为 至少 三笔
%对于向上笔开始的线段:上-下-上-下 构成 底 顶 底 顶
%为 d1 - g1 - d2 - g2, 如果之后出现g3 < g2, 那本线段终结
%以 g2 - d3 所构成的向下笔开始构成新的线段
%对于向下笔开始的线段:下-上-下-上 构成 顶 底 顶 底
%为 g1 - d1 - g2 - d2, 如果之后出现 d3 > d2, 那本线段中介
%以 d2 - g3 所构成的向上笔开始构成新的线段
%找到所有的 actual 高低点
ActualTopPos = find(pOut == 11);
ActualTopPos(2, :) = 11;
ActualBotPos = find(pOut == -11);
ActualBotPos(2, :) = -11;
ActualPos = [ActualTopPos, ActualBotPos];
[B, I] = sort(ActualPos(1, :));
ActualPos(1, :) = B;
ActualPos(2, :) = ActualPos(2, I);
SegPos = ActualPos;
if SegPos(2, 1) == 11
%如果第一个actual 为 顶分型
%则第一根线段为下笔开始的线段
CheckingBot = 1;
CheckingTop = 0;
SegPos(2, 1) = 111;
else
%如果第一个actual 为 底分型
%则第一根线段为向上笔开始的线段
CheckingTop = 1;
CheckingBot = 0;
SegPos(2, 1) = -111;
end
i = 1;
d2 = i + 3;
d3 = i + 5;
g2 = i + 3;
g3 = i + 5;
while i < size(SegPos, 2) - 5
%以向下笔开始的线段的特征序列,只考察底分型
if SegPos(2, i) == 111
%只要以向下笔开始的线段没有结束,就一直寻找底分型
while CheckingBot && d2 < size(SegPos, 2) - 5 && d3 < size(SegPos, 2) - 5
%对于向下笔开始的线段:下-上-下-上 构成 顶 底 顶 底
%为 g1 - d1 - g2 - d2
d2 = i + 3;
d3 = i + 5;
nPrevBot = SegPos(1, d2);
nCurrBot = SegPos(1, d3);
%只要底分型一个比一个低,那就继续检查
if pLow(nCurrBot) < pLow(nPrevBot)
i = i + 2;
CheckingBot = 1;
CheckingTop = 0;
else %如果之后出现一个底分型 比之前高, 那本线段终结
CheckingBot = 0;
CheckingTop = 1;
end
end
end
%以 d2 - g3 所构成的向上笔开始构成新的线段
%记录起始点 在 SegPos
SegPos(2, d2) = -111;
if size(SegPos, 2) - d2 > 4
i = d2;
else
break
end
%以向上笔开始的线段的特征序列,只考察顶分型
if SegPos(2, i) == -111
%只要以向上笔开始的线段没有结束,就一支寻找顶分型
while CheckingTop && g2 < size(SegPos, 2) - 5 && g3 < size(SegPos, 2) - 5
%对于向上笔开始的线段:上-下-上-下 构成 底 顶 底 顶
%为 d1 - g1 - d2 - g2
g2 = i + 3;
g3 = i + 5;
nPrevTop = SegPos(1, g2);
nCurrTop = SegPos(1, g3);
%只要顶分型一个比一个高,那就继续检查
if pHigh(nCurrTop) > pHigh(nPrevTop)
i = i + 2;
CheckingTop = 1;
CheckingBot = 0;
else %如果之后出现一个顶分型 比之前高,那本线段终结
CheckingTop = 0;
CheckingBot = 1;
end
end
end
%以 g2 - d3 所构成的向下笔开始构成新的线段
%记录起始点 在 SegPos
SegPos(2, g2) = 111;
if size(SegPos, 2) - g2 > 4
i = g2;
else
break
end
end
%只保留线段高低点
NotSeg = find(SegPos(2, :) == 11 | SegPos(2, :) == -11);
SegPos(:, NotSeg) = [];
% %检查高低点情况
% assetPlot = array2table(asset, 'VariableNames', {'Date','Close','High','Low','Open','Average'});
% figure(2)
% candle(assetPlot);
% hold on
%
% for i = 1 : size(ActualPos, 2) - 1
% x1 = ActualPos(1, i);
% x2 = ActualPos(1, i + 1);
%
% if ActualPos(2, i) == 11%笔高点低点
% y1 = pHigh(x1);
% y2 = pLow(x2);
% line([x1,x2],[y1,y2], 'Color', [0.6350 0.0780 0.1840]);
% else %笔低点高点
% y1 = pLow(x1);
% y2 = pHigh(x2);
% line([x1,x2],[y1,y2], 'Color', [0.6350 0.0780 0.1840]);
% end
% end
%
%
% for i = 1 : size(SegPos, 2) - 1
% x1 = SegPos(1, i);
% x2 = SegPos(1, i + 1);
%
% if SegPos(2, i) == 111 %线段高点低点
% y1 = pHigh(x1);
% y2 = pLow(x2);
% line([x1,x2],[y1,y2], 'Color', [0.8500 0.3250 0.0980]);
% else %线段低点高点
% y1 = pLow(x1);
% y2 = pHigh(x2);
% line([x1,x2],[y1,y2], 'Color', [0.8500 0.3250 0.0980]);
% end
% end
%
% hold off
%
%
%Func2
%中枢高点数据
global Centroid
Centroid = CCentroid;
Centroid_high = NaN(1, size(asset, 1));
for i = 1:nCount - 1
if pOut(i) == 11
%遇到线段高点,推入中枢算法
if PushHigh(i, pHigh(i))
%区段内更新算得的中枢高数据
for j = Centroid.nStart:Centroid.nEnd
Centroid_high(j) = Centroid.fPHigh;
end
end
elseif pOut(i) == -11
%遇到线段低点,推入中枢算法
if PushLow(i, pLow(i))
%区段内更新算得的中枢低数据
for j = Centroid.nStart:Centroid.nEnd
Centroid_high(j) = Centroid.fHigh;
end
end
end
%局部未完成中枢处理
if Centroid.bValid==1 & (Centroid.nLines >= 2) & (i == nCount -1)
for j = Centroid.nStart:nCount-1
Centroid_high(j) = Centroid.fHigh;
end
end
end
%Func3
%中枢低点数据
Centroid_low = NaN(1, size(asset, 1));
for i = 1:nCount - 1
if pOut(i) == 11
%遇到线段高点,推入中枢算法
if PushHigh(i, pHigh(i))
%区段内更新算得得中枢高数据
for j = Centroid.nStart:Centroid.nEnd
Centroid_low(j) = Centroid.fPLow;
end
end
elseif pOut(i) == -11
if PushLow(i, pLow(i))
%区段内更新算得的中枢低数据
for j = Centroid.nStart:Centroid.nEnd
Centroid_low(j) = Centroid.fPLow;
end
end
end
%局部未完成中枢处理
if Centroid.bValid & (Centroid.nLines >= 2) & i == nCount - 1
for j = Centroid.nStart:nCount - 1
Centroid_low(j) = Centroid.fLow;
end
end
end
%Func4
%中枢起点 终点信号 3 = 开始,4 = 结束
Centroid_pos = NaN(1, size(asset, 1));
for i = 1:nCount - 1
if pOut(i) == 11
%遇到线段高点 推入中枢算法
if PushHigh(i,pHigh(i))
%进行标记
Centroid_pos(Centroid.nStart) = 3;
Centroid_pos(Centroid.nEnd) = 4;
end
elseif pOut(i) == -11
%遇到线段低点 推入中枢算法
if PushLow(i,pLow(i))
%进行标记
Centroid_pos(Centroid.nStart) = 3;
Centroid_pos(Centroid.nEnd) = 4;
end
end
%局部未完成中枢处理
if Centroid.bValid & Centroid.nLines >=2 & i == nCount -1
Centroid_pos(Centroid.nStart) = 3;
Centroid_pos(nCount-1) = 4;
end
end
%Func5
%三类买卖点信号
%第三类卖点 13
%第二类卖点 12
%第三类买点 3
%第二类买点 2
%其余都算作0 处理
standard_long_short = zeros(1, size(asset, 1));
for i = 1:nCount - 1
if pOut(i) == 11
if PushHigh(i,pHigh(i))
%第三类卖点信号
standard_long_short(i) = 13;
elseif Centroid.fTop1 < Centroid.fTop2
%第二类卖点信号
standard_long_short(i) = 12;
else
standard_long_short(i) = 0;
end
elseif pOut(i) == -11
if PushLow(i,pLow(i))
%第三类买点信号
standard_long_short(i) = 3;
elseif Centroid.fBot1 > Centroid.fBot2
%第二类买点信号
standard_long_short(i) = 2;
else
standard_long_short(i) = 0;
end
end
end
%Func7
%线段强度分析指标
line_strength = NaN(1, size(asset, 1));
nPrevTop = 1;
nPrevBot = 1;
for i = 2:nCount - 1 %由1开始改成2开始,因为i-1
%遇到线段高点
if pOut(i-1) == 11
%标记高点位置
nPrevTop = i -1;
%遇到线段低点
elseif pOut(i-1) == -11
%标记低点位置
nPrevBot = i -1;
end
%上升线段计算模式
if pOut(i) == 11
%计算上升线段斜率
line_strength(i) = (pHigh(i) - pLow(nPrevBot)) / pLow(nPrevBot) * 100;
elseif pOut(i) == -11
line_strength(i) = (pLow(i) - pHigh(nPrevTop)) / pHigh(nPrevTop) * 100;
end
end
%Func8
%线段斜率分析指标
line_slope = NaN(1, size(asset, 1));
nPrevTop = 1;
nPrevBot = 1;
for i = 2:nCount-1
%遇到线段高点
if pOut(i-1) == 11
%标记高点位置
nPrevTop = i - 1;
%遇到线段低点
elseif pOut(i-1) == -11
%标记低点位置
nPrevBot = i -1;
end
%上升线段计算模式
if pOut(i) == 11
%计算上升线段斜率
line_slope(i) = (pHigh(i) - pLow(nPrevBot)) / (i - nPrevBot);
%下降线段计算模式
elseif pOut(i) == -11
line_slope(i) = (pLow(i) - pHigh(nPrevBot)) / (i - nPrevTop);
end
end
%净值计算:不同买卖点组合测试
%1. standard 二类买卖点
%2. standard 三类买卖点测试
%3. standard 二+三类,不同权重测试
return_index=NaN(size(assetFull,1)-1,1);
return_index(1,1) = 1;
for i=2:size(assetFull,1)
return_index(i,1)=assetFull.Close(i) ./ assetFull.Close(i-1);
end
net_value_index = NaN(size(assetFull,1)-1,1);
net_value_index(1,1) = 1;
for i=2:size(assetFull,1)
net_value_index(i,1) = net_value_index(i-1) * return_index(i);
end
net_value = SingleTimeStandard(asset, assetFull, standard_long_short, 0, 1, tc);
net_value1 = SingleTimeStandard(asset, assetFull, standard_long_short, 1, 0, tc);
net_value2 = SingleTimeStandard(asset, assetFull, standard_long_short, 0.3, 0.7, tc);
net_value3 = SingleTimeStandard(asset, assetFull, standard_long_short, 0.7, 0.3, tc);
net_value4 = SingleTimeStandard(asset, assetFull, standard_long_short, 1, 1, tc);
figure(1);
p1 = plot(net_value);
hold on
p2 = plot(net_value1);
p3 = plot(net_value2);
p4 = plot(net_value3);
p5 = plot(net_value4);
p6 = plot(net_value_index);
hold off
legend([p1 p2 p3 p4 p5, p6], '三类买卖点','二类买卖点','三类买卖点占据主要权重',...
'二类买卖点占据主要权重', '买卖点全部考虑','万得全A日线收益');
title('缠论策略标准二三类买卖点策略对比万得全A日线指数净值')
grid on
%计算相关数据
net_valueDf = transpose([net_value; net_value1; net_value2; net_value3; net_value4; transpose(net_value_index)]);
MaxDrawdown = NaN(6, 1);
AnnualRate = NaN(6, 1);
for i = 1:size(net_valueDf, 2)
MaxDrawdown(i) = maxdrawdown(net_valueDf(:, i));
AnnualRate(i) = (net_valueDf(end, i) / net_valueDf(1, i) - 1) ^ (1 / (size(assetFull, 1) / 244)) - 1;
end
stats = array2table([MaxDrawdown, AnnualRate]);
% stats.Properties.VariableNames = {'最大回撤','年化收益'};
% stats.Properties.RowNames = {'三类买卖点','二类买卖点','三类买卖点占据主要权重',...
% '二类买卖点占据主要权重', '买卖点全部考虑','万得全A日线收益'};
figure(3);
%asset = renamevars(asset, "AdjClose", "Close");
assetPlot = array2table(asset, 'VariableNames', {'Date','Close','High','Low','Open','Average'});
candle(assetPlot);
hold on
%画出标准买卖点
for i = 1:length(standard_long_short)
if standard_long_short(i) == 13
plot(i,pHigh(i), 'o', 'MarkerEdgeColor', 'green');
elseif standard_long_short(i) == 12
plot(i,pHigh(i), 's', 'MarkerEdgeColor', 'green');
elseif standard_long_short(i) == 3
plot(i,pLow(i), 'o', 'MarkerEdgeColor','red');
elseif standard_long_short(i) == 2
plot(i,pLow(i), 's', 'MarkerEdgeColor', 'red');
end
end
%画出中枢
rec_start = find(Centroid_pos == 3);
rec_end = find(Centroid_pos == 4);
rec_pos = sort([rec_start, rec_end]);
for i = 1:2:length(rec_pos)-1
w = rec_pos(i+1) - rec_pos(i);
if w > 3
rectangle('Position', [rec_pos(i), Centroid_low(rec_pos(i)), rec_pos(i+1) - rec_pos(i), ...
Centroid_high(rec_pos(i+1)) - Centroid_low(rec_pos(i+1))], 'EdgeColor', [0.8500 0.3250 0.0980]);
end
end
ActualTopPos = find(pOut == 11);
ActualTopPos(2, :) = 11;
ActualBotPos = find(pOut == -11);
ActualBotPos(2, :) = -11;
ActualPos = [ActualTopPos, ActualBotPos];
[B, I] = sort(ActualPos(1, :));
ActualPos(1, :) = B;
ActualPos(2, :) = ActualPos(2, I);
for i = 1 : size(ActualPos, 2) - 1
x1 = ActualPos(1, i);
x2 = ActualPos(1, i + 1);
if ActualPos(2, i) == 11 %高点低点
y1 = pHigh(x1);
y2 = pLow(x2);
line([x1,x2],[y1,y2], 'Color', [0.6350 0.0780 0.1840]);
else %低点高点
y1 = pLow(x1);
y2 = pHigh(x2);
line([x1,x2],[y1,y2], 'Color', [0.6350 0.0780 0.1840]);
end
end
%画出尾部虚线
x1 = ActualPos(1, end);
x2 = length(pOut);
if ActualPos(2, end) == 11
y1 = pHigh(x1);
y2 = pLow(x2);
l1 = line([x1,x2],[y1,y2], 'Color', [0.6350 0.0780 0.1840]);
l1.LineStyle = '--';
else
y1 = pLow(x1);
y2 = pHigh(x2);
l2 = line([x1,x2],[y1,y2], 'Color', [0.6350 0.0780 0.1840]);
l2.LineStyle = '--';
end
%text(x2,y2, num2str(line_data(i+1,4)));
%画出线段
for i = 1 : size(SegPos, 2) - 1
x1 = SegPos(1, i);
x2 = SegPos(1, i + 1);
if SegPos(2, i) == 111 %线段高点低点
y1 = pHigh(x1);
y2 = pLow(x2);
line([x1,x2],[y1,y2], 'Color', [0.8500 0.3250 0.0980]);
else %线段低点高点
y1 = pLow(x1);
y2 = pHigh(x2);
line([x1,x2],[y1,y2], 'Color', [0.8500 0.3250 0.0980]);
end
end
%画出尾部虚线
x1 = SegPos(1, end);
x2 = length(pOut);
if SegPos(2, end) == 111
y1 = pHigh(x1);
y2 = pLow(x2);
l1 = line([x1,x2],[y1,y2], 'Color', [0.8500 0.3250 0.0980]);
l1.LineStyle = '--';
else
y1 = pLow(x1);
y2 = pHigh(x2);
l2 = line([x1,x2],[y1,y2], 'Color', [0.8500 0.3250 0.0980]);
l2.LineStyle = '--';
end
hold off
title("万得全A日线缠论画图")
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。