CMO
Download scriptThis script implements a specialized financial analysis tool known as Chande's Momentum Oscillator (CMO). It is designed to measure the strength and direction of price momentum by comparing upward movement against downward movement over a specific period.
Core Logic Overview
The indicator works by analyzing price changes over a defined window (defaulting to 14 bars). It breaks down these price movements into two distinct categories:
- Upward Movement: The script identifies every instance where the closing price of a candle is higher than the previous one. It calculates the total distance gained during these specific "up" moves.
- Downward Movement: Similarly, it identifies every instance where the closing price is lower than the previous one and calculates the total distance lost during these specific "down" moves.
The Calculation Formula
To provide a clear picture of market sentiment, the script performs a three-step calculation:
- Difference: It subtracts the total downward movement from the total upward movement.
- Ratio: It divides that difference by the sum of both movements (Total Up + Total Down). This normalizes the data so it isn't just a raw number, but a relative proportion of movement.
- Scaling: Finally, the result is multiplied by 100. This allows the indicator to fluctuate within a specific range of -100 to +100.
Interpretation of Results
The resulting line on your chart represents the balance between buyers and sellers:
- Positive Values: Indicate that upward momentum is stronger than downward momentum.
- Negative Values: Indicate that downward momentum is dominating the market.
- Extreme Values: When the indicator approaches the 100 or -100 limits, it suggests very strong, one-sided momentum.
Practical Trading Rules
The internal logic also provides a framework for executing trades based on specific "Cross-over" events:
- Entry Signal: A long position (buy) is triggered when the indicator crosses below the -50 level.
- Exit Signals: There are three distinct conditions to close a position:
- The indicator crosses back above the +50 level.
- A profit target of 0.2% is achieved.
- A "Stop Loss" logic where the position closes if the price drops below the entry point within 20 bars.
//+------------------------------------------------------------------+
//| CMO.mq4 |
//| Copyright © 2007, Alexandre |
//| http://www.kroufr.ru/content/view/1491/124/ |
//+------------------------------------------------------------------+
/* Ôîðìóëû èíäèêàòîðà äëÿ Ìåòàñòîêà |
CMO_1 |
Sum(If(C, >, Ref(C, -1), (C - Ref(C, -1)), 0), 14) |
CMO_2 |
Sum(If(C, <, Ref(C, -1), (Ref(C, -1) - C)), 0), 14) |
CMO_Final |
100 *((Fml("CMO_1") - Fml("CMO_2")) / (Fml("CMO_1") + Fml("CMO_2"))) |
Êîìáèíèðîâàííàÿ ôîðìóëà: |
Chande's Momentum Oscillator |
100 * |
((Sum(If(C, >, Ref(C, -1), (C - Ref(C,-1)), 0), 14)) - |
(Sum(If(C, <, REF(C, -1), (REF(C,-1) - C), 0), 14))) / |
((Sum(If(C, >, Ref(C, -1), (C - Ref(C, -1)), 0), 14) + |
(Sum(If(C, <, REF(C, -1), (REF(C, -1) - C), 0), 14)))) |
//+------------------------------------------------------------------+
Ìîìåíòóì-îñöèëëÿòîð ×àíäå ðàññ÷èòûâàåòñÿ ïóòåì äåëåíèÿ ðàçíèöû ìåæäó |
äâèæåíèåì âîñõîäÿùåãî äíÿ è íèñõîäÿùåãî äíÿ íà ñóììó ìåæäó äâèæåíèåì |
âîñõîäÿùåãî äíÿ è íèñõîäÿùåãî äíÿ. Ïîëó÷åííûé ðåçóëüòàò óìíîæàåòñÿ íà|
100.  ðåçóëüòàòå ìû ïîëó÷àåì èíäèêàòîð, ÷üè çíà÷åíèÿ âàðüèðóþòñÿ îò |
-100 äî 100. |
Íàïðèìåð, èñïîëüçóåì äíåâíûå äàííûå â êà÷åñòâå ïðèìåðà. |
Åñëè ñåãîäíÿøíÿÿ öåíà çàêðûòèÿ âûøå â÷åðàøíåé öåíû çàêðûòèÿ, |
òî ñåãîäíÿøíèé äåíü ñ÷èòàåòñÿ âîñõîäÿùèì äíåì, àêòèâíîñòüþ |
âîñõîäÿùåãî äíÿ ñ÷èòàåì ðàçíèöó ìåæäó ñåãîäíÿøíåé öåíîé è â÷åðàøíåé |
öåíîé, íèñõîäÿùàÿ àêòèâíîñòü ñ÷èòàåòñÿ ðàâíîé 0. Ïðîòèâîïîëîæíîå |
âåðíî, åñëè ñåãîäíÿøíåå çàêðûòèå íèæå â÷åðàøíåãî çàêðûòèÿ. |
CMO = ((äâèæåíèå ââåðõäâèæåíèå âíèç)/(äâèæåíèå ââåðõ + |
äâèæåíèå âíèç)) * 100 |
Äàííàÿ ñèñòåìà ðàáîòàåò òîëüêî ñ äëèííûìè ïîçèöèÿìè. |
Ïðàâèëà: |
1. Îòêðûâàåì äëèííóþ ïîçèöèþ íà îòêðûòèè ñëåäóþùåãî áàðà, ïîñëå |
òîãî, êàê ÑÌÎ14 ïåðåñåêàåò âíèç óðîâåíü -50; |
2. Äëèííàÿ ïîçèöèÿ çàêðûâàåòñÿ, åñëè ÑÌÎ14 ïåðåñåêàåò ââåðõ |
óðîâåíü +50; |
3. Äëèííàÿ ïîçèöèÿ çàêðûâàåòñÿ ïðè äîñòèæåíèè öåëè ïðèáûëè 0.2 %; |
4. Äëèííàÿ ïîçèöèÿ çàêðûâàåòñÿ, åñëè íà 20 áàðå ïîñëå îòêðûòèÿ |
ïîçèöèè öåíà íàõîäèòñÿ íèæå óðîâíÿ âõîäà. |
//+------------------------------------------------------------------+
*/
#property copyright "Copyright © 2007, Alexandre"
#property link "http://www.kroufr.ru/content/view/1491/124/"
//----
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_color1 Red
#property indicator_minimum -100
#property indicator_maximum 100
#property indicator_level1 50
#property indicator_level2 -50
//---- input parameters
extern bool LastBarOnly = true;
extern int CMO_Range = 14;
//---- buffers
double CMO_Buffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init()
{
//---- indicators
IndicatorShortName("Chande`s Momentum Oscillator (" + CMO_Range + ")");
SetLevelStyle(STYLE_DASHDOT, 1, DodgerBlue);
SetIndexStyle(0, DRAW_LINE);
SetIndexLabel(0, "CMO");
SetIndexBuffer(0, CMO_Buffer);
SetIndexDrawBegin(0, CMO_Range);
//----
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
//----
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+
int start()
{
int counted_bars = IndicatorCounted();
int i, j, Limit, cnt_bars;
double dif_close, cmo_up, cmo_dw;
static bool run_once;
// to prevent possible error
if(counted_bars < 0)
{
return(-1);
}
Limit = Bars - counted_bars;
// run once on start
if(run_once == false)
cnt_bars = Limit - CMO_Range;
else
if(LastBarOnly == false)
cnt_bars = Limit;
else
cnt_bars = 0;
//----
for(i = cnt_bars; i >= 0; i--)
{
cmo_up = 0.0;
cmo_dw = 0.0;
//----
for(j = i + CMO_Range - 1; j >= i; j--)
{
dif_close = Close[j] - Close[j+1];
if(dif_close > 0)
cmo_up += dif_close;
else
if(dif_close < 0)
cmo_dw -= dif_close;
}
CMO_Buffer[i] = 100 * (cmo_up - cmo_dw) / (cmo_up + cmo_dw);
}
//----
if(run_once == false)
run_once = true;
//----
return(0);
}
//+------------------------------------------------------------------+
Comments