ð¬ã16ææ³ãç·åœããããã¬ã€ã¯ã¢ãŠãèªåæ¢çŽ¢ã§å€æïŒZigzagæåŒ·ãã§ã3æ¥éã¬ã³ãžã«ãå ã...ïŒïŒ
ð€ãçµå±ã©ã®ãã¬ã€ã¯ã¢ãŠããäžçªåŒ·ãã®ïŒïŒã
ãã®çåããã£ãšã¢ã€ã¢ã€ããŠãŸããã§ããïŒ
ãNè¶³é«å€å®å€ããããããã ãããã忥ã®é«å€å®å€ã䜿ãã ãZigzagã®ãããããæåŒ·ããããã ããã³ãã£ã³ãã£ãã«ã£ãŠã©ããªã®ïŒã
æ å ±ãå€ãããŠãäœãä¿¡ããã°ãããè¿·åïŒ ðµð«
ããã§ç§ããã¬ã€ã¯ã¢ãŠãèªåæ¢çŽ¢è£ çœ®ããŽãªãŽãªéçºããŸããã
16çš®é¡ã®ãã¬ã€ã¯ã¢ãŠãææ³ãã15,000æ¬ã®ããŒã¿ã§ç·åœããæ€èšŒïŒ
ä»åã®ç®çã¯**ãæ¥è¶³ã¬ã³ãžãã®æéã1ã6æ¥éãŸã§çްããæ€èšŒ**ããããšã
ã忥ã ããã®é«å€å®å€ãšãéå»3æ¥éãã®é«å€å®å€ãã©ã£ã¡ãããã®ãïŒ
çµæã¯...
æç§æžãæžãæããã¬ãã«ã®çºèŠã§ããã ð±âš
ð¯ ãã®èšäºã§ã¹ãããªããããš
ãã©ã®ãã¬ã€ã¯ã¢ãŠãå®çŸ©ãæåŒ·ãªã®ãïŒããçœé»ããããªã€ããŸãïŒ
æ€èšŒããææ³ïŒ
- ð Nè¶³é«å€å®å€ïŒN=10, 20, 50æ¬ïŒ
- ð¯ ZigzagïŒããããé«å€å®å€ïŒ â æåŒ·åè£ïŒ
- ð æ¥è¶³ã¬ã³ãžïŒ1ã6æ¥éïŒâ ä»åã®å€§å®éšïŒ
- ð ATRãã³ãïŒä¿æ°1.0, 1.5, 2.0ïŒ
- ð ãã³ãã£ã³ãã£ãã«ïŒæé10, 20, 50ïŒ
åèš16ãã¿ãŒã³ à 買ã/売ã à 5ã€ã®ä¿ææé = 160éãã®å£®çµ¶ããã«ïŒ
ããçµè«èšã£ã¡ãããŸãã... ð€«
ð¥ 1äœ: Zigzag(20) â åç60.3%ãå¹³å+5.16pips
ð¥ 2äœ: ATRÃ2.0 â åç60.1%
ð¥ 3äœ: æ¥è¶³3æ¥éã¬ã³ãž â åç56.7%ãå¹³å+3.23pips â ããŒã¯ããŒã¹ïŒ
ð æ¥è¶³1æ¥éïŒåæ¥ã®ã¿ïŒâ åç49.0%ïŒã³ã€ã³ãã¹ä»¥äž...ïŒ
æ€èšŒç°å¢
- Python 3.11- MetaTrader5 (MT5)- pandas, numpy, matplotlib, seaborn, scipy- é貚ãã¢: USDJPY- æéè¶³: 5åè¶³ïŒæ¥è¶³ããŒã¿ã䜵çšïŒ- ããŒã¿æé: çŽ2.5ã¶æåïŒ15,000æ¬ïŒ- 決æž: æéã¯ããŒãºïŒ5åã15åã30åã60åã120ååŸïŒæ€èšŒãããã¬ã€ã¯ã¢ãŠãå®çŸ©
1. Nè¶³é«å€å®å€ãã¬ã€ã¯ã¢ãŠã
æãã·ã³ãã«ãªå®çŸ©ããã¬ãŒãå ¥éæžã®1ããŒãžç®ã«èŒã£ãŠããã€ã
ãçŽè¿Næ¬ã®æé«å€ãçµå€ãè¶ ãããè²·ããæå®å€ãå²ã£ãã売ãã
æ€èšŒãã©ã¡ãŒã¿ïŒN = 10, 20, 50æ¬
2. ZigzagïŒããããé«å€å®å€ïŒãã¬ã€ã¯ã¢ãŠã
ã¹ã€ã³ã°ãã€ã»ã¹ã€ã³ã°ããŒã䜿ã£ãå®çŸ©ãã¡ãã£ãšç人åãã
ãçŽè¿ã®æç¢ºãªé«å€ïŒãããããã€ïŒãè¶ ãããè²·ããå®å€ïŒããããããŒïŒãå²ã£ãã売ãã
åãªãé«å€å®å€ã§ã¯ãªããåšå²ããæç¢ºã«çªåºãããã€ã³ãã䜿ããŸãã
èŠããã«ã誰ãèŠãŠãé«å€ïŒã£ãŠåãããšãããã䜿ãããã§ãã
3. æ¥è¶³ã¬ã³ãžãã¬ã€ã¯ã¢ãŠãïŒ1ã6æ¥éïŒ
ä»åã®äž»åœ¹ïŒNæ¥éã®é«å€å®å€ã¬ã³ãžã䜿ã£ãå®çŸ©ã
- 1æ¥é: 忥ã®ã¿ã®é«å€å®å€
- 2æ¥é: 忥ã2æ¥åã®é«å€å®å€ïŒ2æ¥åã®ã¬ã³ãžïŒ
- 3æ¥é: 忥ã3æ¥åã®é«å€å®å€ïŒ3æ¥åã®ã¬ã³ãžïŒ
- 4æ¥é: 忥ã4æ¥åã®é«å€å®å€ïŒ4æ¥åã®ã¬ã³ãžïŒ
- 5æ¥é: 忥ã5æ¥åã®é«å€å®å€ïŒ5æ¥åã®ã¬ã³ãžïŒ
- 6æ¥é: 忥ã6æ¥åã®é«å€å®å€ïŒ6æ¥åã®ã¬ã³ãžïŒ
ã忥ã®é«å€å®å€ãè¶ ãããè²·ããã¯ãã€ãã¬ã®å®çª...ã ãã©æ¬åœã«å¹ãã®ïŒ
ãããããŠ**3æ¥éãšã5æ¥éã®ã¬ã³ãžã䜿ã£ãæ¹ãããããããªãïŒ**ãšããä»®èª¬ãæ€èšŒïŒ
4. ATRãã³ããã¬ã€ã¯ã¢ãŠã
ãã©ãã£ãªãã£ãèæ ®ããå®çŸ©ã
ãåã®è¶³ã®çµå€ + ATR Ã ä¿æ° ãè¶ ãããè²·ããçµå€ - ATR Ã ä¿æ° ãå²ã£ãã売ãã
æ€èšŒãã©ã¡ãŒã¿ïŒä¿æ° = 1.0, 1.5, 2.0
5. ãã³ãã£ã³ãã£ãã«ãã¬ã€ã¯ã¢ãŠã
ã¿ãŒãã«ãºã§æåãªãªãã£ãŒãã»ãã³ãã¢ã³ãéçºããææ³ã
ãçŽè¿Næ¬ã®æé«å€ãè¶ ãããè²·ããæå®å€ãå²ã£ãã売ãã
...ãããããNè¶³é«å€å®å€ãšåããããªãïŒð€
ïŒãã¿ãã¬: ãŸã£ããåãã§ããïŒ
ðš çµæçºè¡šïŒ16ææ³ã®çå®ïŒ
ð åçããŒãããã
ãã®è²ã®éããèŠãŠãã ããïŒ ð±
ç·ãæ¿ãã»ã©é«åçãèµ€ãã»ã©...å¯ããŠãã ããã
ð 120åä¿æã§ã®åçã©ã³ãã³ã°
| é äœ | ææ³ | åç | å¹³åãªã¿ãŒã³ | ãµã³ãã«æ° |
|---|---|---|---|---|
| ð¥ 1äœ | Zigzag(20) | 60.3% | +5.16pips | 316 |
| ð¥ 2äœ | ATRÃ2.0 | 60.1% | +0.88pips | 143 |
| ð¥ 3äœ | æ¥è¶³(3æ¥é) | 56.7% | +3.23pips | 124 |
| 4äœ | æ¥è¶³(6æ¥é) | 49.9% | -1.33pips | 77 |
| 5äœ | æ¥è¶³(2æ¥é) | 49.6% | +1.08pips | 141 |
| 6äœ | ATRÃ1.5 | 49.2% | -0.94pips | 413 |
| 7äœ | Donchian(10) | 49.1% | -0.38pips | 1638 |
| 8äœ | Nè¶³(10æ¬) | 49.1% | -0.38pips | 1638 |
| ð 9äœ | æ¥è¶³(1æ¥é) | 49.0% | +0.51pips | 203 |
| 10äœ | æ¥è¶³(4æ¥é) | 48.8% | -2.69pips | 114 |
| 11äœ | Donchian(20) | 48.1% | -0.76pips | 1102 |
| 12äœ | Nè¶³(20æ¬) | 48.1% | -0.76pips | 1102 |
| 13äœ | ATRÃ1.0 | 48.0% | -0.35pips | 1538 |
| 14äœ | Donchian(50) | 47.2% | -0.38pips | 649 |
| 15äœ | Nè¶³(50æ¬) | 47.2% | -0.38pips | 649 |
| ðð 16äœ | æ¥è¶³(5æ¥é) | 43.9% | -4.72pips | 94 |
èŠããŸãããããã®è¡æã®äºå®ïŒïŒ ð
ð ãã¹ãææ³ã®å¯èŠå
Zigzagãã¶ã£ã¡ããã§ç·è²ïŒNè¶³ã»ãã³ãã£ã³ã¯èŠäºãªèµ€ïŒ ð
ð¥ è¡æã®çºèŠ5é£çºïŒ
ð¡ çºèŠâ ïŒZigzagæåŒ·èª¬ã¯æ¬åœã ã£ãïŒ
ãã¹ã€ã³ã°ãã€ã»ã¹ã€ã³ã°ããŒã䜿ãããšããå äººã®æããæ£ããã£ãïŒ
| ææš | Zigzag(20) |
|---|---|
| åç | 60.3% |
| å¹³åãªã¿ãŒã³ | +5.16pips |
| ãµã³ãã«æ° | 316 |
åçããªã¿ãŒã³ããµã³ãã«æ°ããäžæåæã£ãçè ïŒ
ð¡ çºèŠâ¡ïŒæ¥è¶³3æ¥éã¬ã³ãžãããŒã¯ããŒã¹ïŒ
ããã¯äºæ³å€ã§ãã...
| ææš | æ¥è¶³(3æ¥é) | æ¥è¶³(1æ¥é) |
|---|---|---|
| åç | 56.7% | 49.0% |
| å¹³åãªã¿ãŒã³ | +3.23pips | +0.51pips |
忥ã®ã¿ïŒ1æ¥éïŒã§ã¯ãªãã忥ã3æ¥åïŒ3æ¥éïŒã®ã¬ã³ãžã䜿ãã ãã§åç7.7ãã€ã³ãUPïŒ
åããæ¥è¶³ã¬ã³ãžãã¬ã€ã¯ããªã®ã«ã倩åœãšå°çã®å·®ïŒ ð±
ð¡ çºèŠâ¢ïŒåæ¥ã®ã¿ïŒ1æ¥éïŒã¯ãã£ã±ããŽãã ã£ã
ã忥é«å€ãè¶ ãããè²·ãã
ãã€ãã¬ãŒããŒã®å®çªææ³ãå®ã¯...
| ææš | æ¥è¶³(1æ¥é) |
|---|---|
| åç | 49.0% |
| é äœ | 16ææ³äž9äœ |
ã³ã€ã³ãã¹ãšå€ãããªãïŒ ð
ã¿ããªã䜿ã£ãŠãææ³ãªã®ã«ããªãå¹ããªãïŒ
â ã¿ããªãæèããããŠãããã·ãå¢ããããïŒ
倧å£ã¯ã忥é«å€ãè¶ ãããè²·ããå ¥ãããšç¥ã£ãŠãŸãã ãããšè¶ ããããŠãè²·ããèªã蟌ãã§ããå©ãèœãšãã
ããããããã·ãã®æ£äœã§ãã
ð¡ çºèŠâ£ïŒNè¶³é«å€å®å€ãšãã³ãã£ã³ã¯å®å šåäžã®ãŽãã ã£ã
æ€èšŒããŠå€æïŒ
Donchian(10) = Nè¶³(10æ¬) â åç49.1%Donchian(20) = Nè¶³(20æ¬) â åç48.1%Donchian(50) = Nè¶³(50æ¬) â åç47.2%å®å šã«åãçµæïŒååãéãã ãã§ãäžèº«ã¯åããŽãã ð
ããã³ãã£ã³ãã£ãã«ãã£ãŠã«ãã³ããååã«éšããããªïŒ
ð¡ çºèŠâ€ïŒæ¥è¶³ã¬ã³ãžã¯ã3æ¥éããã¹ã€ãŒãã¹ããã
| æé | åç | è©äŸ¡ |
|---|---|---|
| 1æ¥é | 49.0% | ð ãŽã |
| 2æ¥é | 49.6% | ð ãŽã |
| 3æ¥é | 56.7% | âš å ã£ãïŒ |
| 4æ¥é | 48.8% | ð ãŽã |
| 5æ¥é | 43.9% | ðð ææª |
| 6æ¥é | 49.9% | ð ãŽã |
ã3æ¥éãã ããç°æ§ã«å ã£ãŠãïŒ
çãããŠãé·ãããŠããã¡ã3æ¥éãã¡ããã©ããå¡©æ¢ ã
ãªããïŒ
- 1ã2æ¥é: ãã€ãºãå€ãããããããŸããŸãæããã ãã®ãã¿ãŒã³ãå€ã
- 3æ¥é: çšãããæå³ã®ããã¬ã³ãžããšããŠæ©èœããŠãã
- 4æ¥é以äž: ãµã³ãã«æ°ãæžããããïŒã¬ã³ãžãåºãããŠãã¬ã€ã¯ããŠãå¢ããç¶ããªã
ä¿ææéå¥ã®åæ
è峿·±ããã¿ãŒã³ïŒ
- Zigzag: å®å®ããŠå³è©äžãããæéã峿¹ããŠãããïŒ
- æ¥è¶³(3æ¥é): 60å以éã§äžæåŸå
- Nè¶³/ãã³ãã£ã³: ãã£ãš50%æªæºã§æšªã°ããæéããããŠãç¡é§ã
è²·ããšå£²ãã®æ¯èŒ
ãªãZigzagãæåŒ·ãªã®ãïŒ
çç±1ïŒãæ¬ç©ã®é«å€å®å€ãã ãã䜿ã
Nè¶³é«å€å®å€ã¯ãããŸããŸçŽè¿Næ¬ã§æé«ããšããã ãã
Zigzagã¯**ãååŸãèŠãŠãæç¢ºã«çªåºããŠããã**ãã€ã³ãã䜿ããŸãã
â ãæ¬ç©ã®ãµãã¬ãžãã ãããã¬ã€ã¯ããïŒ
çç±2ïŒãã€ãºãèªåãã£ã«ã¿ãªã³ã°
å°ããªäžäžåã¯ãããããããšããŠèªèãããŸããã
â ããã·ãèªåçã«é€å€ãããïŒ
çç±3ïŒå€§å£ãæèããŠãã
æ©é¢æè³å®¶ãã¹ã€ã³ã°ãã€ã»ã¹ã€ã³ã°ããŒãèŠãŠããŸãã
â ãã¬ã€ã¯ãããæ¬åœã«åãïŒ
å®è·µãžã®ç€ºå
æŠç¥1ïŒZigzagã䜿ãïŒ
ãããããçµè«ãã¹ã€ã³ã°ãã€ã»ã¹ã€ã³ã°ããŒãåºæºã«ããŸãããã
# ZigzagïŒã¹ã€ã³ã°ãã€ã»ã¹ã€ã³ã°ããŒïŒã®æ€åºdef detect_zigzag(df, period=20): swing_high = df['high'] == df['high'].rolling(period*2+1, center=True).max() swing_low = df['low'] == df['low'].rolling(period*2+1, center=True).min() return swing_high, swing_lowæŠç¥2ïŒæ¥è¶³ã¬ã³ãžã䜿ããªã3æ¥é
ã©ãããŠãæ¥è¶³ã¬ã³ãžã䜿ããããªãã忥ã3æ¥åã®3æ¥éã®ã¬ã³ãžã䜿ããŸãããã
# 3æ¥éã®æ¥è¶³é«å€å®å€ãååŸdaily_high_3days = df_daily['high'].shift(1).rolling(3).max()daily_low_3days = df_daily['low'].shift(1).rolling(3).min()æŠç¥3ïŒNè¶³/ãã³ãã£ã³ã¯ä»ããæšãŠã
ã·ã³ãã«ã§åãããããããã£ãŠäœ¿ã£ãŠãŸãããïŒ
åç47ã49%ã¯ãã¹ãã¬ããè² ãã§å®è³ªãã€ãã¹ã§ãã
ä»ããåé€ããŠãã ããã
æŠç¥4ïŒ120å以äžä¿æãã
5ååŸã15ååŸã¯ãã€ãºãå€ãã
æäœã§ã60åãã§ããã°120åã¯ä¿æããåæã§ã
â ïž æ³šæç¹
ãµã³ãã«æ°ã®éã
| ææ³ | ãµã³ãã«æ° |
|---|---|
| Nè¶³(10æ¬) | 1638 |
| Zigzag(20) | 316 |
| æ¥è¶³(3æ¥é) | 124 |
Zigzagãšæ¥è¶³3æ¥éã¯ãµã³ãã«æ°ãå°ãªãã
çµ±èšçãªäžç¢ºå®æ§ã¯æ®ããŸãã
ãã ãZigzag(316ãµã³ãã«)ã¯ååãªéããããä¿¡é Œæ§ã¯é«ãã§ãã
æ€èšŒæé
2025幎10æã12æã®çŽ2.5ã¶æéã
ããé·æã®ããŒã¿ã§ã®æ€èšŒãä»åŸãããŸãïŒ
ð ãŸãšãïŒãã¬ã€ã¯ã¢ãŠãææ³ã®çå®
ð ããŒã¿ãæŽããçå®
| çºèŠ | å 容 | ããªããžã®æå³ |
|---|---|---|
| â | ZigzagæåŒ·ïŒ60.3%ïŒ | ããã䜿ãïŒ |
| â¡ | æ¥è¶³3æ¥éãæå€ãšè¯ãïŒ56.7%ïŒ | ãµãææ³ã«ïŒ |
| ⢠| 忥ã®ã¿ïŒ1æ¥éïŒã¯ãŽãïŒ49.0%ïŒ | å®çªææ³ãçãïŒ |
| ⣠| Nè¶³/ãã³ãã£ã³ã¯å šéšãŽã | ä»ããæšãŠãïŒ |
| †| æ¥è¶³ã¬ã³ãžã¯3æ¥éããã¹ã | çãããŠãé·ãããŠããã¡ïŒ |
â¡ ä»ããå®è·µã§ãã3ã€ã®ããš
- ð¯ ZigzagïŒã¹ã€ã³ã°ãã€ã»ã¹ã€ã³ã°ããŒïŒãåºæºã«ãã
- â° æäœ120åã¯ä¿æããåæã§æŠç¥ãçµã
- ðïž Nè¶³é«å€å®å€ã»ãã³ãã£ã³ãã£ãã«ãåé€ãã
ð¥ æåŸã«ãã忥é«å®ãã¬ã€ã¯ããä¿¡ããŠãéå»ã®èªåãž
ã忥é«å€ãè¶ ãããè²·ãïŒããããã€ãã¬ã®åºæ¬ã ïŒã
ãã®é ã®ä¿ºãèããŠãïŒ
ããã倧ééãã ã£ããã ð
忥é«å®ãã¬ã€ã¯ïŒåç49%ã
ã³ã€ã³ãã¹ãšå€ãããªãããããã¹ãã¬ããèãããã³ã€ã³ãã¹ä»¥äžã
ã§ãZigzagã䜿ãã°ïŒåç60.3%ïŒ
æ¥è¶³3æ¥éã¬ã³ãžã䜿ãã°ïŒåç56.7%ïŒ
ãã¿ããªãèŠãŠããšãããã«ã¯ãããåªäœæ§ããªãã
ãã¿ããªãèŠãŠãªããšãããã«ãå®ãããã
ãããããŒã¿ã§æ€èšŒããããšã®äŸ¡å€ã
ãåžžèããçãããå®çªããçãã
æ°åã ããçå®ãæããŠãããã ð¬âš
ð é¢é£èšäº: ATRãã£ã«ã¿ãŒã§ããã·ãé¿ãã - ãã¬ã€ã¯ã¢ãŠããããã«æ¹åããæ¹æ³
ð¬ 質åã»ææ³ã¯ãã¡ã èšäºäœæè ïŒããœãP (@hosono_p) on XïŒæ§TwitterïŒ ãã¬ã€ã¯ã¢ãŠãã®è©±ãæ€èšŒã®çžè«ããªãã§ããæ°è»œã«DMãã ããïŒ
ð ïž æ€èšŒã³ãŒãå šæ
ä»å䜿çšããããã¬ã€ã¯ã¢ãŠãèªåæ¢çŽ¢è£ çœ®ãã®Pythonã³ãŒãã§ãã
åäœç°å¢:
- Python 3.11+
- MetaTrader5ãã€ã³ã¹ããŒã«ãããŠããããš
- å¿
èŠã©ã€ãã©ãª:
pandas,numpy,matplotlib,seaborn,scipy
"""ãã¬ã€ã¯ã¢ãŠãèªåæ¢çŽ¢è£
çœ®è€æ°ã®ãã¬ã€ã¯ã¢ãŠãå®çŸ©ãèªåæ€èšŒããæé©ãªææ³ãçºèŠãã
æ€èšŒãããã¬ã€ã¯ã¢ãŠãå®çŸ©:1. Nè¶³é«å€å®å€ïŒN=10, 20, 50ïŒ2. ZigzagïŒããããã®é«å€å®å€ïŒ3. æ¥è¶³é«å€å®å€4. ATRãã³ãïŒçµå€Â±ATRÃä¿æ°ïŒ5. ãã³ãã£ã³ãã£ãã«
決æž: æéã¯ããŒãºïŒ5åã15åã30åã60åã120ååŸïŒ"""
import MetaTrader5 as mt5import pandas as pdimport numpy as npimport matplotlib.pyplot as pltimport matplotlibmatplotlib.use('Agg') # GUIãªãã§ç»åä¿åimport seaborn as snsfrom scipy import statsfrom datetime import datetime, timedeltaimport warningswarnings.filterwarnings('ignore')
# æ¥æ¬èªãã©ã³ãèšå®plt.rcParams['font.family'] = ['MS Gothic', 'Hiragino Sans', 'IPAexGothic', 'sans-serif']plt.rcParams['axes.unicode_minus'] = False
# ===== èšå® =====SYMBOL = "USDJPYm" # ãããŒã«ãŒã«ãã£ãŠãµãã£ãã¯ã¹ãç°ãªãTIMEFRAME_M5 = mt5.TIMEFRAME_M5 # 5åè¶³TIMEFRAME_D1 = mt5.TIMEFRAME_D1 # æ¥è¶³NUM_BARS = 15000 # ååŸãã5åè¶³ã®æ°ATR_PERIOD = 14
# åæããæéæ ïŒåïŒ- 決æžã¿ã€ãã³ã°TIME_HORIZONS = [5, 15, 30, 60, 120]
# ãã¬ã€ã¯ã¢ãŠãå®çŸ©ã®ãã©ã¡ãŒã¿N_PERIODS = [10, 20, 50] # Nè¶³é«å€å®å€ã®NZIGZAG_PERIOD = 20 # ããããæ€åºæéATR_MULTIPLIERS = [1.0, 1.5, 2.0] # ATRãã³ãã®ä¿æ°DONCHIAN_PERIODS = [10, 20, 50] # ãã³ãã£ã³ãã£ãã«æé
def initialize_mt5(): """MT5ãåæå""" if not mt5.initialize(): print("MT5ã®åæåã«å€±æ") return False print(f"MT5ããŒãžã§ã³: {mt5.version()}") return True
def get_ohlc_data(symbol, timeframe, num_bars): """OHLCããŒã¿ãååŸ""" symbol_info = mt5.symbol_info(symbol) if symbol_info is None: print(f"Symbol {symbol} not found, trying with suffix...") for suffix in ['', '.i', '-m', '_SB']: test_symbol = symbol + suffix symbol_info = mt5.symbol_info(test_symbol) if symbol_info is not None: symbol = test_symbol print(f"Found symbol: {symbol}") break
if symbol_info is None: print(f"Symbol not found. Error: {mt5.last_error()}") symbols = mt5.symbols_get() if symbols: jpy_symbols = [s.name for s in symbols if 'JPY' in s.name][:10] print(f"Available JPY symbols: {jpy_symbols}") return None
if not symbol_info.visible: if not mt5.symbol_select(symbol, True): print(f"Failed to select symbol {symbol}") return None
rates = mt5.copy_rates_from_pos(symbol, timeframe, 0, num_bars) if rates is None or len(rates) == 0: print(f"Data fetch failed. Error: {mt5.last_error()}") return None
df = pd.DataFrame(rates) df['time'] = pd.to_datetime(df['time'], unit='s') df.set_index('time', inplace=True) print(f"Data: {len(df)} bars ({df.index[0]} to {df.index[-1]})") return df
def calculate_atr(df, period): """ATRïŒAverage True RangeïŒãèšç®""" high = df['high'] low = df['low'] close = df['close'].shift(1)
tr1 = high - low tr2 = abs(high - close) tr3 = abs(low - close)
tr = pd.concat([tr1, tr2, tr3], axis=1).max(axis=1) atr = tr.rolling(window=period).mean() return atr
def calculate_future_returns(df, horizons_minutes, timeframe_minutes=5): """ã·ã°ãã«çºçåŸã®ãªã¿ãŒã³ãèšç®ïŒpipsåäœïŒ""" for minutes in horizons_minutes: bars_ahead = minutes // timeframe_minutes if bars_ahead < 1: bars_ahead = 1 future_close = df['close'].shift(-bars_ahead) df[f'return_{minutes}m'] = (future_close - df['close']) * 100 # pips return df
# ===== ãã¬ã€ã¯ã¢ãŠãå®çŸ©é¢æ° =====
def detect_n_bar_breakout(df, n_period): """Nè¶³é«å€å®å€ãã¬ã€ã¯ã¢ãŠããæ€åº""" df[f'highest_{n_period}'] = df['high'].rolling(window=n_period).max().shift(1) df[f'lowest_{n_period}'] = df['low'].rolling(window=n_period).min().shift(1)
breakout_up = df['close'] > df[f'highest_{n_period}'] breakout_down = df['close'] < df[f'lowest_{n_period}']
signal_up = breakout_up & ~breakout_up.shift(1).fillna(False) signal_down = breakout_down & ~breakout_down.shift(1).fillna(False) return signal_up, signal_down
def detect_zigzag_breakout(df, period): """ZigzagïŒããããé«å€å®å€ïŒãã¬ã€ã¯ã¢ãŠããæ€åº""" df['swing_high'] = np.nan df['swing_low'] = np.nan
for i in range(period, len(df) - period): if df['high'].iloc[i] == df['high'].iloc[i-period:i+period+1].max(): df.iloc[i, df.columns.get_loc('swing_high')] = df['high'].iloc[i] if df['low'].iloc[i] == df['low'].iloc[i-period:i+period+1].min(): df.iloc[i, df.columns.get_loc('swing_low')] = df['low'].iloc[i]
df['last_swing_high'] = df['swing_high'].ffill() df['last_swing_low'] = df['swing_low'].ffill()
breakout_up = df['close'] > df['last_swing_high'] breakout_down = df['close'] < df['last_swing_low']
signal_up = breakout_up & ~breakout_up.shift(1).fillna(False) signal_down = breakout_down & ~breakout_down.shift(1).fillna(False) return signal_up, signal_down
def detect_daily_breakout(df_m5, df_d1, n_days=1): """ æ¥è¶³é«å€å®å€ãã¬ã€ã¯ã¢ãŠããæ€åº n_days: 忥ããäœæ¥åã®é«å€å®å€ã䜿ãã - 1 = 忥ã®ã¿ã®é«å€å®å€ - 2 = 忥ã2æ¥åã®é«å€å®å€ïŒ2æ¥éã®ã¬ã³ãžïŒ - 3 = 忥ã3æ¥åã®é«å€å®å€ïŒ3æ¥éã®ã¬ã³ãžïŒ â»åœæ¥ã®é«å€å®å€ã¯æ¥äžã«æŽæ°ããããããåç
§åºæºãšããŠäœ¿ããªã """ df_d1_copy = pd.DataFrame() df_d1_copy['ref_high'] = df_d1['high'].shift(1).rolling(window=n_days, min_periods=1).max() df_d1_copy['ref_low'] = df_d1['low'].shift(1).rolling(window=n_days, min_periods=1).min() df_d1_copy['date'] = df_d1.index.date
df_m5['date'] = df_m5.index.date df_merged = df_m5.merge(df_d1_copy, on='date', how='left') df_merged.index = df_m5.index
breakout_up = df_m5['close'] > df_merged['ref_high'] breakout_down = df_m5['close'] < df_merged['ref_low']
signal_up = breakout_up & ~breakout_up.shift(1).fillna(False) signal_down = breakout_down & ~breakout_down.shift(1).fillna(False) return signal_up, signal_down
def detect_atr_band_breakout(df, multiplier): """ATRãã³ããã¬ã€ã¯ã¢ãŠããæ€åº""" df[f'atr_upper_{multiplier}'] = df['close'].shift(1) + df['atr'] * multiplier df[f'atr_lower_{multiplier}'] = df['close'].shift(1) - df['atr'] * multiplier
breakout_up = df['close'] > df[f'atr_upper_{multiplier}'] breakout_down = df['close'] < df[f'atr_lower_{multiplier}']
signal_up = breakout_up & ~breakout_up.shift(1).fillna(False) signal_down = breakout_down & ~breakout_down.shift(1).fillna(False) return signal_up, signal_down
def detect_donchian_breakout(df, period): """ãã³ãã£ã³ãã£ãã«ãã¬ã€ã¯ã¢ãŠããæ€åº""" df[f'donchian_high_{period}'] = df['high'].rolling(window=period).max().shift(1) df[f'donchian_low_{period}'] = df['low'].rolling(window=period).min().shift(1)
breakout_up = df['close'] > df[f'donchian_high_{period}'] breakout_down = df['close'] < df[f'donchian_low_{period}']
signal_up = breakout_up & ~breakout_up.shift(1).fillna(False) signal_down = breakout_down & ~breakout_down.shift(1).fillna(False) return signal_up, signal_down
def analyze_signals(df, signal_up, signal_down, method_name): """ã·ã°ãã«ã®æçžŸãåæ""" results = {'method': method_name, 'up': {}, 'down': {}}
up_df = df[signal_up].copy() if len(up_df) >= 10: for minutes in TIME_HORIZONS: col = f'return_{minutes}m' returns = up_df[col].dropna() if len(returns) >= 5: results['up'][minutes] = { 'count': len(returns), 'mean': returns.mean(), 'std': returns.std(), 'win_rate': (returns > 0).mean() * 100, 'sharpe': returns.mean() / returns.std() if returns.std() > 0 else 0, 'skewness': stats.skew(returns) if len(returns) >= 3 else 0, }
down_df = df[signal_down].copy() if len(down_df) >= 10: for minutes in TIME_HORIZONS: col = f'return_{minutes}m' returns = -down_df[col].dropna() # 売ããªã®ã§ç¬Šå·å転 if len(returns) >= 5: results['down'][minutes] = { 'count': len(returns), 'mean': returns.mean(), 'std': returns.std(), 'win_rate': (returns > 0).mean() * 100, 'sharpe': returns.mean() / returns.std() if returns.std() > 0 else 0, 'skewness': stats.skew(returns) if len(returns) >= 3 else 0, } return results
def create_summary_table(all_results): """å
šçµæããµããªãŒããŒãã«ã«å€æ""" rows = [] for result in all_results: method = result['method'] for direction in ['up', 'down']: for minutes in TIME_HORIZONS: if minutes in result[direction]: data = result[direction][minutes] rows.append({ 'method': method, 'direction': 'è²·ã' if direction == 'up' else '売ã', 'hold_time': f'{minutes}å', 'count': data['count'], 'win_rate': data['win_rate'], 'mean_return': data['mean'], 'sharpe': data['sharpe'], 'skewness': data['skewness'], }) return pd.DataFrame(rows)
def main(): """ã¡ã€ã³åŠç""" print("[START] Breakout Explorer starting...")
if not initialize_mt5(): return None, None
try: print("\n[DOWNLOAD] Getting data...") df_m5 = get_ohlc_data(SYMBOL, TIMEFRAME_M5, NUM_BARS) df_d1 = get_ohlc_data(SYMBOL, TIMEFRAME_D1, 100)
if df_m5 is None or df_d1 is None: return None, None
df_m5['atr'] = calculate_atr(df_m5, ATR_PERIOD) df_m5 = calculate_future_returns(df_m5, TIME_HORIZONS)
all_results = []
# 1. Nè¶³é«å€å®å€ãã¬ã€ã¯ã¢ãŠã print("\n[1] Testing N-bar High/Low Breakout...") for n in N_PERIODS: signal_up, signal_down = detect_n_bar_breakout(df_m5, n) results = analyze_signals(df_m5, signal_up, signal_down, f'Nè¶³({n}æ¬)') all_results.append(results)
# 2. ZigzagïŒããããïŒãã¬ã€ã¯ã¢ãŠã print("\n[2] Testing Zigzag (Pivot) Breakout...") signal_up, signal_down = detect_zigzag_breakout(df_m5, ZIGZAG_PERIOD) results = analyze_signals(df_m5, signal_up, signal_down, f'Zigzag({ZIGZAG_PERIOD})') all_results.append(results)
# 3. æ¥è¶³é«å€å®å€ãã¬ã€ã¯ã¢ãŠãïŒ1ã6æ¥éã¬ã³ãžïŒ print("\n[3] Testing Daily High/Low Breakout (N-day range)...") for n_days in range(1, 7): day_label = f"{n_days}æ¥é" signal_up, signal_down = detect_daily_breakout(df_m5, df_d1, n_days) results = analyze_signals(df_m5, signal_up, signal_down, f'æ¥è¶³({day_label})') all_results.append(results)
# 4. ATRãã³ããã¬ã€ã¯ã¢ãŠã print("\n[4] Testing ATR Band Breakout...") for mult in ATR_MULTIPLIERS: signal_up, signal_down = detect_atr_band_breakout(df_m5, mult) results = analyze_signals(df_m5, signal_up, signal_down, f'ATRÃ{mult}') all_results.append(results)
# 5. ãã³ãã£ã³ãã£ãã«ãã¬ã€ã¯ã¢ãŠã print("\n[5] Testing Donchian Channel Breakout...") for period in DONCHIAN_PERIODS: signal_up, signal_down = detect_donchian_breakout(df_m5, period) results = analyze_signals(df_m5, signal_up, signal_down, f'Donchian({period})') all_results.append(results)
summary_df = create_summary_table(all_results) print("\n[DONE] Analysis complete!")
return all_results, summary_df
finally: mt5.shutdown()
if __name__ == "__main__": results, summary = main() if summary is not None: summary.to_csv('breakout_summary.csv', index=False, encoding='utf-8-sig') print("[SAVE] breakout_summary.csv saved")äœ¿ãæ¹
- MT5ãã€ã³ã¹ããŒã«ïŒãããŒã«ãŒã®ãã¢å£åº§ã§OKïŒ
- å¿
èŠã©ã€ãã©ãªãã€ã³ã¹ããŒã«
Bashpip install MetaTrader5 pandas numpy matplotlib seaborn scipy
- ã·ã³ãã«åãä¿®æ£ïŒãããŒã«ãŒã«ãã£ãŠ
USDJPYãUSDJPYmãªã©ç°ãªãïŒ - ã¹ã¯ãªãããå®è¡
Bashpython breakout_explorer.py
å®è¡ãããš:
- ã³ã³ãœãŒã«ã«çµæã©ã³ãã³ã°ã衚瀺ããã
breakout_summary.csvã«å šçµæãä¿åããã- ããŒããããçã®PNGç»åãçæããã
èªåã®ããŒã¿ã§æ€èšŒããŠãèªåã ãã®ãæåŒ·ãã¬ã€ã¯ã¢ãŠãããèŠã€ããŠãã ããïŒ ð¬
ðããããããŒã«ã»ãµãŒãã¹
ãã£ã³ããŒã³ã§æ1,790åããMT4/MT5ããªã€ã³ã¹ããŒã«æžã¿ãèªååŸ©æ§æ©èœä»ãã14æ¥éç¡æã詊ãã
ã·ã³ã¯ã©ãŠããã¹ã¯ããã for FX4幎ã§è³é4.7åã®ããã¯ãã¹ãå®çžŸããœãŒã¹ã³ãŒãä»ãã§èªç±ã«ã«ã¹ã¿ãã€ãºå¯èœã
ãŽããŒæ¥EA UltimateçïŒ3,980åïŒâ»äžèšãªã³ã¯ã«ã¯ããã¢ãŒã·ã§ã³ïŒåºåïŒãå«ãŸããŠããŸã
éåçžå Žè¬ç¥ïœããœãP
ããã°ã§ã¯æžããªãæ¬é³ã®ãã¬ãŒãæŠç¥ãšEAéçºã®è£åŽãå ¬éã ããŒã¿ã«åºã¥ããæ€èšŒã§ãåçŸæ§ã®ããææ³ã ãããå±ãããŸãã