代码解释
```mql4
//+------------------------------------------------------------------+
//| ChanTheory_KLine_Full.mq4 |
//| Copyright 2025, Your Name |
//| https://yourwebsite.com/ |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, Your Name"
#property link "https://yourwebsite.com/"
#property version "1.00"
#property strict
// 输入参数
input int MA_Period = 20; // 趋势判断均线周期
input double LotSize = 0.1; // 基础交易手数
input int TakeProfit = 400; // 总体止盈点数
input int ZS_Lookback = 50; // 中枢分析回溯周期
input int MinWaveCount = 3; // 最小波动数量
input int FibPeriod = 50; // 斐波那契计算周期
// 结构体定义
struct ZhongShu {
double high;
double low;
datetime startTime;
datetime endTime;
int waveCount; // 包含的波动数量
};
ZhongShu currentZS; // 当前中枢
int trendDirection = 0; // 趋势方向:0-震荡, 1-上涨, -1-下跌
// 函数声明
double CalculateFibonacciLevel(int fibPeriod, double levelRatio);
bool IdentifyZhongShu();
void DetermineTrend();
double GetAvgVolume(int period);
int CheckBuyPoint();
int CheckSellPoint();
// K线形态函数声明
bool IsYouHaoFanGong(int lookback = 1);
bool IsShuGuangChuXian(int lookback = 1);
bool IsXuRiDongSheng(int lookback = 1);
bool IsPingDi(int lookback = 2);
bool IsTaXingChuDi(int lookback = 5);
bool IsBeiZhuangDi(int lookback = 20);
bool IsHongSanBing(int lookback = 3);
bool IsSheJiZhiXian(int lookback = 1);
bool IsPingDing(int lookback = 1);
bool IsTaXingDing(int lookback = 5);
bool IsDanYouFanGong(int lookback = 1);
bool IsSanZhiWuYa(int lookback = 3);
bool IsHeiSanBing(int lookback = 3);
bool IsMianMianYinDie(int lookback = 5);
bool IsDiaoJingXian(int lookback = 1);
bool IsGaoWeiChuTao(int lookback = 1);
bool IsGraveyardDoji(int lookback = 1);
bool IsDarkCloudCover(int lookback = 1);
bool IsEveningStar(int lookback = 2);
bool IsBigBearEngulfing(int lookback = 1);
bool IsDojiReversal(int lookback = 1);
bool IsSymmetricalTriangle(int lookback = 5);
bool IsAscendingTriangle(int lookback = 5);
bool IsDescendingTriangle(int lookback = 5);
bool IsFlagPattern(int lookback = 5);
bool IsRisingWedge(int lookback = 5);
bool IsFallingWedge(int lookback = 5);
bool IsRectangleRange(int lookback = 5);
bool IsTweezerBottom(int lookback = 1);
bool IsBullishEngulfing(int lookback = 1);
bool IsHarami(int lookback = 1);
bool IsPiercingLinePlus(int lookback = 1);
bool IsHopefulStar(int lookback = 2);
bool IsThreeLineStrike(int lookback = 3);
bool IsUpsideTasukiGap(int lookback = 2);
bool IsInNeckLine(int lookback = 1);
bool IsFakeoutSupport(int lookback = 1);
bool IsTweezerTop(int lookback = 1);
bool IsBearishEngulfing(int lookback = 1);
bool IsDarkCloudHarami(int lookback = 1);
bool IsDownsideTasukiGap(int lookback = 2);
bool IsCounterattackLine(int lookback = 1);
bool IsDeliberationPattern(int lookback = 3);
bool IsShootingStarLine(int lookback = 1);
bool IsDojiWithVolumeDrop(int lookback = 1);
bool IsFakeoutResistance(int lookback = 1);
bool IsRisingThreeMethods(int lookback = 5);
bool IsFallingThreeMethods(int lookback = 5);
// 辅助函数
bool GetHighArray(double &highs[], int count = 5) {
ArraySetAsSeries(highs, true);
return (CopyHigh(_Symbol, _Period, 0, count, highs) == count);
}
bool GetLowArray(double &lows[], int count = 5) {
ArraySetAsSeries(lows, true);
return (CopyLow(_Symbol, _Period, 0, count, lows) == count);
}
bool IsFlatTop(double &array[], int lookback = 5) {
for (int i = 1; i < lookback; i++) {
if (MathAbs(array[i] - array[i+1]) > Point * 5)
return false;
}
return true;
}
bool IsFlatBottom(double &array[], int lookback = 5) {
for (int i = 1; i < lookback; i++) {
if (MathAbs(array[i] - array[i+1]) > Point * 5)
return false;
}
return true;
}
bool IsNarrowRange(double &highs[], double &lows[], int lookback = 5) {
double avgRange = 0;
for (int i = 1; i <= lookback; i++) {
avgRange += highs[i] - lows[i];
}
avgRange /= lookback;
return ((highs[0] - lows[0]) < avgRange * 0.6);
}
int TrendLength(double &prices[], int lookback = 20) {
int count = 0;
for (int i = 1; i <= lookback; i++) {
if (prices[i] > prices[i+1]) count++;
else break;
}
return count;
}
// 自定义斐波那契回撤计算函数
double CalculateFibonacciLevel(int fibPeriod, double levelRatio) {
int startBar = 1;
int endBar = fibPeriod;
double maxHigh = -1;
double minLow = 999999;
for (int i = startBar; i <= endBar; i++) {
if (High[i] > maxHigh) maxHigh = High[i];
if (Low[i] < minLow) minLow = Low[i];
}
double range = maxHigh - minLow;
return maxHigh - range * levelRatio;
}
// 改进的中枢识别函数
bool IdentifyZhongShu() {
currentZS.high = -999999;
currentZS.low = 999999;
currentZS.startTime = 0;
currentZS.endTime = 0;
currentZS.waveCount = 0;
double highs[], lows[];
ArraySetAsSeries(highs, true);
ArraySetAsSeries(lows, true);
if(CopyHigh(_Symbol, _Period, 0, ZS_Lookback, highs) < ZS_Lookback)
return false;
if(CopyLow(_Symbol, _Period, 0, ZS_Lookback, lows) < ZS_Lookback)
return false;
bool inOverlap = false;
int overlapStart = 0;
int waveCounter = 0;
int i;
for(i = 4; i < ZS_Lookback; i++) {
double currentHigh = highs[i];
double currentLow = lows[i];
bool hasOverlap = true;
double overlapHigh = currentHigh;
double overlapLow = currentLow;
for(int j = 1; j <= 4; j++) {
if(highs[i-j] < overlapLow || lows[i-j] > overlapHigh) {
hasOverlap = false;
break;
}
overlapHigh = MathMin(overlapHigh, highs[i-j]);
overlapLow = MathMax(overlapLow, lows[i-j]);
}
if(hasOverlap) {
if(!inOverlap) {
inOverlap = true;
overlapStart = i;
}
currentZS.high = MathMax(currentZS.high, overlapHigh);
currentZS.low = MathMin(currentZS.low, overlapLow);
currentZS.endTime = iTime(_Symbol, _Period, i-4);
waveCounter++;
} else {
if(inOverlap) {
inOverlap = false;
currentZS.startTime = iTime(_Symbol, _Period, overlapStart);
currentZS.waveCount = waveCounter;
break;
}
}
}
return (currentZS.waveCount >= MinWaveCount);
}
// 改进的趋势判断函数
void DetermineTrend() {
double maCurrent = iMA(_Symbol, _Period, MA_Period, 0, MODE_EMA, PRICE_CLOSE, 0);
double maPrev = iMA(_Symbol, _Period, MA_Period, 0, MODE_EMA, PRICE_CLOSE, 1);
double price = Close[0];
if(price > maCurrent && maCurrent > maPrev) {
trendDirection = 1;
} else if(price < maCurrent && maCurrent < maPrev) {
trendDirection = -1;
} else {
trendDirection = 0;
}
}
// 获取平均成交量
double GetAvgVolume(int period) {
double sum = 0;
for (int i = 1; i <= period; i++) {
sum += (double)Volume[i];
}
return sum / period;
}
// 缠论三类买点判断
int CheckBuyPoint() {
double close0 = Close[0], close1 = Close[1], close2 = Close[2];
double high0 = High[0], high1 = High[1], high2 = High[2];
double low0 = Low[0], low1 = Low[1], low2 = Low[2];
double ema50 = iMA(NULL, 0, 50, 0, MODE_EMA, PRICE_CLOSE, 0);
double ema200 = iMA(NULL, 0, 200, 0, MODE_EMA, PRICE_CLOSE, 0);
bool isBullishEMA = (ema50 > ema200);
double macdMain0 = iMACD(NULL, 0, 12, 26, 9, PRICE_CLOSE, MODE_MAIN, 0);
double hist0 = macdMain0 - iMACD(NULL, 0, 12, 26, 9, PRICE_CLOSE, MODE_SIGNAL, 0);
double hist1 = iMACD(NULL, 0, 12, 26, 9, PRICE_CLOSE, MODE_MAIN, 1) - iMACD(NULL, 0, 12, 26, 9, PRICE_CLOSE, MODE_SIGNAL, 1);
bool bullishDivergence = (low0 < low1 && hist0 > hist1 && hist0 < 0);
double rsi0 = iRSI(NULL, 0, 14, PRICE_CLOSE, 0);
double rsi1 = iRSI(NULL, 0, 14, PRICE_CLOSE, 1);
bool isRSIOversold = (rsi0 < 30);
double lowerBand = iBands(NULL, 0, 20, 2, 0, PRICE_CLOSE, MODE_LOWER, 0);
bool isPriceBelowLower = (close0 < lowerBand);
double fiboLevel = CalculateFibonacciLevel(FibPeriod, 0.618);
bool isPriceAtFibo = (close0 < fiboLevel);
bool isZSConfirmed = (currentZS.waveCount >= MinWaveCount);
double obv0 = iOBV(NULL, 0, PRICE_CLOSE, 0);
double obv1 = iOBV(NULL, 0, PRICE_CLOSE, 1);
bool isOBVRising = (obv0 > obv1);
double supportLevel = iLowest(NULL, 0, MODE_LOW, 20, 0);
bool isBreakoutSupport = (close0 > supportLevel && close1 <= supportLevel);
bool consolidationAboveZS = (low0 > currentZS.low && low1 > currentZS.low && low2 > currentZS.low);
if(trendDirection == -1 &&
close1 < currentZS.low &&
close0 > currentZS.low &&
low0 > low1 &&
bullishDivergence &&
isRSIOversold &&
isPriceBelowLower &&
isBullishEMA &&
isZSConfirmed &&
isOBVRising &&
isBreakoutSupport)
{
return 1;
}
if(trendDirection == 1 &&
low0 > currentZS.low &&
low1 > currentZS.low &&
low0 > low2 &&
close0 > ema50 &&
isBullishEMA &&
isZSConfirmed &&
isOBVRising)
{
return 2;
}
if(close2 > currentZS.high &&
close1 < currentZS.high &&
close0 > currentZS.high &&
close0 > high1 &&
close0 > iHighest(NULL, 0, MODE_HIGH, 20, 0) &&
isPriceAtFibo &&
isBullishEMA &&
isZSConfirmed &&
consolidationAboveZS)
{
return 3;
}
return 0;
}
// 新增的三类卖点判断
int CheckSellPoint() {
double close0 = Close[0], close1 = Close[1], close2 = Close[2];
double high0 = High[0], high1 = High[1], high2 = High[2];
double low0 = Low[0], low1 = Low[1], low2 = Low[2];
double ema50 = iMA(NULL, 0, 50, 0, MODE_EMA, PRICE_CLOSE, 0);
double ema200 = iMA(NULL, 0, 200, 0, MODE_EMA, PRICE_CLOSE, 0);
bool isBearishEMA = (ema50 < ema200);
double macdMain0 = iMACD(NULL, 0, 12, 26, 9, PRICE_CLOSE, MODE_MAIN, 0);
double hist0 = macdMain0 - iMACD(NULL, 0, 12, 26, 9, PRICE_CLOSE, MODE_SIGNAL, 0);
double hist1 = iMACD(NULL, 0, 12, 26, 9, PRICE_CLOSE, MODE_MAIN, 1) - iMACD(NULL, 0, 12, 26, 9, PRICE_CLOSE, MODE_SIGNAL, 1);
bool bearishDivergence = (high0 > high1 && hist0 < hist1 && hist0 > 0);
double rsi0 = iRSI(NULL, 0, 14, PRICE_CLOSE, 0);
double rsi1 = iRSI(NULL, 0, 14, PRICE_CLOSE, 1);
bool isRSIOverbought = (rsi0 > 70);
double upperBand = iBands(NULL, 0, 20, 2, 0, PRICE_CLOSE, MODE_UPPER, 0);
bool isPriceAboveUpper = (close0 > upperBand);
bool isZSConfirmed = (currentZS.waveCount >= MinWaveCount);
double resistanceLevel = iHighest(NULL, 0, MODE_HIGH, 20, 0);
bool isFailedResistance = (close0 < resistanceLevel && close1 >= resistanceLevel);
bool consolidationBelowZS = (high0 < currentZS.low && high1 < currentZS.low && high2 < currentZS.low);
if(trendDirection == 1 &&
close1 > currentZS.high &&
close0 < currentZS.high &&
high0 < high1 &&
bearishDivergence &&
isRSIOverbought &&
isPriceAboveUpper &&
isBearishEMA &&
isZSConfirmed &&
isFailedResistance &&
consolidationBelowZS)
{
return 1;
}
if(trendDirection == -1 &&
high0 < currentZS.high &&
high1 < currentZS.high &&
high0 < high2 &&
close0 < ema50 &&
isBearishEMA &&
isZSConfirmed &&
consolidationBelowZS)
{
return 2;
}
if(close2 < currentZS.low &&
close1 > currentZS.low &&
close0 < currentZS.low &&
close0 < low1 &&
close0 < iLowest(NULL, 0, MODE_LOW, 20, 0) &&
isZSConfirmed &&
consolidationBelowZS)
{
return 3;
}
return 0;
}
// 动态止盈与最大回撤管理函数
void ManageTrades() {
double atr = iATR(NULL, 0, 14, 0);
double drawdownThreshold = 50 * Point;
double trailingStopDistance = 2 * atr;
for (int i = 0; i < OrdersTotal(); i++) {
if (!OrderSelect(i, SELECT_BY_POS)) continue;
if (OrderSymbol() != Symbol()) continue;
double orderType = OrderType();
double openPrice = OrderOpenPrice();
double currentPrice = (orderType == OP_BUY) ? Bid : Ask;
double profitPoints = (orderType == OP_BUY)
? (currentPrice - openPrice) / Point
: (openPrice - currentPrice) / Point;
double sl = OrderStopLoss();
double newSl = 0;
if (profitPoints > TakeProfit * 0.2) {
if (orderType == OP_BUY) {
newSl = currentPrice - trailingStopDistance;
if ((Bid - sl) / Point < -drawdownThreshold) {
if (!OrderClose(OrderTicket(), OrderLots(), Bid, 3, Red))
Print("多单关闭失败,错误码: ", GetLastError());
else
Print("多单因最大回撤关闭");
continue;
}
} else {
newSl = currentPrice + trailingStopDistance;
if ((sl - Ask) / Point < -drawdownThreshold) {
if (!OrderClose(OrderTicket(), OrderLots(), Ask, 3, Red))
Print("空单关闭失败,错误码: ", GetLastError());
else
Print("空单因最大回撤关闭");
continue;
}
}
if (newSl != sl && newSl > 0) {
if (!OrderModify(OrderTicket(), OrderOpenPrice(), newSl, OrderTakeProfit(), 0, clrGreen))
Print("止损更新失败,错误码: ", GetLastError());
}
}
}
}
// 执行多头交易函数
void ExecuteTrade(int signal) {
double entryPrice = Ask;
double sl = entryPrice - iATR(NULL, 0, 14, 0) * 2;
double tp = entryPrice + TakeProfit * Point;
double dynamicLot = CalculateDynamicLotSize();
int ticket = OrderSend(Symbol(), OP_BUY, dynamicLot, entryPrice, 3, sl, tp, "Chan"+IntegerToString(signal), 0, 0, Green);
if(ticket < 0) {
Print("多单开仓失败,错误码: ", GetLastError());
}
}
// 执行空头交易函数
void ExecuteShortTrade(int signal) {
double entryPrice = Bid;
double sl = entryPrice + iATR(NULL, 0, 14, 0) * 2;
double tp = entryPrice - TakeProfit * Point;
double dynamicLot = CalculateDynamicLotSize();
int ticket = OrderSend(Symbol(), OP_SELL, dynamicLot, entryPrice, 3, sl, tp, "Chan_Sell"+IntegerToString(signal), 0, 0, Red);
if(ticket < 0) {
Print("空单开仓失败,错误码: ", GetLastError());
}
}
// 智能仓位管理
double CalculateDynamicLotSize(double riskPercent = 1.0) {
double accountRisk = AccountBalance() * riskPercent / 100;
double lotSize = MathMin(LotSize, accountRisk / (iATR(NULL, 0, 14, 0) * MarketInfo(Symbol(), MODE_TICKVALUE)));
return NormalizeDouble(lotSize, 2);
}
// K线形态函数实现
bool IsYouHaoFanGong(int lookback = 1) {
return (Close[lookback] < Open[lookback] && Close[0] > Open[0] &&
Close[0] == Open[lookback] && Open[0] == Close[lookback]);
}
bool IsShuGuangChuXian(int lookback = 1) {
return (Close[lookback] < Open[lookback] && Close[0] > Open[0] &&
Close[0] > (Open[lookback] + Close[lookback]) / 2 &&
Close[0] < Open[lookback]);
}
bool IsXuRiDongSheng(int lookback = 1) {
return (Close[lookback] < Open[lookback] && Close[0] > Open[0] &&
Close[0] > Open[lookback]);
}
bool IsPingDi(int lookback = 2) {
return (Low[lookback] == Low[lookback + 1] && MathAbs(Close[lookback] - Open[lookback]) < Point * 5);
}
bool IsTaXingChuDi(int lookback = 5) {
for (int i = 0; i < lookback; i++) {
if (High[i] < High[i+1] && Low[i] > Low[i+1]) continue;
else return false;
}
return true;
}
bool IsBeiZhuangDi(int lookback = 20) {
double min = Low[lookback];
int mid = lookback / 2;
return (Low[0] > min && Low[mid] < min && Low[lookback] > min);
}
bool IsHongSanBing(int lookback = 3) {
return (Close[lookback] > Open[lookback] && Close[lookback-1] > Open[lookback-1] && Close[lookback-2] > Open[lookback-2]);
}
bool IsSheJiZhiXian(int lookback = 1) {
return (Close[lookback] < Open[lookback] && Close[0] == Low[0] && MathAbs(High[0] - Low[0]) > Point * 10);
}
bool IsPingDing(int lookback = 1) {
return (High[lookback] == High[lookback + 1] && MathAbs(Close[lookback] - Open[lookback]) < Point * 5);
}
bool IsTaXingDing(int lookback = 5) {
for (int i = 0; i < lookback; i++) {
if (High[i] > High[i+1] && Low[i] < Low[i+1]) continue;
else return false;
}
return true;
}
bool IsDanYouFanGong(int lookback = 1) {
return (Close[lookback] > Open[lookback] && Close[0] < Open[0] &&
Close[0] == Open[lookback] && Open[0] == Close[lookback]);
}
bool IsSanZhiWuYa(int lookback = 3) {
return (Close[lookback] < Open[lookback] && Close[lookback-1] < Open[lookback-1] && Close[lookback-2] < Open[lookback-2]);
}
bool IsHeiSanBing(int lookback = 3) {
return (Close[lookback] < Open[lookback] && Close[lookback-1] < Open[lookback-1] && Close[lookback-2] < Open[lookback-2]);
}
bool IsMianMianYinDie(int lookback = 5) {
for (int i = 0; i < lookback; i++) {
if (Close[i] < Open[i]) continue;
else return false;
}
return true;
}
bool IsDiaoJingXian(int lookback = 1) {
return (Close[lookback] > Open[lookback] && Close[0] == Low[0] && MathAbs(High[0] - Low[0]) > Point * 10);
}
bool IsGaoWeiChuTao(int lookback = 1) {
return (High[lookback] > iHighest(NULL, 0, MODE_HIGH, 20, 0) && Close[0] < Open[0]);
}
bool IsGraveyardDoji(int lookback = 1) {
return (MathAbs(Close[0] - Open[0]) < Point * 3 && High[0] == Close[0] && Low[0] < Close[0] - Point * 10);
}
bool IsDarkCloudCover(int lookback = 1) {
return (Close[lookback] > Open[lookback] && Close[0] < Open[0] &&
Close[0] < Open[lookback] && Close[0] > (Open[lookback] + Close[lookback]) / 2);
}
bool IsEveningStar(int lookback = 2) {
return (Close[lookback] > Open[lookback] && MathAbs(Close[lookback-1] - Open[lookback-1]) < Point * 3 &&
Close[0] < Open[0] && Close[0] < (Open[lookback] + Close[lookback]) / 2);
}
bool IsBigBearEngulfing(int lookback = 1) {
return (Close[lookback] > Open[lookback] && Close[0] < Open[0] && Close[0] < Open[lookback] && Close[0] < Close[lookback]);
}
bool IsDojiReversal(int lookback = 1) {
return (MathAbs(Close[lookback] - Open[lookback]) > Point * 10 && MathAbs(Close[0] - Open[0]) < Point * 3);
}
bool IsSymmetricalTriangle(int lookback = 5) {
double highs[];
if (!GetHighArray(highs, lookback)) return false;
double lows[];
if (!GetLowArray(lows, lookback)) return false;
bool higherHighs = true, lowerLows = true;
for (int i = 1; i < lookback; i++) {
if (highs[i] <= highs[i+1]) higherHighs = false;
if (lows[i] >= lows[i+1]) lowerLows = false;
}
return (higherHighs && lowerLows);
}
bool IsAscendingTriangle(int lookback = 5) {
double lows[];
if (!GetLowArray(lows, lookback)) return false;
bool higherLows = true;
for (int i = 1; i < lookback; i++) {
if (lows[i] <= lows[i+1]) higherLows = false;
}
double highs[];
if (!GetHighArray(highs, lookback)) return false;
return (IsFlatTop(highs) && higherLows);
}
bool IsDescendingTriangle(int lookback = 5) {
double highs[];
if (!GetHighArray(highs, lookback)) return false;
bool lowerHighs = true;
for (int i = 1; i < lookback; i++) {
if (highs[i] >= highs[i+1]) lowerHighs = false;
}
double lows[];
if (!GetLowArray(lows, lookback)) return false;
return (IsFlatBottom(lows) && lowerHighs);
}
bool IsFlagPattern(int lookback = 5) {
double highs[], lows[];
if (!GetHighArray(highs, lookback) || !GetLowArray(lows, lookback))
return false;
double prevHighs[20];
if (!GetHighArray(prevHighs, lookback * 2)) return false;
bool narrowRange = IsNarrowRange(highs, lows, lookback);
bool trend = TrendLength(prevHighs, lookback * 2) > lookback;
return (narrowRange && trend);
}
bool IsRisingWedge(int lookback = 5) {
double highs[];
if (!GetHighArray(highs, lookback)) return false;
bool risingHighs = true;
for (int i = 1; i < lookback; i++) {
if (highs[i] >= highs[i+1]) risingHighs = false;
}
double lows[];
if (!GetLowArray(lows, lookback)) return false;
bool risingLows = true;
for (int i = 1; i < lookback; i++) {
if (lows[i] >= lows[i+1]) risingLows = false;
}
return (risingHighs && risingLows);
}
bool IsFallingWedge(int lookback = 5) {
double highs[];
if (!GetHighArray(highs, lookback)) return false;
bool fallingHighs = true;
for (int i = 1; i < lookback; i++) {
if (highs[i] <= highs[i+1]) fallingHighs = false;
}
double lows[];
if (!GetLowArray(lows, lookback)) return false;
bool fallingLows = true;
for (int i = 1; i < lookback; i++) {
if (lows[i] <= lows[i+1]) fallingLows = false;
}
return (fallingHighs && fallingLows);
}
bool IsRectangleRange(int lookback = 5) {
double highs[];
if (!GetHighArray(highs, lookback)) return false;
double lows[];
if (!GetLowArray(lows, lookback)) return false;
double maxHigh = ArrayMaximum(highs);
double minLow = ArrayMinimum(lows);
return ((maxHigh - minLow) < Point * 20);
}
bool IsTweezerBottom(int lookback = 1) {
return (MathAbs(High[lookback] - High[lookback+1]) < Point * 5 &&
MathAbs(Low[lookback] - Low[lookback+1]) < Point * 5 &&
Close[lookback] < Open[lookback] && Close[lookback+1] > Open[lookback+1]);
}
bool IsBullishEngulfing(int lookback = 1) {
return (Close[lookback] < Open[lookback] && Close[0] > Open[0] &&
Close[0] > Open[lookback] && Open[0] < Close[lookback]);
}
bool IsHarami(int lookback = 1) {
return (Close[lookback] > Open[lookback] && Close[0] < Open[0] &&
Close[0] > Open[lookback] && Open[0] < Close[lookback]);
}
bool IsPiercingLinePlus(int lookback = 1) {
return (Close[lookback] < Open[lookback] && Close[0] > Open[0] &&
Close[0] > Open[lookback] && Close[0] > (Open[lookback] + Close[lookback]) * 0.7);
}
bool IsHopefulStar(int lookback = 2) {
return (Close[lookback] < Open[lookback] &&
MathAbs(Close[lookback-1] - Open[lookback-1]) < Point * 3 &&
Close[0] > Open[0] && Close[0] > (Open[lookback] + Close[lookback]) / 2);
}
bool IsThreeLineStrike(int lookback = 3) {
return (Close[lookback] > Open[lookback] && Close[lookback-1] > Open[lookback-1] &&
Close[lookback-2] > Open[lookback-2] && Close[0] < Open[0] &&
Close[0] < Open[lookback-2]);
}
bool IsUpsideTasukiGap(int lookback = 2) {
return (Close[lookback] > Open[lookback] && Close[lookback-1] > Open[lookback-1] &&
Close[0] < Open[0] && Close[0] > Close[lookback-1]);
}
bool IsInNeckLine(int lookback = 1) {
return (Close[lookback] < Open[lookback] && Close[0] < Open[0] &&
Close[0] == Low[lookback] && Close[0] < Open[lookback]);
}
bool IsFakeoutSupport(int lookback = 1) {
return (Low[lookback] < iLowest(NULL, 0, MODE_LOW, 20, 0) &&
Low[0] > iLowest(NULL, 0, MODE_LOW, 20, 0));
}
bool IsTweezerTop(int lookback = 1) {
return (MathAbs(High[lookback] - High[lookback+1]) < Point * 5 &&
MathAbs(Low[lookback] - Low[lookback+1]) < Point * 5 &&
Close[lookback] > Open[lookback] && Close[lookback+1] < Open[lookback+1]);
}
bool IsBearishEngulfing(int lookback = 1) {
return (Close[lookback] > Open[lookback] && Close[0] < Open[0] &&
Close[0] < Open[lookback] && Open[0] > Close[lookback]);
}
bool IsDarkCloudHarami(int lookback = 1) {
return (Close[lookback] > Open[lookback] && Close[0] < Open[0] &&
Close[0] < Close[lookback] && Open[0] > Close[lookback]);
}
bool IsDownsideTasukiGap(int lookback = 2) {
return (Close[lookback] < Open[lookback] && Close[lookback-1] < Open[lookback-1] &&
Close[0] > Open[0] && Close[0] < Close[lookback-1]);
}
bool IsCounterattackLine(int lookback = 1) {
return (Close[lookback] < Open[lookback] && Close[0] == Close[lookback]);
}
bool IsDeliberationPattern(int lookback = 3) {
return (Close[lookback] > Open[lookback] && Close[lookback-1] > Open[lookback-1] &&
Close[lookback-2] > Open[lookback-2] && Close[0] < Open[0] &&
High[0] < High[lookback-1]);
}
bool IsShootingStarLine(int lookback = 1) {
return (MathAbs(Close[lookback] - Open[lookback]) < Point * 5 &&
High[lookback] - MathMax(Close[lookback], Open[lookback]) > Point * 10 &&
MathMin(Close[lookback], Open[lookback]) - Low[lookback] < Point * 5);
}
bool IsDojiWithVolumeDrop(int lookback = 1) {
return (MathAbs(Close[lookback] - Open[lookback]) < Point * 3 &&
Volume[lookback] > Volume[lookback+1] * 1.5 &&
Close[lookback] > Close[lookback+1]);
}
bool IsFakeoutResistance(int lookback = 1) {
return (High[lookback] > iHighest(NULL, 0, MODE_HIGH, 20, 0) &&
High[0] < iHighest(NULL, 0, MODE_HIGH, 20, 0));
}
bool IsRisingThreeMethods(int lookback = 5) {
double highs[];
if (!GetHighArray(highs, lookback)) return false;
return (highs[0] > highs[1] && highs[1] < highs[2] && highs[2] < highs[3] && highs[3] < highs[4]);
}
bool IsFallingThreeMethods(int lookback = 5) {
double lows[];
if (!GetLowArray(lows, lookback)) return false;
return (lows[0] < lows[1] && lows[1] > lows[2] && lows[2] > lows[3] && lows[3] > lows[4]);
}
// 主循环
void OnTick() {
if(OrdersTotal() > 0) {
ManageTrades();
}
if(OrdersTotal() == 0) {
if(IdentifyZhongShu()) {
DetermineTrend();
}
int buySignal = CheckBuyPoint();
int sellSignal = CheckSellPoint();
if(buySignal > 0) {
ExecuteTrade(buySignal);
} else if(sellSignal > 0) {
ExecuteShortTrade(sellSignal);
} else {
// ===== 新增K线形态识别开始 =====
double highs[5], lows[5];
GetHighArray(highs); GetLowArray(lows);
if (IsYouHaoFanGong()) { Print("检测到好友反攻,准备做多"); ExecuteTrade(16); }
if (IsShuGuangChuXian()) { Print("检测到曙光初现,准备做多"); ExecuteTrade(17); }
if (IsXuRiDongSheng()) { Print("检测到旭日东升,准备做多"); ExecuteTrade(18); }
if (IsPingDi()) { Print("检测到平底,准备做多"); ExecuteTrade(19); }
if (IsTaXingChuDi()) { Print("检测到塔形底,准备做多"); ExecuteTrade(20); }
if (IsBeiZhuangDi()) { Print("检测到杯状底,准备做多"); ExecuteTrade(21); }
if (IsHongSanBing()) { Print("检测到红三兵,准备做多"); ExecuteTrade(25); }
if (IsSheJiZhiXian()) { Print("检测到射击之星,准备做空"); ExecuteShortTrade(21); }
if (IsPingDing()) { Print("检测到平顶,准备做空"); ExecuteShortTrade(16); }
if (IsTaXingDing()) { Print("检测到塔形顶,准备做空"); ExecuteShortTrade(17); }
if (IsDanYouFanGong()) { Print("检测到淡友反攻,准备做空"); ExecuteShortTrade(18); }
if (IsSanZhiWuYa()) { Print("检测到三只乌鸦,准备做空"); ExecuteShortTrade(20); }
if (IsHeiSanBing()) { Print("检测到黑三兵,准备做空"); ExecuteShortTrade(23); }
if (IsMianMianYinDie()) { Print("检测到绵绵阴跌形,准备做空"); ExecuteShortTrade(26); }
if (IsDiaoJingXian()) { Print("检测到吊颈线,准备做空"); ExecuteShortTrade(27); }
if (IsGaoWeiChuTao()) { Print("检测到高位出逃形,准备做空"); ExecuteShortTrade(28); }
if (IsGraveyardDoji()) { Print("检测到墓碑线,准备做空"); ExecuteShortTrade(29); }
if (IsDarkCloudCover()) { Print("检测到乌云盖顶,准备做空"); ExecuteShortTrade(30); }
if (IsEveningStar()) { Print("检测到黄昏之星,准备做空"); ExecuteShortTrade(31); }
if (IsBigBearEngulfing()) { Print("检测到大阴包阳,准备做空"); ExecuteShortTrade(32); }
if (IsDojiReversal()) { Print("检测到十字星反转,准备做空"); ExecuteShortTrade(33); }
if (IsSymmetricalTriangle()) { Print("检测到对称三角形,准备突破"); ExecuteTrade(34); }
if (IsAscendingTriangle()) { Print("检测到上升三角形,准备突破"); ExecuteTrade(35); }
if (IsDescendingTriangle()) { Print("检测到下降三角形,准备突破"); ExecuteTrade(36); }
if (IsFlagPattern()) { Print("检测到旗形,准备突破"); ExecuteTrade(37); }
if (IsRisingWedge()) { Print("检测到上升楔形,准备做空"); ExecuteShortTrade(38); }
if (IsFallingWedge()) { Print("检测到下降楔形,准备做多"); ExecuteTrade(39); }
if (IsRectangleRange()) { Print("检测到矩形震荡,准备区间操作"); ExecuteTrade(40); }
if (IsTweezerBottom()) { Print("检测到镊子底,准备做多"); ExecuteTrade(41); }
if (IsBullishEngulfing()) { Print("检测到看涨吞没,准备做多"); ExecuteTrade(42); }
if (IsHarami()) { Print("检测到孕线,准备做多"); ExecuteTrade(43); }
if (IsPiercingLinePlus()) { Print("检测到刺透加强形态,准备做多"); ExecuteTrade(44); }
if (IsHopefulStar()) { Print("检测到希望之星,准备做多"); ExecuteTrade(45); }
if (IsThreeLineStrike()) { Print("检测到三空阳线,准备做多"); ExecuteTrade(46); }
if (IsUpsideTasukiGap()) { Print("检测到向上跳空并列阳线,准备做多"); ExecuteTrade(47); }
if (IsInNeckLine()) { Print("检测到颈内线,准备做多"); ExecuteTrade(48); }
if (IsFakeoutSupport()) { Print("检测到假突破支撑,准备做多"); ExecuteTrade(49); }
if (IsTweezerTop()) { Print("检测到镊子顶,准备做空"); ExecuteShortTrade(41); }
if (IsBearishEngulfing()) { Print("检测到看空吞没,准备做空"); ExecuteShortTrade(42); }
if (IsDarkCloudHarami()) { Print("检测到乌云孕线,准备做空"); ExecuteShortTrade(43); }
if (IsDownsideTasukiGap()) { Print("检测到向下跳空并列阴线,准备做空"); ExecuteShortTrade(44); }
if (IsCounterattackLine()) { Print("检测到反击线,准备做空"); ExecuteShortTrade(45); }
if (IsDeliberationPattern()) { Print("检测到黑三兵变体,准备做空"); ExecuteShortTrade(46); }
if (IsShootingStarLine()) { Print("检测到流星线,准备做空"); ExecuteShortTrade(47); }
if (IsDojiWithVolumeDrop()) { Print("检测到十字星+放量下跌,准备做空"); ExecuteShortTrade(48); }
if (IsFakeoutResistance()) { Print("检测到高位假突破,准备做空"); ExecuteShortTrade(49); }
if (IsRisingThreeMethods()) { Print("检测到上升三法,准备突破"); ExecuteTrade(50); }
if (IsFallingThreeMethods()) { Print("检测到下降三法,准备突破"); ExecuteShortTrade(51); }
}
}
}
```