goo blog サービス終了のお知らせ 

CyberChaos(さいばかおす)

プログラミング言語、トランスパイラ、RPA、ChatGPT、データマイニング、リバースエンジニアリングのための忘備録

TradingViewのPine Scriptでフーリエ変換プログラミング

2025-04-05 09:03:20 | FX
Pineスクリプトでロウソク足チャートをフーリエ変換し、いくつかの連続した波に分解したい。チャート形成に最も影響を与えている波5つを表示するプログラムを書いて欲しい。

# Pineスクリプトによるフーリエ変換と主要波の抽出

以下は、TradingViewのPine Scriptで価格データをフーリエ変換し、主要な5つの周波数成分を抽出して表示するプログラムです。このスクリプトは離散フーリエ変換(DFT)を使用して価格データを周波数成分に分解し、最も影響の大きい5つの波をチャート上に表示します。

```pinescript
//@version=5
indicator("フーリエ変換 - 主要5波分析", overlay=true)

// 入力パラメータ
length = input.int(256, title="分析ウィンドウサイズ", minval=32, maxval=512)
show_original = input(true, title="元の価格を表示")
show_combined = input(true, title="合成波を表示")
show_individual = input(true, title="個別の波を表示")
price_source = input(close, title="価格ソース")

// フーリエ変換関数
fourierTransform(series, length) =>
var real = array.new_float(length, 0)
var imag = array.new_float(length, 0)
// DFT計算
for k = 0 to length - 1
sum_real = 0.0
sum_imag = 0.0
for n = 0 to length - 1
angle = -2 * math.pi * k * n / length
sum_real += series[n] * math.cos(angle)
sum_imag += series[n] * math.sin(angle)
array.set(real, k, sum_real)
array.set(imag, k, sum_imag)
[real, imag]

// 振幅計算
calculateAmplitudes(real, imag, length) =>
var amplitudes = array.new_float(length, 0)
for k = 0 to length - 1
array.set(amplitudes, k, math.sqrt(math.pow(array.get(real, k), 2) + math.pow(array.get(imag, k), 2)))
amplitudes

// 逆フーリエ変換(選択した周波数のみ)
inverseTransform(real, imag, selected_indices, length) =>
var reconstructed = array.new_float(length, 0)
for n = 0 to length - 1
sum = 0.0
for k in selected_indices
angle = 2 * math.pi * k * n / length
sum += array.get(real, k) * math.cos(angle) - array.get(imag, k) * math.sin(angle)
array.set(reconstructed, n, sum / length)
reconstructed

// 価格データを配列に格納
var price_array = array.new_float(length, 0)
if barstate.islast
for i = 0 to length - 1
array.set(price_array, i, price_source[i])

// フーリエ変換実行
[real_part, imag_part] = fourierTransform(price_array, length)
amplitudes = calculateAmplitudes(real_part, imag_part, length)

// 振幅が大きい上位5つのインデックスを取得
findTopIndices(amplitudes, count) =>
var indices = array.new_int(count, 0)
var temp_amplitudes = array.copy(amplitudes)
for i = 0 to count - 1
max_val = -1.0
max_idx = 0
for k = 1 to array.size(temp_amplitudes) / 2 - 1 // ミラーリングを避ける
current_val = array.get(temp_amplitudes, k)
if current_val > max_val
max_val = current_val
max_idx = k
array.set(indices, i, max_idx)
array.set(temp_amplitudes, max_idx, -1.0) // 選択済みを無効化
indices

top_indices = findTopIndices(amplitudes, 5)

// 個々の波を再構築
var wave_arrays = array.new_array(5)
for i = 0 to 4
indices = array.new_int()
array.push(indices, array.get(top_indices, i))
array.set(wave_arrays, i, inverseTransform(real_part, imag_part, indices, length))

// 合成波を再構築
combined_wave = inverseTransform(real_part, imag_part, top_indices, length)

// プロット
if barstate.islast
// 元の価格
if show_original
plot(price_source, color=color.gray, title="元の価格", offset=-length+1)
// 合成波
if show_combined
var combined_line = array.new_float(length, 0)
for i = 0 to length - 1
array.set(combined_line, i, array.get(combined_wave, i))
plot(array.get(combined_line, 0), color=color.white, title="合成波", offset=-length+1, style=plot.style_linebr)
for i = 1 to length - 1
array.set(combined_line, i, array.get(combined_wave, i))
// 個々の波
if show_individual
colors = array.from(color.red, color.blue, color.green, color.orange, color.purple)
for wave_idx = 0 to 4
var wave_line = array.new_float(length, 0)
for i = 0 to length - 1
array.set(wave_line, i, array.get(array.get(wave_arrays, wave_idx), i))
plot(array.get(wave_line, 0), color=array.get(colors, wave_idx), title="波 " + str.tostring(wave_idx+1), offset=-length+1, style=plot.style_linebr)
for i = 1 to length - 1
array.set(wave_line, i, array.get(array.get(wave_arrays, wave_idx), i))

// 周波数情報表示
if barstate.islast
var table freq_table = table.new(position.top_right, 6, 6, border_width=1)
table.cell(freq_table, 0, 0, "周波数成分", bgcolor=color.gray)
table.cell(freq_table, 1, 0, "周期(バー)", bgcolor=color.gray)
table.cell(freq_table, 2, 0, "振幅", bgcolor=color.gray)
for row = 0 to 4
idx = array.get(top_indices, row)
period = length / idx
amplitude = array.get(amplitudes, idx)
table.cell(freq_table, 0, row+1, "波 " + str.tostring(row+1), bgcolor=array.get(colors, row))
table.cell(freq_table, 1, row+1, str.tostring(math.round(period, 2)), bgcolor=array.get(colors, row))
table.cell(freq_table, 2, row+1, str.tostring(math.round(amplitude, 2)), bgcolor=array.get(colors, row))
```

## プログラムの特徴

1. **離散フーリエ変換(DFT)の実装**:
- 価格データを周波数成分に分解
- 実数部と虚数部を計算

2. **主要5波の抽出**:
- 振幅が大きい上位5つの周波数を選択
- 各波の周期と振幅をテーブル表示

3. **可視化機能**:
- 元の価格系列(灰色)
- 5つの波を合成した信号(白色)
- 個々の波(カラフルな線)
- 各波の周期と振幅をテーブル表示

4. **カスタマイズ可能なパラメータ**:
- 分析ウィンドウサイズ(32-512バー)
- 表示/非表示の切り替え
- 価格ソースの選択(終値、始値など)

## 注意点

- このスクリプトは最新の`length`本のバーでのみ計算を行います
- 大きな`length`値を設定すると計算負荷が高くなる可能性があります
- フーリエ変換は過去データに対して行うため、リアルタイムの予測には適していません
- Pine Scriptの配列操作には制限があるため、完全なFFT(高速フーリエ変換)ではなくDFTを実装しています

このスクリプトを使用すると、価格変動を構成する主要な周期成分を視覚的に分析できます。各波の周期情報から、短期トレンドや長期トレンドの影響を理解するのに役立ちます。


TradingViewのPine Scriptで逆指値トラップリピート自動売買プログラムを作る

2025-04-05 08:59:38 | FX
Pineスクリプトで逆指値トラップリピート自動売買プログラムを作りたい。ソースコードを教えて。

# 逆指値トラップリピート自動売買プログラム (Pine Script)

以下は、TradingViewのPine Scriptで作成した逆指値トラップリピート自動売買プログラムの例です。このスクリプトは、価格が指定したレベルを突破した後に逆方向に動いた時にエントリーし、利益確定または逆指値で決済後に再度同じ条件でエントリーを試みます。

```pinescript
//@version=5
strategy("逆指値トラップリピート自動売買", overlay=true, margin_long=100, margin_short=100)

// 入力パラメータ
length = input.int(20, title="ATRの期間")
multiplier = input.float(1.5, title="ATR乗数", step=0.1)
stopLossMultiplier = input.float(2.0, title="ストップロス用ATR乗数", step=0.1)
takeProfitMultiplier = input.float(3.0, title="テイクプロフィット用ATR乗数", step=0.1)
trailingStopMultiplier = input.float(1.5, title="トレーリングストップ用ATR乗数", step=0.1)
useTrailingStop = input(true, title="トレーリングストップを使用する")
entryAfterBars = input.int(1, title="エントリー後の再エントリー禁止期間", minval=1)

// ATR計算
atr = ta.atr(length)

// ブレイクアウトレベル計算
longTrigger = high + multiplier * atr
shortTrigger = low - multiplier * atr

// ストップロスとテイクプロフィット計算
longStopLoss = low - stopLossMultiplier * atr
longTakeProfit = close + takeProfitMultiplier * atr
shortStopLoss = high + stopLossMultiplier * atr
shortTakeProfit = close - takeProfitMultiplier * atr

// トレーリングストップ計算
trailingStop = trailingStopMultiplier * atr

// 状態管理変数
var bool longTriggered = false
var bool shortTriggered = false
var int lastEntryBar = 0

// ブレイクアウト検出
if not longTriggered and not shortTriggered and not (strategy.position_size != 0)
if high >= longTrigger[1]
longTriggered := true
else if low <= shortTrigger[1]
shortTriggered := true

// ロングエントリー条件
longCondition = longTriggered and close < open and bar_index > lastEntryBar + entryAfterBars

// ショートエントリー条件
shortCondition = shortTriggered and close > open and bar_index > lastEntryBar + entryAfterBars

// エントリー実行
if longCondition
strategy.entry("Long", strategy.long)
strategy.exit("Long Exit", "Long", stop=longStopLoss, limit=longTakeProfit, trail_points=useTrailingStop ? trailingStop : na)
longTriggered := false
lastEntryBar := bar_index
if shortCondition
strategy.entry("Short", strategy.short)
strategy.exit("Short Exit", "Short", stop=shortStopLoss, limit=shortTakeProfit, trail_points=useTrailingStop ? trailingStop : na)
shortTriggered := false
lastEntryBar := bar_index

// ポジションがクローズしたらリセット
if strategy.position_size == 0
longTriggered := false
shortTriggered := false

// チャート表示
plot(longTrigger, color=color.green, style=plot.style_circles, title="Long Trigger")
plot(shortTrigger, color=color.red, style=plot.style_circles, title="Short Trigger")
plot(strategy.position_size > 0 ? longStopLoss : na, color=color.red, style=plot.style_linebr, title="Long Stop Loss")
plot(strategy.position_size > 0 ? longTakeProfit : na, color=color.green, style=plot.style_linebr, title="Long Take Profit")
plot(strategy.position_size < 0 ? shortStopLoss : na, color=color.red, style=plot.style_linebr, title="Short Stop Loss")
plot(strategy.position_size < 0 ? shortTakeProfit : na, color=color.green, style=plot.style_linebr, title="Short Take Profit")
```

## プログラムの説明

1. **入力パラメータ**:
- ATRの期間と乗数を調整可能
- ストップロス、テイクプロフィット、トレーリングストップの設定
- 再エントリー禁止期間の設定

2. **動作原理**:
- 高値/安値がATRベースのトリガーレベルを突破するとフラグが立つ
- その後価格が逆方向に動いた場合にエントリー
- ストップロスまたはテイクプロフィットで決済
- 決済後、再度同じ条件でエントリーを試みる

3. **リスク管理**:
- ATRベースの動的ストップロス
- トレーリングストップオプション
- 再エントリー禁止期間で過剰な取引を防止

このスクリプトはTradingViewのストラテジーテスターでバックテスト可能です。パラメータはご自身の取引スタイルに合わせて調整してください。

トレードステーションが使えるハイレバレッジのブローカーと倍率について

2025-04-05 08:54:00 | FX
トレードステーションが使えるハイレバレッジのブローカーはどこか?またレバレッジの倍率は最大何倍か?

**TradeStation(トレードステーション)が利用可能で、かつハイレバレッジ(高レバレッジ)を提供するブローカー**は限られています。
TradeStationは主に**米国市場(株式、先物、オプション)**向けのプラットフォームであり、**FXやCFD取引ではレバレッジ規制が厳しい**ため、特に**海外の規制緩和地域のブローカー**を探す必要があります。

---

### **1. TradeStationが使えるブローカーとレバレッジ**
#### **(1) TradeStation Global(Interactive Brokers提携)**
- **レバレッジ**:最大 **40倍**(FX/CFD)
- **特徴**:
- Interactive Brokers(IBKR)の流動性を利用したTradeStationの海外版。
- **FXやCFDでレバレッジ取引が可能**(ただし、米国規制の影響で最大40倍程度)。
- 日本からも口座開設可能(ただし、レバレッジは規制対象)。
- **デメリット**:
- 米国やEU規制下ではレバレッジが制限される(日本では最大25倍)。

#### **(2) TradeStation(米国本社)**
- **レバレッジ**:
- 株式:最大 **4倍**(米国規制、Reg T適用)
- 先物:**10~50倍**(商品による)
- FX(外国為替):**最大50倍**(ただし、米国規制で制限あり)
- **デメリット**:
- **FXやCFDではハイレバレッジ(100倍以上)は提供されない**。
- 日本からの口座開設は難しい場合がある。

---

### **2. ハイレバレッジ(100倍以上)を提供する代替ブローカー**
TradeStationで**100倍以上のレバレッジ**を求める場合、以下のような**海外FX/CFDブローカー**を検討する必要があります(ただし、TradeStationは使えず、MT4/MT5やcTraderなど別プラットフォームになります)。

| ブローカー名 | 最大レバレッジ | 主な取引商品 | 規制地域 |
|------------------|--------------|------------|---------|
| **XM** | **1000倍** | FX, CFD | キプロス(CySEC) |
| **Exness** | **無制限** | FX, CFD | キプロス・セーシェル |
| **FBS** | **3000倍** | FX, CFD | ベリーズ |
| **IC Markets** | **500倍** | FX, CFD | オーストラリア(ASIC) |
| **Pepperstone** | **500倍** | FX, CFD | オーストラリア・バハマ |

#### **特徴**:
- **ExnessやFBS**は**「無制限」や「3000倍」**のレバレッジを提供(ただし、規制の緩い地域のみ)。
- **IC MarketsやPepperstone**は信頼性が高いが、レバレッジは500倍程度。
- **日本規制(金融庁)**では最大25倍までなので、ハイレバレッジを求める場合は**海外ブローカー**を利用する必要がある。

---

### **結論**
- **「TradeStation + ハイレバレッジ」を両立させるのは難しい**(米国規制の影響で最大50倍程度)。
- **100倍以上のレバレッジを求める場合**は、**XM、Exness、FBS**などの海外FXブローカーを利用し、MT4/MT5で取引するのが現実的。
- **TradeStationを使いたい場合**は、レバレッジを諦めるか、**先物取引(50倍程度)**を活用する方法がある。

**※注意**:ハイレバレッジ取引はリスクが非常に高いため、資金管理が必須です。**規制の厳しいブローカー(ASIC、FCAなど)ではレバレッジが制限される**傾向があります。

※XMはトレードステーションが使えないことが判明。

MQL5でフーリエ変換プログラミング

2024-12-17 15:57:31 | FX

知っておくべきMQL5ウィザードのテクニック(第06回):フーリエ変換

知っておくべきMQL5ウィザードのテクニック(第06回):フーリエ変換

ジョセフ・フーリエによって導入されたフーリエ変換は、複雑なデータの波動点を単純な構成波に分解する手段です。この記事では、トレーダーにとって有益なこの機能を見てい...

      if(position==NULL)
         return(false);
      
      m_high.Refresh(-1);
      m_low.Refresh(-1);
      
      int _x=StartIndex();
      
      double _ft=ProcessFT(_x);
      double _type=_ft/100.0;
      
      double _atr=fmax(2.0*m_spread.GetData(_x)*m_symbol.Point(),m_high.GetData(_x)-m_low.GetData(_x))*(_type);
      
      double _sl=m_low.GetData(_x)-(m_step*_atr);
      
      double level =NormalizeDouble(m_symbol.Bid()-m_symbol.StopsLevel()*m_symbol.Point(),m_symbol.Digits());
      double new_sl=NormalizeDouble(_sl,m_symbol.Digits());
      double pos_sl=position.StopLoss();
      double base  =(pos_sl==0.0) ? position.PriceOpen() : pos_sl;
      
      sl=EMPTY_VALUE;
      tp=EMPTY_VALUE;
      if(new_sl>base && new_sl<level)
         sl=new_sl;
//---
   return(sl!=EMPTY_VALUE);
  }
//+------------------------------------------------------------------+
//| Checking trailing stop and/or profit for short position.         |
//+------------------------------------------------------------------+
bool CTrailingFT::CheckTrailingStopShort(CPositionInfo *position,double &sl,double &tp)
  {
//--- check
      if(position==NULL)
         return(false);
   
      m_high.Refresh(-1);
      m_low.Refresh(-1);
      
      int _x=StartIndex();
      
      double _ft=ProcessFT(_x);
      double _type=_ft/100.0;
   
      double _atr=fmax(2.0*m_spread.GetData(_x)*m_symbol.Point(),m_high.GetData(_x)-m_low.GetData(_x))*(_type);
      
      double _sl=m_high.GetData(_x)+(m_step*_atr);
      
      double level =NormalizeDouble(m_symbol.Ask()+m_symbol.StopsLevel()*m_symbol.Point(),m_symbol.Digits());
      double new_sl=NormalizeDouble(_sl,m_symbol.Digits());
      double pos_sl=position.StopLoss();
      double base  =(pos_sl==0.0) ? position.PriceOpen() : pos_sl;
      
      sl=EMPTY_VALUE;
      tp=EMPTY_VALUE;
      if(new_sl<base && new_sl>level)
         sl=new_sl;
//---
      return(sl!=EMPTY_VALUE);
  }
//+------------------------------------------------------------------+
//| Fourier Transform                                                |
//| INPUT PARAMETERS                                                 |
//|     Index   -   int, read index within price buffer.             |
//| OUTPUT                                                           |
//|     double  -   forecast change in price                         |
//+------------------------------------------------------------------+
double CTrailingFT::ProcessFT(int Index)
   {
      double _ft=0.0;
      
      int _index=Index;//+StartIndex();
      
      m_close.Refresh(-1);
      
      double _a[];
      matrix _output;
      al_complex _f[];
      
      //6 data points, 5 epicycles
   
      ArrayResize(_a,6);ArrayInitialize(_a,0.0);
      _output.Init(6,5);_output.Fill(0.0);
      
      for(int p=0;p<6;p++)
      {
         _a[p]=m_close.GetData(_index+p)-m_close.GetData(_index+p+1);
      }
      
      FFT.FFTR1D(_a,5,_f);
       
      for(int p=0;p<6;p++)
      {
         for(int s=0;s<5;s++)
         {
            double _divisor=(1.0/5),_angle=(p);_angle/=6;
            _output[p][s]=(_divisor*_a[p]*MathExp(-2.0*__PI*(_f[s].im/_f[s].re)*_angle));
         }
      }
      
      double _close=m_close.GetData(_index)>m_close.GetData(_index+1);
      
      int _max_index=0;
      double _max=fabs(_output[5][_max_index]);
      for(int s=0;s<5;s++)
      {
         if(_max<fabs(_output[5][s]))
         {
            _max_index=s;
            _max=fabs(_output[5][s]);
         }
      }
      
      _ft=(_output[5][_max_index]/fmax(m_symbol.Point(),fabs(_output[5][_max_index])+fabs(_close)))*100.0;
      
      return(_ft);
   }
//+----------------------------------------

任意の期間のFXチャートをフーリエ変換して10個の成分として表示するプログラム

2024-12-16 22:20:03 | FX
以下は、前回の「離散データを補間して連続化するインジケータ」に続けて、その生成された「連続データ」からフーリエ変換を行い、10個の周波数成分を三角関数(サイン・コサイン)展開で表示するサンプルコード例です。


ポイント

前回のインジケータをベースにし、補間後のSmoothBufferに対して離散的なフーリエ変換(DFT)を行います。
基本的なDFTを用いて、k=1~10程度の低次のサイン・コサイン成分を求めます。
フーリエ級数展開として、
𝑥[𝑛]𝑎0+𝑘=1〜10[𝑎𝑘cos(2𝜋𝑘𝑛/𝑁)+
𝑏𝑘sin(2𝜋𝑘𝑛/𝑁)]
x[n]≈a0+k=110[akcos(2πkn/N)+
bksin(2πkn/N)]
の形の係数a_k、b_kを計算し、結果をチャート上に表示(Comment)します。



簡易実装のため、滑らかな曲線を生成するインジケータ内部で完結しています。




a_k、b_kの求め方:
𝑎𝑘=2𝑁𝑛=0
𝑁1𝑥[𝑛]cos(2𝜋𝑘𝑛𝑁)
,
𝑏𝑘=2𝑁𝑛=0
𝑁1𝑥[𝑛]sin(2𝜋𝑘𝑛𝑁)
ak=N2
n=0N−1
x[n]cos(N2πkn),bk
=N2
n=0N−1
x[n]sin(N2πkn)
※a_0はk=0の場合で、
𝑎0=1𝑁𝑛=0𝑁1𝑥[𝑛]a 0
=N1
n=0N−1
x[n]

#property copyright "YourCompany"
#property link "http://www.example.com"
#property indicator_separate_window false
#property indicator_buffers 1
#property indicator_color1 Blue
#property indicator_width1 2
#property indicator_style1 STYLE_SOLID

extern int InterpolationPoints=5;
extern int NumOfComponents=10; // 表示するフーリエ成分数

double SmoothBuffer[];

//------------------------------------------
int init()
{
IndicatorBuffers(1);
SetIndexStyle(0, DRAW_LINE);
SetIndexBuffer(0, SmoothBuffer);

IndicatorShortName("Continuous Curve from M5 + Fourier Components");
return(0);
}

//------------------------------------------
int start()
{
int counted_bars = IndicatorCounted();
if(counted_bars < 0) return(-1);

int total_bars = Bars;
string sym = Symbol();
int timeFrame = PERIOD_M5;

int limit = MathMin(1000, total_bars);
ArraySetAsSeries(SmoothBuffer,true);

// M5の終値取得
double closeArray[];
ArraySetAsSeries(closeArray, true);
ArrayResize(closeArray, limit);
for(int i=0; i<limit; i++)
{
closeArray[i] = iClose(sym, timeFrame, i);
}

// 線形補間によるスムースデータ生成
for(int i=0; i<limit*InterpolationPoints; i++)
SmoothBuffer[i] = EMPTY_VALUE;

int outIndex=0;
for(int i=limit-1; i>0; i--)
{
double startVal = closeArray[i];
double endVal = closeArray[i-1];
for(int j=0; j<InterpolationPoints; j++)
{
double t = (double)j/(double)InterpolationPoints;
double val = startVal*(1.0-t) + endVal*t;
SmoothBuffer[outIndex] = val;
outIndex++;
}
}
// 最後の点
SmoothBuffer[outIndex] = closeArray[0];
int N = outIndex+1; // 補間後のデータ数

// DFTによるフーリエ係数算出
// a0, a_k, b_kを計算
// a0 = (1/N)*Σ x[n]
double a0=0.0;
for(int n=0; n<N; n++)
a0 += SmoothBuffer[n];
a0 /= N;

double a[], b[];
ArrayResize(a, NumOfComponents+1);
ArrayResize(b, NumOfComponents+1);

// k=1~NumOfComponentsまで計算
for(int k=1; k<=NumOfComponents; k++)
{
double sum_cos=0.0;
double sum_sin=0.0;
for(int n=0; n<N; n++)
{
double theta = 2.0*MathPi*k*n/(double)N;
sum_cos += SmoothBuffer[n]*MathCos(theta);
sum_sin += SmoothBuffer[n]*MathSin(theta);
}
// a_k, b_kの計算
a[k] = (2.0/(double)N)*sum_cos;
b[k] = (2.0/(double)N)*sum_sin;
}

// 取得したフーリエ成分を表示
// ここではChart上のComment関数を使って表示する
// a0 と a_k, b_kを列挙
string commentStr = "Fourier Components: ";
commentStr += StringFormat("a0 = %.5f ", a0);
for(int k=1; k<=NumOfComponents; k++)
{
commentStr += StringFormat(" k=%d: a%d=%.5f, b%d=%.5f ", k, k, a[k], k, b[k]);
}

Comment(commentStr);

return(0);
}

//------------------------------------------
int deinit()
{
Comment("");
return(0);
}


説明
元データ生成部分:
前回のインジケータと同様に、M5終値データを取得し、InterpolationPointsに応じて線形補間してSmoothBufferに格納。これが「連続的な曲線」に相当します。

フーリエ成分計算:
SmoothBufferに格納されたN点のデータx[n]に対して、DFTを実行し、以下を求めます。




a0 = (1/N)*Σ x[n] (直流成分)
a_k, b_k = 周波数 k のコサイン・サイン係数
計算後、a0、a_k、b_kをComment関数でチャート上に表示します。

拡張・改良:

周波数成分数NumOfComponentsはパラメータで指定。
より大きなデータ数、より高度な平滑化にも対応可能。
FFT(高速フーリエ変換)を実装すればパフォーマンス向上も可能ですが、ここでは簡易的なDFT。
表示結果:
チャート上にはa0をはじめ、a1,b1~a10,b10までの値が表示され、これにより元の波形が10次までのサイン・コサイン成分で近似できることが分かります。

以上のコード例により、前段で生成した「連続データ」をフーリエ変換して、10個の三角関数成分として表示することが可能になります。

※AIで予測とかマヌケな奴等が多いが、好きな時に好きなタイミングで好きなように介入して意図的に相場をいじれるようなものを予測なんかできるわけがない。
フーリエ変換して不当な介入・操作が行われた時期を特定し、相場にその変換が現れる前に検知するしかないのだ。

例えばレンジ相場が続いていたのにいきなり急激なトレンド・大きな変化が発生した場合、その変化が現れる前に不当な介入・操作が必ずあるのだ。
その不当な介入・操作はフーリエ変換して分解した波の成分の中に含まれているのだ。

また逆にトレンドが続いていたのにいきなりレンジ相場になってしまった場合にも同じことが言える。何者かが不当な介入・操作をしたからトレンド相場からいきなりレンジ相場になるのだ。

レンジ⇔トレンドの切り替えの原因となる不当介入・操作の波を検知すべし!


連続的なカーブを描くMQL4プログラム

2024-12-16 21:54:56 | FX
任意の期間の五分足のFXチャートの離散データを連続データ曲線にして表示させるMQL4プログラムを書いて。




【FXチャートのデータ変換】
以下は、MQL4を用いて、任意の期間の5分足(M5)チャート上の離散的な価格データ(例えばClose価格)をもとに、連続的なカーブを表示するカスタムインジケータの一例です。
ここでは、基本的な考え方として、5分足の終値データを取得し、それらをスプライン補間や単純な線形補間でなめらかな曲線に近似したラインを描画します。
以下のコードは一例であり、実行環境や必要に応じて適宜修正ください。

ポイント:

カスタムインジケータとして作成。
期間はチャート上で選択した期間に関係なく、内部でM5のデータを取得して使用。
シンプルな方法として、5分足の終値データから1分ごとの補間を行い、補間結果をバッファに格納し、ライン表示。
より高度な平滑化(スプライン補間)を実装したい場合は、別途補間用関数を定義。ここでは簡易的な線形補間例を示す。
コード例(IndicatorName.mq4)
#property copyright "YourCompany"
#property link "http://www.example.com"
#property indicator_separate_window false // メインチャートに表示
#property indicator_buffers 1
#property indicator_color1 Blue
#property indicator_width1 2
#property indicator_style1 STYLE_SOLID

// ---- 入力パラメータ ----
// どれくらい細かく補間するか(1バー=5分なので、その中間点を何点挿入するか)
// 例えば5とすれば、5分間を5等分して1分刻みに近似的なポイントを生成
extern int InterpolationPoints=5;

// ---- バッファ ----
double SmoothBuffer[];

//------------------------------------------
// カスタムインジケータ初期化
int init()
{
IndicatorBuffers(1);
SetIndexStyle(0, DRAW_LINE);
SetIndexBuffer(0, SmoothBuffer);

// インジケータ名設定
IndicatorShortName("Continuous Curve from M5 data");
return(0);
}

//------------------------------------------
// スタート時処理(旧OnCalculate的な役割 MQL4)
int start()
{
int counted_bars = IndicatorCounted();
if(counted_bars < 0) return(-1);

// 最新バー更新用に全バー再計算を回避するため、必要なら最初から計算
// 今回はシンプルに全部計算
int total_bars = Bars;

// M5データ取得用
// 現在のチャートシンボル・M5から取得
string sym = Symbol();
int timeFrame = PERIOD_M5;

// 必要な過去バー数 (現在表示中のチャートバー数より少なくてもOK)
// 補間を行うので余裕を持った数
int limit = MathMin(1000, total_bars);

// 一旦すべてのバッファをクリア
for(int i=0; i<limit*InterpolationPoints; i++)
SmoothBuffer[i] = EMPTY_VALUE;

// M5バーのクローズ価格を配列に取得
double closeArray[];
if(!SeriesInfoInteger(sym, timeFrame, SERIES_BARS_COUNT, limit)) limit = Bars; // 念のため
ArraySetAsSeries(SmoothBuffer,true);
ArraySetAsSeries(closeArray, true);

// iCloseで取得する場合
ArrayResize(closeArray, limit);
for(int i=0; i<limit; i++)
{
closeArray[i] = iClose(sym, timeFrame, i);
}

// 補間:
// 5分足間をInterpolationPoints分割する場合、たとえばInterpo=5なら
// 1つのM5バーから次のM5バーへの間に、4つの中間点を線形で補間
// バッファには( limit-1 )*InterpolationPoints + 1 個の点が並ぶイメージ
int outIndex=0;
for(int i=limit-1; i>0; i--)
{
double startVal = closeArray[i];
double endVal = closeArray[i-1];
// 1区間(5分)をInterpolationPoints分割
for(int j=0; j<InterpolationPoints; j++)
{
double t = (double)j/(double)InterpolationPoints;
double val = startVal*(1.0-t) + endVal*t; // 線形補間
SmoothBuffer[outIndex] = val;
outIndex++;
}
}

// 最後の終点
SmoothBuffer[outIndex] = closeArray[0];

return(0);
}

//------------------------------------------
int deinit()
{
return(0);
}
説明
概要:
このインジケータは現在のチャート上で表示されますが、データは常にM5足の価格データ(終値)を取得します。そのため、チャートが1時間足だろうが日足だろうが、内部的にはM5の価格データを用いて補間した連続線を描画します。

補間方法:
上記サンプルでは簡易な線形補間を実装しています。例えば、5分足同士の間を指定のInterpolationPoints個に分割し、直線的になめらかな値を生成します。より平滑なカーブを得たい場合は、スプライン補間など高度な数値補間手法を独自実装する必要があります。

表示方法:
DRAW_LINEスタイルでSmoothBuffer内の値をチャート上にラインとして描画します。
InterpolationPointsを増やせば増やすほど、より密なデータ点を生成し、実質的に滑らかなカーブが表示されます。

パフォーマンス等:
例示のコードは特に最適化にはこだわっていません。必要に応じてlimitを調整する、計算部分を軽量化する等の工夫が必要です。また、描画バッファサイズやインジケータ呼び出し頻度についても調整可能です。

上記のサンプルコードをベースとして、より高度な補間、平滑化処理などを加えることで、任意の期間のM5データから連続的なカーブを描画することが可能になります。

FXのチャートは離散データである。任意の期間の離散データを補完して連続データ曲線のチャートをデッチ上げ、フーリエ変換して有限個の三角関数の成分として分解したいのだ。
まずは飛び飛びで歯抜けになっている離散データを連続データとしてデッチ上げるプログラムをChatGPTに書かせてみた。

動くかどうかは知らんけど。


一目均衡表を指標・サインに用いたEA

2024-08-07 21:30:57 | FX

EAで一目均衡表を使う(サンプルソース)  –  ぷろぐらむFX

EAで一目均衡表を使う(サンプルソース) – ぷろぐらむFX



このサイトは一目均衡表を使ったEAのソースコードを掲載してくれている。

一目均衡表は複雑怪奇にして難解だ。
だからこそしっかり仕組みを理解して使いこなそうではないか!

一目均衡表を使ったEAの存在を初めて知った。一目均衡表はレンジに弱いらしい。

だからフーリエ変換でトレンド発生のきっかけとなる波を検知し、一目均衡表のシグナルと照らし合わせて逆指値トラップを張るようにすればよい。

そしてレンジ発生の兆候を検知したら利確・損切りして撤収し、次のトレンドを待てば良い。

その他の情報はGoogleで
「一目均衡表 自動売買」
で検索すべし!

MQL4でPythonを呼び出す方法

2023-05-13 12:23:31 | FX

MQL4でPythonを呼び出す方法

MQL4 から Python を呼び出す方法はいくつかあります。1 つの方法は、Python プログラムをコンパイルして DLL ファイルにしてから、MQL4 から DLL ファイルをロードすることです。もう 1 つの方法は、Python スクリプトを実行するサーバーを使用して、MQL4 から Python スクリプトを呼び出すことです。

DLL ファイルを使用して MQL4 から Python を呼び出すには、次の手順に従います。

Python プログラムをコンパイルして DLL ファイルにします。
DLL ファイルを MQL4 のインストールディレクトリにコピーします。
MQL4 のソースファイルで、次の行を使用して DLL ファイルをロードします。


#include

HMODULE hModule = LoadLibrary("python.dll");

if (hModule == NULL) {
// エラー処理
}


DLL 内の関数を呼び出すには、次の構文を使用します。

FARPROC pFunc = GetProcAddress(hModule, "FunctionName");

if (pFunc == NULL) {
// エラー処理
}

int result = (int)pFunc();

サーバーを使用して MQL4 から Python スクリプトを呼び出すには、次の手順に従います。

Python スクリプトを実行するサーバーをセットアップします。
MQL4 のソースファイルで、次の行を使用してサーバーに接続します。


#include
#include

using namespace std;

int main() {
// サーバーに接続
string host = "localhost";
int port = 5000;

Socket socket(host, port);

if (!socket.isConnected()) {
// エラー処理
}

// Python スクリプトを実行する
string command = "python myscript.py";

socket.write(command.c_str());

// 応答を待つ
char buffer[1024];

int bytesReceived = socket.read(buffer, 1024);

if (bytesReceived == -1) {
// エラー処理
}

// 応答を出力する
cout <

// サーバーを切断する
socket.close();

return 0;
}


一目均衡表を使った逆指値自動売買EA

2023-04-09 01:24:50 | FX
一目均衡表を使った逆指値自動売買EAのコードを書いてください。
 
一目均衡表を使った逆指値自動売買EAのコードの例を以下に示します。このコードは、Pythonで書かれたもので、Backtraderと呼ばれるフレームワークを使用しています。これは、一目均衡表の計算やトレードシグナルの生成などの多くの機能を提供してくれます。
 
import backtrader as bt
import backtrader.indicators as btind
 
class IchimokuStrategy(bt.Strategy):
params = (
('tenkan_period', 9),
('kijun_period', 26),
('senkou_period', 52),
('senkou_offset', 26),
('stop_loss', 100),
('take_profit', 200),
('trade_size', 10000),
)
 
def __init__(self):
self.ichimoku = btind.Ichimoku(self.data)
self.tenkan_sen = self.ichimoku.tenkan_sen
self.kijun_sen = self.ichimoku.kijun_sen
self.senkou_span_a = self.ichimoku.senkou_span_a
self.senkou_span_b = self.ichimoku.senkou_span_b
 
def next(self):
if self.position:
if self.data.close[0] < self.senkou_span_a[0]:
self.close()
elif self.data.close[0] > self.senkou_span_b[0]:
self.close()
 
else:
if self.tenkan_sen[0] > self.kijun_sen[0] and self.data.close[0] > self.senkou_span_a[0]:
self.buy(size=self.params.trade_size, exectype=bt.Order.Stop, price=self.data.close[0] + self.params.stop_loss)
self.sell(size=self.params.trade_size, exectype=bt.Order.Limit, price=self.data.close[0] + self.params.take_profit)
 
elif self.tenkan_sen[0] < self.kijun_sen[0] and self.data.close[0] < self.senkou_span_b[0]:
self.sell(size=self.params.trade_size, exectype=bt.Order.Stop, price=self.data.close[0] - self.params.stop_loss)
self.buy(size=self.params.trade_size, exectype=bt.Order.Limit, price=self.data.close[0] - self.params.take_profit)
↑この部分が文法エラーだから直せとよ!
このコードでは、IchimokuStrategyという名前のクラスが定義されています。このクラスは、backtrader.Strategyクラスを継承しており、バックテストやトレードシグナルの生成を担当します。paramsには、トレードに必要なパラメーターが含まれています。
 
IchimokuStrategyでは、__init__メソッドで一目均衡表のインジケーターを初期化しています。また、nextメソッドで、現在のポジションと市場状況を分析し、売買の条件を決定します。
 
売買ルールは以下の通りです。
 
ポジションがなく、テンカン線が基準線を上回り、クロージング価格が先行スパンAよりも高い場合、指定されたサイズでロングポジションを取得します。同時に、ストップロス価格をクロージング価格に設定し、テイクプロフィット価格をクロージング価格に加えたものに設定された価格でリミット注文を出します。
ポジションがなく、テンカン線が基準線を下回り、クロージング価格が先行スパンBよりも低い場合、指定されたサイズでショートポジションを取得します。同時に、ストップロス価格をクロージング価格に設定し、テイクプロフィット価格をクロージング価格から差し引いたものに設定された価格でリミット注文を出します。
ポジションがある場合、クロージング価格が先行スパンAよりも低い場合、ポジションをクローズします。
ポジションがある場合、クロージング価格が先行スパンBよりも高い場合、ポジションをクローズします。
これらのルールに基づいて、IchimokuStrategyクラスがバックテストを実行し、トレードを行います。このコードは、実際の取引に使用する前に、さまざまなパラメータを調整して、最適なパフォーマンスを得る必要があります。
 
runfile('C:/Users/User/untitled0.py', wdir='C:/Users/User')
  File "C:\Users\User\untitled0.py", line 33
    elif:
    ^
SyntaxError: invalid syntax
 

import backtrader as bt
import backtrader.indicators as btind

class IchimokuStrategy(bt.Strategy):
    params = (
('tenkan_period', 9),
('kijun_period', 26),
('senkou_period', 52),
('senkou_offset', 26),
('stop_loss', 100),
('take_profit', 200),
('trade_size', 10000),
)

def __init__(self):
    self.ichimoku = btind.Ichimoku(self.data)
self.tenkan_sen = self.ichimoku.tenkan_sen
self.kijun_sen = self.ichimoku.kijun_sen
self.senkou_span_a = self.ichimoku.senkou_span_a
self.senkou_span_b = self.ichimoku.senkou_span_b

def next(self):
    if self.position:
        if self.data.close[0] < self.senkou_span_a[0]:
            self.close()
    elif self.data.close[0] > self.senkou_span_b[0]:
        self.close()

    else:
        if self.tenkan_sen[0] > self.kijun_sen[0] and self.data.close[0] > self.senkou_span_a[0]:
            self.buy(size=self.params.trade_size, exectype=bt.Order.Stop, price=self.data.close[0] + self.params.stop_loss)
            self.sell(size=self.params.trade_size, exectype=bt.Order.Limit, price=self.data.close[0] + self.params.take_profit)        
    elif:
        self.tenkan_sen[0] < self.kijun_sen[0] and self.data.close[0] < self.senkou_span_b[0]:
            self.sell(size=self.params.trade_size, exectype=bt.Order.Stop, price=self.data.close[0] - self.params.stop_loss)
            self.buy(size=self.params.trade_size, exectype=bt.Order.Limit, price=self.data.close[0] - self.params.take_profit)

↑ここの文法エラーがどうにもならん!


一目均衡表は最強!? 一目均衡表の使い方

2023-04-02 00:57:11 | FX

一目均衡表は最強!売買シグナルの見方3つと実践での使い方を紹介

一目均衡表は最強!売買シグナルの見方3つと実践での使い方を紹介

FXの一目均衡表とは?一目山人(いちもくさんじん)こと、細田悟一氏が、2千人のスタッフと、7年かけて編み出した純国産のテクニカル分析が一目均衡表(いちもくきんこうひ...

FXの教科書

一目均衡表は最強!だそうだ。


FXの任意のチャートをフーリエ変換するMQL4プログラム

2023-03-13 20:30:47 | FX

FXの任意のチャートをフーリエ変換するプログラムをMQL4で書いて。

MQL4でFXチャートをフーリエ変換するプログラムを作成するには、まずチャートから価格データを収集し、それを数値データに変換する必要があります。その後、収集した価格データをフーリエ変換するためのアルゴリズムを実装する必要があります。

以下は、MQL4でFXチャートのフーリエ変換を行うプログラムの一例です。

// チャートから価格データを収集する
double prices[];
int limit;
int counted_bars = IndicatorCounted();
if(counted_bars < 0) return(-1);
if(counted_bars > 0) counted_bars--;
limit = Bars - counted_bars;
ArraySetAsSeries(prices, true);
for(int i = 0; i < limit; i++) {
    prices[i] = Close[i];
}

// フーリエ変換を行う
Complex fft[];
ArraySetAsSeries(fft, true);
ArrayResize(fft, limit);
for(int i = 0; i < limit; i++) {
    fft[i].re = prices[i];
    fft[i].im = 0;
}
FourierTransform(fft, FFT_FORWARD);

// 結果を表示する
for(int i = 0; i < limit; i++) {
    double freq = i / (Period() * limit);
    double amplitude = MathSqrt(fft[i].re*fft[i].re + fft[i].im*fft[i].im);
    Print("Frequency: ", freq, ", Amplitude: ", amplitude);
}

このプログラムでは、Close価格を収集し、FourierTransform関数を使用してフーリエ変換を実行します。結果は、周波数と振幅のペアのリストとして表示されます。

ただし、このプログラムはFXチャートのヒストリカルデータを使用してフーリエ変換を行うだけで、リアルタイムでの解析には適していません。また、フーリエ変換を使用する場合、周期的な信号に対してのみ有効であるため、FXチャートの場合には限界があります。


レンジブレイクアウト逆指値トラップリピートEA

2023-03-13 20:27:24 | FX

ボックスブレイクアウトを狙うためのMT4インジケーター集

ボックスブレイクアウトを狙うためのMT4インジケーター集

今回はボックスブレイクアウトを狙う際に便利なインジケーターをご紹介します。 ボックスブレイクアウトは別名「タイムレンジブレイク」とも呼ばれ、特定の時間帯の値幅をブ...

元FXコーチによるFX情報商材検証ブログ

レンジをボックスで囲み、ボックスを突破した所をトレンド発生と判断し、逆指値トラップをはる手法。

ダマシがあるので、突破したらすぐ逆指値を入れるのではなく、任意の間隔を開けてから逆指値を入れるようにするといいらしい。

自動でボックスを作り、突破して指定のpipes離れたら逆指値を自動で入れるEAを開発すべきだ。


にあるようなフーリエ変換インジケータを併用すると、さらに効果的と思われる。

レンジ判定にはpythonによるディープラーニングプログラムの適用が望ましい。

ex.4ファイルをGhidraで逆コンパイルできますか?

2023-03-13 17:49:54 | FX
ChatGPTで超ヤバい質問をしてみた。

MT4のex.4ファイルをGhidraで逆コンパイルすることはできますか?

Ghidraは多くのバイナリ形式に対応していますが、MT4のex.4ファイルがどのような形式であるかによっては、Ghidraで逆コンパイルできるかどうかが異なります。

一般的に、Ghidraはプログラムのバイナリを解析し、アセンブリ言語に変換することができますが、そのバイナリ形式がサポートされている必要があります。MT4のex.4ファイルがGhidraで逆コンパイルできるかどうかは、ファイルがどのような形式であるかによって異なります。

MT4のex.4ファイルが、Ghidraがサポートしているバイナリ形式の1つであるx86アーキテクチャでコンパイルされている場合、Ghidraはそれを逆コンパイルすることができます。ただし、MT4のex.4ファイルが別のアーキテクチャでコンパイルされている場合、Ghidraは逆コンパイルできません。

したがって、MT4のex.4ファイルをGhidraで逆コンパイルできるかどうかを確認するには、ファイルのバイナリ形式が何であるかを特定する必要があります。ファイルのバイナリ形式がx86アーキテクチャである場合は、Ghidraを使用して逆コンパイルすることができます。そうでない場合は、他のツールを使用する必要があるかもしれません。

Spectrometr separateのソースコード

2023-03-07 20:46:36 | FX

#property copyright ""
#property link ""

#property indicator_separate_window
#property indicator_buffers 8
#property indicator_color1 Red
#property indicator_color2 Orange
#property indicator_color3 Yellow
#property indicator_color4 Lime
#property indicator_color5 Blue
#property indicator_color6 DodgerBlue
#property indicator_color7 DarkViolet
#property indicator_color8 DimGray

//---- input parameters

extern int iPeriod=240;
extern int iStartFrom=1;
extern string AddToObjName="1";
extern color HandlerColor=Gray;
extern color TextColor=Black;

string ObjNPref="Spectrometr";
string ShortName;

int LastTime;
double A[],B[],R[],F[];

//---- buffers
double ExtMapBuffer1[];
double ExtMapBuffer2[];
double ExtMapBuffer3[];
double ExtMapBuffer4[];
double ExtMapBuffer5[];
double ExtMapBuffer6[];
double ExtMapBuffer7[];
double ExtMapBuffer8[];


int LastLeftBar;
int LastRightBar;
int LastLeftTime;
int LastRightTime;
int LastStartFrom;
int LastiStartFrom;
int LastiPeriod;

//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int init(){
ShortName=ObjNPref+"_"+AddToObjName;
ObjNPref=ObjNPref+"_"+AddToObjName+"_";



IndicatorShortName(ShortName);

SetIndexStyle(0,DRAW_LINE,DRAW_LINE,2);
SetIndexBuffer(0,ExtMapBuffer1);

SetIndexStyle(1,DRAW_LINE,DRAW_LINE,2);
SetIndexBuffer(1,ExtMapBuffer2);

SetIndexStyle(2,DRAW_LINE,DRAW_LINE,2);
SetIndexBuffer(2,ExtMapBuffer3);

SetIndexStyle(3,DRAW_LINE,DRAW_LINE,2);
SetIndexBuffer(3,ExtMapBuffer4);

SetIndexStyle(4,DRAW_LINE,DRAW_LINE,2);
SetIndexBuffer(4,ExtMapBuffer5);

SetIndexStyle(5,DRAW_LINE,DRAW_LINE,2);
SetIndexBuffer(5,ExtMapBuffer6);

SetIndexStyle(6,DRAW_LINE,DRAW_LINE,2);
SetIndexBuffer(6,ExtMapBuffer7);

SetIndexStyle(7,DRAW_LINE,DRAW_LINE,2);
SetIndexBuffer(7,ExtMapBuffer8);

//----
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
int deinit()
{
//----
fObjDeleteByPrefix(ObjNPref);
//----
return(0);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function |
//+------------------------------------------------------------------+

int start(){


string ObjName=ObjNPref+"ヘ裘・ ・湜";

if(ObjectFind(ObjName)!=WindowFind(ShortName)){
LastStartFrom=iStartFrom;//
LastLeftBar=iStartFrom+iPeriod-1;
LastRightBar=iStartFrom;
LastLeftTime=Time[LastLeftBar];
LastRightTime=Time[LastRightBar];
fObjTrendLine(ObjName,LastLeftTime,0,LastRightTime,0,false,HandlerColor,3,WindowFind(ShortName),0,true);
}

int NowLeftTime=ObjectGet(ObjName,OBJPROP_TIME1);
int NowRightTime=ObjectGet(ObjName,OBJPROP_TIME2);
if(NowRightTime>Time[1])NowRightTime=Time[1];

int NowLeftBar=iBarShift(NULL,0,NowLeftTime,false);
int NowRightBar=iBarShift(NULL,0,NowRightTime,false);
iPeriod=NowLeftBar-NowRightBar+1;
int LastStartFromTime=iBarShift(NULL,0,LastRightTime,false);
iStartFrom=(NowRightBar-LastStartFromTime)+LastStartFrom;

LastStartFrom=iStartFrom;
LastLeftBar=iStartFrom+iPeriod-1;
LastRightBar=iStartFrom;
LastLeftTime=Time[LastLeftBar];
LastRightTime=Time[LastRightBar];
fObjTrendLine(ObjName,LastLeftTime,0,LastRightTime,0,false,HandlerColor,3,WindowFind(ShortName),0,true);

ObjName=ObjNPref+"iPeriod";
fObjLabel(ObjName,80,5,"Period: "+iPeriod,3,TextColor,8,WindowFind(ShortName),"Arial Black",false);
ObjName=ObjNPref+"iStartFrom";
fObjLabel(ObjName,10,5,"StartFrom: "+iStartFrom,3,TextColor,8,WindowFind(ShortName),"Arial Black",false);


//=====================================================================================================

static int LastBars=0;

if(iStartFrom==LastiStartFrom && iPeriod==LastiPeriod)if(Bars
LastiStartFrom=iStartFrom;
LastiPeriod=iPeriod;
LastBars=Bars;

ArrayInitialize(ExtMapBuffer1,EMPTY_VALUE);
ArrayInitialize(ExtMapBuffer2,EMPTY_VALUE);
ArrayInitialize(ExtMapBuffer3,EMPTY_VALUE);
ArrayInitialize(ExtMapBuffer4,EMPTY_VALUE);
ArrayInitialize(ExtMapBuffer5,EMPTY_VALUE);
ArrayInitialize(ExtMapBuffer6,EMPTY_VALUE);
ArrayInitialize(ExtMapBuffer7,EMPTY_VALUE);
ArrayInitialize(ExtMapBuffer8,EMPTY_VALUE);

//=====================================================================================================

int tPeriod;
double tVal_0;
double tVal_1;
double tB;
double tMaxDev;
double tStdError;
double tRSquared;
double Arr[];

fLinearRegressionAll2(iStartFrom,iStartFrom+iPeriod-1,0,tPeriod,tVal_0,tVal_1,tB,tMaxDev,tStdError,tRSquared,Arr);

//======================================================================================================

fFurie(Arr,A,B,R,F);
//======================================================================================================

int N=ArraySize(Arr);
for(int i=0;i
int ii=i+iStartFrom;
ExtMapBuffer1[ii]=A[1]*MathSin(1*6.28*i/(N-1))+B[1]*MathCos(1*6.28*i/(N-1));
ExtMapBuffer2[ii]=A[2]*MathSin(2*6.28*i/(N-1))+B[2]*MathCos(2*6.28*i/(N-1));
ExtMapBuffer3[ii]=A[3]*MathSin(3*6.28*i/(N-1))+B[3]*MathCos(3*6.28*i/(N-1));
ExtMapBuffer4[ii]=A[4]*MathSin(4*6.28*i/(N-1))+B[4]*MathCos(4*6.28*i/(N-1));
ExtMapBuffer5[ii]=A[5]*MathSin(5*6.28*i/(N-1))+B[5]*MathCos(5*6.28*i/(N-1));
ExtMapBuffer6[ii]=A[6]*MathSin(6*6.28*i/(N-1))+B[6]*MathCos(6*6.28*i/(N-1));
ExtMapBuffer7[ii]=A[7]*MathSin(7*6.28*i/(N-1))+B[7]*MathCos(7*6.28*i/(N-1));
ExtMapBuffer8[ii]=A[8]*MathSin(8*6.28*i/(N-1))+B[8]*MathCos(8*6.28*i/(N-1));
}

//======================================================================================================
//・湜・籵
fObjTrendLine(ObjNPref+"1",Time[0]+Period()*60*3,R[1],Time[0]+Period()*60*3,-R[1],false,indicator_color1,8,WindowFind(ShortName),0,false);
fObjTrendLine(ObjNPref+"2",Time[0]+Period()*60*5,R[2],Time[0]+Period()*60*5,-R[2],false,indicator_color2,8,WindowFind(ShortName),0,false);
fObjTrendLine(ObjNPref+"3",Time[0]+Period()*60*7,R[3],Time[0]+Period()*60*7,-R[3],false,indicator_color3,8,WindowFind(ShortName),0,false);
fObjTrendLine(ObjNPref+"4",Time[0]+Period()*60*9,R[4],Time[0]+Period()*60*9,-R[4],false,indicator_color4,8,WindowFind(ShortName),0,false);
fObjTrendLine(ObjNPref+"5",Time[0]+Period()*60*11,R[5],Time[0]+Period()*60*11,-R[5],false,indicator_color5,8,WindowFind(ShortName),0,false);
fObjTrendLine(ObjNPref+"6",Time[0]+Period()*60*13,R[6],Time[0]+Period()*60*13,-R[6],false,indicator_color6,8,WindowFind(ShortName),0,false);
fObjTrendLine(ObjNPref+"7",Time[0]+Period()*60*15,R[7],Time[0]+Period()*60*15,-R[7],false,indicator_color7,8,WindowFind(ShortName),0,false);
fObjTrendLine(ObjNPref+"8",Time[0]+Period()*60*17,R[8],Time[0]+Period()*60*17,-R[8],false,indicator_color8,8,WindowFind(ShortName),0,false);


return(0);
}
//+------------------------------------------------------------------+

//浯蔡頌・湜跫韜 ・糺・鸙
void fObjLabel(
string aObjectName, // 1 韲
int aX, // 2 ・
int aY, // 3 ・
string aText, // 4 ・・
int aCorner=0, // 5 鸙 0 1
// 2 3
color aColor=Black, // 6 褪
int aFontSize=8, // 7 銕褞 頡
int aWindowNumber=0, // 8 鶴濵
string aFont="Arial Black", // 9 頡・
bool aBack=false // 10 ・
){


if(ObjectFind(aObjectName)!=aWindowNumber){
ObjectCreate(aObjectName,OBJ_LABEL,aWindowNumber,0,0);
}
ObjectSet(aObjectName,OBJPROP_XDISTANCE,aX);
ObjectSet(aObjectName,OBJPROP_YDISTANCE,aY);
ObjectSetText(aObjectName,aText,aFontSize,aFont,aColor);
ObjectSet(aObjectName,OBJPROP_BACK,aBack);
ObjectSet(aObjectName,OBJPROP_CORNER,aCorner);
}

//ⅳ粲・粢韭 ・湜・
void fObjTrendLine(
string aObjectName, // 1 韲
datetime aTime_1, // 2 糅褌 1
double aPrice_1, // 3 浯 1
datetime aTime_2, // 4 糅褌 2
double aPrice_2, // 5 浯 2
bool aRay=false, // 6 ・・
color aColor=Black, // 7 褪
int aWidth=1, // 8 ・竟・
int aWindowNumber=0, // 9 鶴濵
int aStyle=1, // 10 0-STYLE_SOLID, 1-STYLE_DASH, 2-STYLE_DOT, 3-STYLE_DASHDOT, 4-STYLE_DASHDOTDOT
bool aBack=false // 11 ・
){
if(ObjectFind(aObjectName)!=aWindowNumber){
ObjectCreate(aObjectName,OBJ_TREND,aWindowNumber,aTime_1,aPrice_1,aTime_2,aPrice_2);
}
ObjectSet(aObjectName,OBJPROP_TIME1,aTime_1);
ObjectSet(aObjectName,OBJPROP_PRICE1,aPrice_1);
ObjectSet(aObjectName,OBJPROP_TIME2,aTime_2);
ObjectSet(aObjectName,OBJPROP_PRICE2,aPrice_2);
ObjectSet(aObjectName,OBJPROP_RAY,aRay);
ObjectSet(aObjectName,OBJPROP_COLOR,aColor);
ObjectSet(aObjectName,OBJPROP_WIDTH,aWidth);
ObjectSet(aObjectName,OBJPROP_BACK,aBack);
ObjectSet(aObjectName,OBJPROP_STYLE,aStyle);
}


int fLinearRegressionAll2(int i0,int i1, int aPrice, int & aPeriod, double & aVal_0, double & aVal_1, double & aB, double & aMaxDev, double & aStdError, double & aRSquared,double & aArr[]){
int rRetError=0;
double x,y,y1,y2,sumy,sumx,sumxy,sumx2,sumy2,sumx22,sumy22,div1,div2;
aPeriod=i1-i0+1;
sumy=0.0;sumx=0.0;sumxy=0.0;sumx2=0.0;sumy2=0.0;
for(int i=0; i
y=iMA(NULL,0,1,0,0,aPrice,i0+i);
x=i;
sumy+=y;
sumxy+=y*i;
sumx+=x;
sumx2+=MathPow(x,2);
sumy2+=MathPow(y,2);
}
sumx22=MathPow(sumx,2);
sumy22=MathPow(sumy,2);
div1=sumx2*aPeriod-sumx22;
div2=MathSqrt((aPeriod*sumx2-sumx22)*(aPeriod*sumy2-sumy22));

//---- regression line ----

if(div1!=0.0){
aB=(sumxy*aPeriod-sumx*sumy)/div1;
aVal_0=(sumy-sumx*aB)/aPeriod;
aVal_1=aVal_0+aB*(aPeriod-1);
rRetError+=-1;
}
else{
rRetError+=-1;
}

//--- stderr & maxdev

aMaxDev=0;aStdError=0;

for(i=0;i
y1=iMA(NULL,0,1,0,0,aPrice,i0+i);
y2=aVal_0+aB*i;
aMaxDev=MathMax(MathAbs(y1-y2),aMaxDev);
aStdError+=MathPow(y1-y2,2);
}

aStdError=MathSqrt(aStdError/aPeriod);

//--- rsquared ---

if(div2!=0){
aRSquared=MathPow((aPeriod*sumxy-sumx*sumy)/div2,2);
}
else{
rRetError+=-2;
}

//----

ArrayResize(aArr,aPeriod);
for(i=0; i
y=iMA(NULL,0,1,0,0,aPrice,i0+i);
x=aVal_0+i*(aVal_1-aVal_0)/aPeriod;
aArr[i]=y-x;
}
return(rRetError);
}

void fFurie(double aArr[],double & aA[],double & aB[],double & aR[], double & aF[]){
int tN=ArraySize(aArr);
int tM=tN/2;

ArrayResize(aA,tM);
ArrayResize(aB,tM);
ArrayResize(aR,tM);
ArrayResize(aF,tM);

for (int ti=1;ti
aA[ti]=0;
aB[ti]=0;
for(int tj=0;tj
aA[ti]+=aArr[tj]*MathSin(ti*6.28*tj/tN);
aB[ti]+=aArr[tj]*MathCos(ti*6.28*tj/tN);
}
aA[ti]=2*aA[ti]/tN;
aB[ti]=2*aB[ti]/tN;
aR[ti]=MathSqrt(MathPow(aA[ti],2)+MathPow(aB[ti],2));
aF[ti]=fMyArcTan(aB[ti],aA[ti]);
}

}

double fMyArcTan(double aS,double aC){
if(aS==0){
return(0);
}
if(aC==0){
if(aS>0){
return(MathArctan(1)*2);
}
else{
if(aS<0){
return(MathArctan(1)*6);
}
}
}
else{
if(aS>0){
if(aC>0){
return(MathArctan(aS/aC));
}
else{
return(MathArctan(aS/aC)+MathArctan(1)*4);
}
}
else{
if(aC>0){
return(MathArctan(aS/aC)+MathArctan(1)*8);
}
else{
return(MathArctan(aS/aC)+MathArctan(1)*4);
}
}
}
}

void fObjDeleteByPrefix(string aPrefix){
for(int i=ObjectsTotal()-1;i>=0;i--){
if(StringFind(ObjectName(i),aPrefix,0)==0){
ObjectDelete(ObjectName(i));
}
}
}