Инструменты пользователя

Инструменты сайта


atf:примеры

Список примеров ATF по категориям

Индикаторы

%R

extern period = 27;
 
function init() {
  setInitCandles(period - 1);
  setBounds(0, period - 1, 0);
}
 
function calc() {
  var p = 1 - period;
  var hi = high[p, 0];
  line[0] = -100 * (hi - close) / (hi - low[p, 0]);
}

A/D

function init()
{
  setInitCandles(1);
  if (high == low) {
    line[0] = 0;
  }
  else {
    line[0] = (2 * close - high - low) * volume / (high - low);
  }
}
 
function calc()
{
  if (high == low) {
    line[0] = line[0][-1];
  }
  else {
	line[0] = line[0][-1] +
        (2 * close - high - low) * volume / (high - low);
  }
 
}

ADX

function init()
{
  setInitCandles(1);
  setBounds(0, 1, 0);
}
 
function calc()
{
  var pdi = IndRef("pdimdi", 27)[0];
  var mdi = IndRef("pdimdi", 27)[1];
  if (pdi and mdi) {
    line[0] = 100*abs(pdi-mdi)/(pdi+mdi);
  }
}

Alligator

#samewindow
#line 0 solid blue
#line 1 solid red
#line 2 solid green
extern period1 = 13;
extern period2 = 8;
extern period3 = 5;
extern lag1 = 8;
extern lag2 = 5;
extern lag3 = 2;
 
function init()
{
	setBounds(0, lag1, lag1);
	setBounds(1, lag2, lag2);
	setBounds(2, lag3, lag3);
}
 
function calc()
{
	line[0][lag1] = MovAvg(ind_smma, period1, pt_med);
	line[1][lag2] = MovAvg(ind_smma, period2, pt_med);
	line[2][lag3] = MovAvg(ind_smma, period3, pt_med);
}

AO

#line 0 colored_hist
 
extern period1 = 5;
extern period2 = 34;
 
function init()
{
	var max = period1;
	if (period2 > max) {max = period2;}
	setBounds(0, max - 1, 0);
}
 
function calc()
{
	line[0] = MovAvg(ind_sma, period1, pt_med) -
		MovAvg(ind_sma, period2, pt_med);
}

ATR

extern period = 27;
 
function init()
{
	setInitCandles(2);
	setBounds(0, 1, 0);
	var tr = high[1] - low[1];
	if (tr < high[1] - close) {tr = high[1] - close;}
	if (tr < close - low[1]) {tr = close - low[1];}
	line[0][1] = tr;
}
 
function calc()
{
	var tr = high - low;
	if (tr < high - close[-1]) {tr = high - close[-1];}
	if (tr < close[-1] - low) {tr = close[-1] - low;}
	var alpha = 2 / (period + 1);
	line[0] = alpha * tr + (1 - alpha) * line[0][-1];
}

Bollinger Bands

#samewindow
#line 0 solid #00C000
#line 1 solid #006000
#line 2 solid #006000
 
extern ma_period = 20;
extern sd_period = 20;
extern k = 2;
 
function init()
{
	var m = ma_period;
	if (m < sd_period) {m = sd_period;}
	setInitCandles(m);
	setBounds(0, m, 0);
	setBounds(1, m, 0);
	setBounds(2, m, 0);
}
 
function calc()
{
	var sd = StdDev(stddev_abs, sd_period, pt_close);
	var v = MovAvg(ind_sma, ma_period, pt_close);
	line[0] = v;
	line[1] = v + k * sd;
	line[2] = v - k * sd;
}

CCI

extern period = 20;
extern var_period = 20;
extern k = 0.015;
 
function init()
{
	var m = period;
	if (m < var_period) {m = var_period;}
	setInitCandles(m);
	setBounds(0, m, 0);
}
 
function calc()
{
	var m = 0;
	var md = 0;
	var i = 0;
	while (i < var_period) {
		m += typical[-i] / var_period;
		i += 1;
	}
 
	i = 0;
	while (i < var_period) {
		md += abs(typical[-i] - m) / var_period;
		i += 1;
	}
 
 
	line[0] = (typical - MovAvg(ind_sma, period, pt_typical)) / (k * md);
}

CMO

extern period = 27;
 
function init()
{
	setInitCandles(period);
	setBounds(0, period, 0);
}
 
function calc()
{
	var sumUp = 0;
	var sumDown = 0;
 
	var i = 0;
	while (i < period) {
		var d = close[-i] - close[-i - 1];
		if (d > 0) {sumUp += d / period;}
		else {sumDown += -d / period;}
		i += 1;
	}
 
	line[0] = 100 * (sumUp - sumDown) / (sumUp + sumDown);
}

DeMarker

#line 0 nodraw
#line 1 nodraw
 
extern period = 17;
 
function init()
{
	setInitCandles(1);
	setBounds(2, period, 0);
}
 
function calc()
{
	if (high > high[-1]) {line[0] = high - high[-1];}
	if (low < low[-1]) {line[1] = low[-1] - low;}
	var sma_demax = MovAvg(ind_sma, period, line[0]);
	var sma_demin = MovAvg(ind_sma, period, line[1]);
	var d = sma_demin + sma_demax;
	if (d > 0) {
		line[2] = sma_demax / (sma_demin + sma_demax);
	}
}

Chaikin Volatility

extern period = 10;
 
var emaold;
var emacur;
 
function init()
{
	setInitCandles(period);
	emaold = high - low;
	emacur = high[period] - low[period];
	line[0] = 100 * (emacur - emaold) / emaold;
	setBounds(0, period, 0);
}
 
function calc()
{
	var alpha = 2 / (period + 1);
	emaold = alpha * (high[-period] - low[-period]) +
		(1 - alpha) * emaold;
	emacur = alpha * (high - low) + (1 - alpha) * emacur;
	line[0] = 100 * (emacur - emaold) / emaold;
}

EFI

extern period = 13;
 
function init()
{
	setInitCandles(2);
	setBounds(0, 1, 0);
	line[0][1] = (close[1] - close) * volume[1];
}
 
function calc()
{
	var alpha = 2 / (period + 1);
	line[0] = alpha * volume * (close - close[-1]) +
		(1 - alpha) * line[0][-1];
}

Elder-rays

extern period = 10;
 
function calc()
{
	var ema = MovAvg(ind_ema, period, pt_close);
	line[0] = high - ema;
	line[1] = low - ema;
}

Ichimoku Kinko Hyo

#samewindow
 
extern n1 = 9;
extern n2 = 26;
extern n3 = 52;
 
function init()
{
	setInitCandles(n3);
	setBounds(0, n3, 0);
	setBounds(1, n3, 0);
	setBounds(2, n3, -n2);
	setBounds(3, n3, -n2);
	setBounds(4, n3 * 2, n2);
}
 
function calc()
{
	line[0] = (high[-n1, 0] + low[-n1, 0]) / 2;
	line[1] = (high[-n2, 0] + low[-n2, 0]) / 2;
	line[2][-n2] = (line[0] + line[1]) / 2;
	line[3][-n2] = (high[-n3, 0] + low[-n3, 0]) / 2;
	line[4][n2] = close;
}

Impulse system (A. Elder)

#line 0 nodraw
#line 1 nodraw
#line 2 hist
 
extern ma_period = 13;
extern macd1 = 12;
extern macd2 = 26;
extern macd_signal = 9;
 
function init()
{
   setInitCandles(1);
   setBounds(2, 1, 0);
}
 
function calc()
{
    line[0] = MovAvg(ind_ema, ma_period, pt_close);
   line[1] = IndRef("macdhistogram", macd1, macd2, macd_signal,
      ind_ema, ind_ema, ind_ema, pt_close)[0];
 
   if (line[0] > line[0][-1] && line[1] > line[1][-1]) {
      line[2] = 1;
   }
   if (line[0] < line[0][-1] && line[1] < line[1][-1]) {
      line[2] = -1;
   }
}

MA Envelope

#samewindow
#line 0 solid #00c000
#line 1 solid #00c000
 
extern period = 14;
extern k = 2;
 
 
function calc()
{
	var ma = MovAvg(ind_ema, period, pt_close);
	line[0] = ma * (1 + k/1000);
	line[1] = ma * (1 - k/1000);
}

ParabolicSAR

#samewindow
#line 0 dot maroon
 
extern step = 0.02;
extern init_step = 0.02;
extern max_step = 0.20;
 
var ac;
var trend;
var ep;
 
function init()
{
	setInitCandles(1);
	if (low < low[1]) {
		trend = 1;
		ep = high[0, 1];
		line[0] = low;
	}
	else {
		trend = -1;
		ep = low[0, 1];
		line[0] = high;
	}
	ac = init_step;
}
 
function calc()
{
	if (trend == 1) {
		if (high > ep) {
			ep = high;
			ac += step;
			if (ac > max_step) {ac = max_step;}
		}
		line[0] = line[0][-1] + ac * (ep - line[0][-1]);
		if (low < line[0]) {
			trend = -1;
			line[0] = ep;
			ep = low;
			ac = init_step;
		}
	}
	else {
		if (low < ep) {
			ep = low;
			ac += step;
			if (ac > max_step) {ac = max_step;}
		}
		line[0] = line[0][-1] + ac * (ep - line[0][-1]);
		if (high > line[0]) {
			trend = 1;
			line[0] = ep;
			ep = high;
			ac = init_step;
		}
	}
}

PDI, MDI

extern period = 27;
 
var alpha;
var pdm;
var mdm;
var tr;
 
function init()
{
    alpha = 2/(period+1);
    setInitCandles(1);
    setCurrentPosition(1);
	pdm = high - high[-1];
	mdm = low[-1] - low;
	if (pdm<0) {pdm = 0;}
	if (mdm<0) {mdm = 0;}
	if (pdm < mdm) {pdm = 0;}
	else {mdm = 0;}
    tr = high - low;
    if (tr < high - close[-1]) {tr = high - close[-1];}
    if (tr < close[-1] - low) {tr = close[-1] - low;}
    if (tr) {
      line[0] = pdm/tr;
      line[1] = mdm/tr;
    }
}
 
function calc()
{
	var pdmt = high - high[-1];
	var mdmt = low[-1] - low;
	if (pdmt<0) {pdmt = 0;}
	if (mdmt<0) {mdmt = 0;}
	if (pdmt < mdmt) {pdmt = 0;}
	else {mdmt = 0;}
    var trt = high - low;
    if (trt < high - close[-1]) {trt = high - close[-1];}
    if (trt < close[-1] - low) {trt = close[-1] - low;}
	pdmt = (1 - alpha) * pdm + alpha * pdmt;
	mdmt = (1 - alpha) * mdm + alpha * mdmt;
	tr = (1 - alpha) * tr + alpha * trt;
    if (trt) {
      line[0] = pdmt/tr;
      line[1] = mdmt/tr;
    }
    else {
      line[0] = line[0][-1];
      line[1] = line[1][-1];
    }
    pdm = pdmt;
    mdm = mdmt;
}

RAVI

extern period1 = 7;
extern period2 = 65;
 
function init()
{
   setInitCandles(period2);
   setBounds(0, period2, 0);
}
 
function calc()
{
   var m1 = MovAvg(ind_sma, period1, pt_close);
   var m2 = MovAvg(ind_sma, period2, pt_close);
   line[0] = abs(100 * (m1 - m2) / m2);
}

RSI (EMA based)

extern period = 14;
 
var up;
var down;
 
function init()
{
	up = 0;
	down = 0;
	setInitCandles(period - 1);
	setBounds(0, period - 1, 0);
	var i = 1;
	while (i <= period) {
		var delta = close[i] - close[i - 1];
		if (delta > 0) {up += delta;}
		else {down -= delta;}
		i += 1;
	}
	up /= period - 1;
	down /= period - 1;
 
	line[0][period] = 100 - 100 / (1 + up / down);
}
 
function calc()
{
	var delta = close - close[-1];
	var u = 0;
	var d = 0;
	if (delta > 0) {u = delta;}
	else {d = -delta;}
	up = (up*(period - 1) + u) / period;
	down = (down*(period - 1) + d) / period;
	line[0] = 100 - 100 / (1 + up / down);
}

RVI

#line 2 nodraw
#line 3 nodraw

function init()
{
  setInitCandles(4);
  setBounds(0, 8, 0);
  setBounds(1, 12, 0);
}

function calc()
{
    line[2] = (close - open) + 2*(close[-1] - open[-1])
         + 2*(close[-2] - open[-2]) + (close[-3] - open[-3]);

    line[3] = (high - low) + 2*(high[-1] - low[-1])
         + 2*(high[-2] - low[-2]) + (high[-3] - low[-3]);

    if (noCandle() < 7) {return;}
  
    line[0] = sumLine(2, -4) / sumLine(3, -4);

    if (noCandle() < 11) {return;}
    line[1] = (line[0] + 2*line[0][-1] + 2*line[0][-2] + line[0][-3]) / 6;
}

ZigZag

#samewindow
#line 0 solid red
extern rate = 1;
var trend = 1;
var last;
var last_n;
var last_extr;
var last_extr_n = 0;
var r;
 
 
function init() {
	last = close;
	line[0] = close;
	last_extr = close;
	last_extr_n = 0;
	last_n = 0;
	r = rate / 100;
}
 
 
function getCandleLag(var n, var curr)
{
	return -(curr - n);
}
 
 
function approxLinear(var x1, var y1, var x2, var y2) 
{
	var n = x2 - x1;
	if (!n) {
		line[0][getCandleLag(x1, noCandle())] = y1;
		return;
	}
	var k = (y2 - y1) / n;
	var i = 0;
	while (i <= n) {
		line[0][getCandleLag(x1 + i, noCandle())] = y1 + k*i;
		i += 1;
	}
}
 
 
function myFindMax(var from, var to)
{
	var m = high[getCandleLag(from, noCandle())];
	var n = from;
	var i = from + 1;
	while (i <= to) {
		var x = high[getCandleLag(from, noCandle())];
		if (x > m) {
			m = x;
			n = i;
		}
		i += 1;
	}
	return n;
}
 
 
function myFindMin(var from, var to)
{
	var m = low[getCandleLag(from, noCandle())];
	var n = from;
	var i = from + 1;
	while (i <= to) {
		var x = low[getCandleLag(from, noCandle())];
		if (x < m) {
			m = x;
			n = i;
		}
		i += 1;
	}
	return n;
}
 
 
 
function calc()
{
	if (trend == 1) {
		if (close > last_extr) {
			last_extr = high;
			last_extr_n = noCandle();
			approxLinear(last_n, last, noCandle(), high);
		}
		else {
			approxLinear(last_extr_n, last_extr, noCandle(), low);
		}
	}
	if (trend == -1) {
		if (close < last_extr) {
			last_extr = low;
			last_extr_n = noCandle();
			approxLinear(last_n, last, noCandle(), low);
		}
		else {
			approxLinear(last_extr_n, last_extr, noCandle(), high);
		}
	}
 
	if (abs(close - last_extr) / last_extr > r) {
		var old_n = last_n;
		var old = last;
		last_n = last_extr_n;
		last = last_extr;
		if (trend > 0) {
			trend = -1;
			last_extr_n = myFindMin(last_n, noCandle());
			last_extr = low[getCandleLag(last_extr_n, noCandle())];
		}
		else {
			trend = 1;
			last_extr_n = myFindMax(last_n, noCandle());
			last_extr = high[getCandleLag(last_extr_n, noCandle())];
		}
		approxLinear(old_n, old, last_n, last);
		approxLinear(last_n, last, noCandle(), close);
	}
}

Pivot points

#samewindow
#line 0 solid blue
#line 1 dashed green
#line 2 dashed red
#line 3 dot green
#line 4 dot red
 
var day; // current day
var nday; // number of day in chart
var ph; // high of yesterday
var pl; // low of yesterday
var pc; // close of yesterday
var cl; // today's low
var ch; // today's high
 
function init()
{
	nday = 1;
	day = getDay(getCandleTime());
}
 
 
function drawLines()
{
	line[0] = (ph + pl + pc) / 3; // Pivot point
	line[1] = 2*line[0] - ph; // Support 1
	line[2] = 2*line[0] - pl; // Resistance 1
	line[3] = line[0] - (line[2] - line[1]); // Resistance 2
	line[4] = line[0] + (line[2] - line[1]); // Support 2
}
 
 
function calc()
{
	if (nday == 1) {
		if (getDay(getCandleTime()) != day) {
			nday = 2;
			day = getDay(getCandleTime());
			ph = high;
			pl = low;
		}
	}
	else if (nday == 2)	{
		if (getDay(getCandleTime()) != day) {
			nday = 3;
			day = getDay(getCandleTime());
			cl = low;
			ch = high;
			pc = close[-1];
			drawLines();
			setBounds(0, noCandle(), 0);
			setBounds(1, noCandle(), 0);
			setBounds(2, noCandle(), 0);
			setBounds(3, noCandle(), 0);
			setBounds(4, noCandle(), 0);
		}
		else {
			if (high > ph) {ph = high;}
			if (low < pl) {pl = low;}
		}
	}
	else {
		if (getDay(getCandleTime()) != day) {
			nday += 1;
			day = getDay(getCandleTime());
			ph = ch;
			pl = cl;
			pc = close[-1];
			cl = low;
			ch = high;
		}
		else {
			if (high > ch) {ch = high;}
			if (low < cl) {cl = low;}
		}
		drawLines();
	}
}

Stochastic Momentum Index

#line 0 nodraw
#line 1 nodraw
#line 2 nodraw
#line 3 nodraw
#line 4 nodraw
#line 5 nodraw
#line 7 solid red
 
extern lp = 13;
extern sm = 25;
extern dsmp = 2;
extern sig = 3;
 
 
function init()
{
	if (countCandles() < lp) {
		lackHistory();
	}
	setInitCandles(lp);
	setBounds(0, lp, 0);
}
 
 
function calc()
{
	line[0] = close - .5 * high[-lp,0] + low[-lp,0];
	line[1] = MovAvg(ind_ema, sm, line[0]);
	line[2] = MovAvg(ind_ema, dsmp, line[1]);
 
	line[3] = high[-lp, 0] - low[-lp, 0];
	line[4] = MovAvg(ind_ema, sm, line[3]);
	line[5] = 0.5*MovAvg(ind_ema, dsmp, line[4]);
 
	line[6] = 100 * line[2] / line[5];
	line[7] = MovAvg(ind_ema, sig, line[6]);
}

Ultimate Oscillator

// Данный индикатор может быть существенно оптимизирован
// с точки зрения скорости расчета. Улучшенный пример
// будет приведен позже
#line 0 nodraw
#line 1 nodraw
extern period = 7;
 
function init()
{
	if (countCandles() < period * 4 + 1) {
		lackHistory();
	}
	setInitCandles(1);
	setBounds(0, period*4 + 1, 0);
}
 
 
function sumLine1(var n)
{
	var i = 0;
	var s = 0;
	while (i < n) {
		s += line[0][-i];
		i += 1;
	}
	return s;
}
 
function sumLine2(var n)
{
	var i = 0;
	var s = 0;
	while (i < n) {
		s += line[1][-i];
		i += 1;
	}
	return s;
}
 
 
function avg(var n)
{
	return sumLine1(n) / sumLine2(n);
}
 
 
function calc()
{
	if (low < close[-1]) {
		line[0] = close - low;
	}
	else {
		line[0] = close - close[-1];
	}
 
	var h;
	var l;
	if (high > close[-1]) {h = high;}
	else {h = close[-1];}
	if (low < close[-1]) {l = low;}
	else {l = close[-1];}
	line[1] = h - l;
 
	if (noCandle() > period*4 + 1) {
		line[2] = 100 * (4*avg(period) + 2*avg(period*2) + avg(period*4)) / 7;
	}
}

Медианный фильтр

#samewindow
 
extern period = 15;
 
var window;
static lastvalue;
 
function init()
{
	window = new_object("array");
	setBounds(0, period + 1, 0);
	setInitCandles(period + 1);
}
 
function findMed()
{
	window.clear();
 
	var i = 1;
	while (i <= period) {
		window.push(close[-i]);
		i += 1;
	}
 
	i = 0;
	while (i <= period / 2) {
		var min_n = i;
 
		var j = min_n + 1;
		while (j < window.size()) {
			if (window[min_n] > window[j]) {
				min_n = j;
			}
			j += 1;
		}
 
		if (min_n > i) {
			var tmp = window[min_n];
			window[min_n] = window[i];
			window[i] = tmp;
		}
 
		i += 1;
	}
 
	lastvalue = window[i - 1];
 
	return lastvalue;
}
 
function onNewCandle()
{
	findMed();
}
 
function calc()
{
	if (!isHistoryCalculated()) {
		findMed();
	}
 
	line[0] = lastvalue;
}

Сигналы

Пересечение ценой скользящей средней

#samewindow
#line 0 solid red
 
extern period = 9;
var trend = 0;
 
function init()
{
	setInitCandles(1);
}
 
 
function calc()
{
	line[0] = MovAvg(ind_ema, period, pt_close);
 
	if (trend == 1 and close < line[0]) {
		signal::alert("Продажа: " + getSecName() +
					" пересекла сверху вниз скользящую среднюю.");
	}
 
	if (trend == -1 and close > line[0]) {
		signal::alert("Покупка: " + getSecName() +
					" пересекла снизу вверх скользящую вреднюю.");
	}
 
	if (close > line[0]) {trend = 1;}
	else if (close < line[0]) {trend = -1;}
}

Пересечение двух скользящих средних

#samewindow
#line 0 solid red
 
extern fast = 9;
extern slow = 14;
var trend = 0;
 
function init()
{
	setInitCandles(1);
}
 
 
function calc()
{
	line[0] = MovAvg(ind_ema, fast, pt_close);
	line[1] = MovAvg(ind_ema, slow, pt_close);
 
	if (trend == 1 and line[0] < line[1]) {
		signal::alert("Продажа: по " + getSecName() +
						" быстрая MA пересекла медленную сверху вниз.");
	}
 
	if (trend == -1 and line[0] > line[1]) {
		signal::alert("Покупка: по " + getSecName() +
						" медленная MA пересекла быструю снизу вверх.");
	}
 
	if (line[1] < line[0]) {trend = 1;}
	else if (line[1] > line[0]) {trend = -1;}
}

Примеры технических функций

Сохранение данных в файл

// Данный код не несет полезной функии,
// а лишь демонстрирует работу с файлами.
// Подробности смотрите в руководстве.
 
 
static c1 = 0;
static c2 = 0;
 
var file;
 
function init()
{
	file = new_object("file");
	file.ropen("data.txt");
	if (file.isopen()) {
		c1 = file.readLn();
		c2 = file.readLn();
		file.close();
	}
	file.wopen("data.txt");
}
 
 
function onNewCandle()
{
	c2 += 1;
	file.seek(0);
	file.writeLn(c1);
	file.writeLn(c2);
}
 
function calc()
{
	if (isHistoryCalculated()) {
		c1 += 1;
	}
	line[0] = 0;
}

Сохранение информации о сделках в файл

// Данный код не несет полезной функии,
// а лишь демонстрирует работу с файлами.
// Подробности смотрите в руководстве.
 
var file;
 
function init()
{
	file = new_object("file");
	file.waopen("data.txt");
}
 
 
function saveTrade(var id)
{
	var trade = getTrade(id);
	if (trade["operation"] == OP_BUY) {
		file.write("BUY ");
	}
	else {
		file.write("SELL ");
	}
 
	file.write(trade["quantity"]);
	file.write(" lots at price ");
	file.writeLn(trade["price"]);
}
 
 
function onClientTrade(var id)
{
	file.write("Client order: ");
	saveTrade(id);
}
 
 
function onATFTrade(var id)
{
	file.write("ATF order: ");
	saveTrade(id);
}
 
 
function calc()
{
	line[0] = 0;
}

Регулярная синхронизация времени клиента со временем сервера

extern interval = 15;
 
function synchronize()
{
  setSystemTime(getServerTime());
}
 
function init()
{
  synchronize();
  setTimer("synchronize", interval * 60,  TIMER_PERIODICALLY);
}

Данный скрипт не содержит в себе каких-либо линий, поэтому может использоваться лишь в совокупности с каким-либо индикатором или роботом ATF.

Торговые роботы

Простая стратегия "Лесенка"

// Данная демонстрационна стратегия продает
// при любом движении цены вверх на step_percent
// процентов и покупает при движении цены вниз
// на step_percent процентов в ожидании коррекции.
// При этом используются лимитированные заявки,
// постоянно выставлено пять-шесть лимитированных
// заявок на одинаковом расстоянии. Смотрите
// результаты тестировщика ATF для более наглядного
// представления.
 
 
extern step_percent = 0.2;
extern num = 5;
extern amount = 1;
 
var step;
static buy_count = 0;
static sell_count = 0;
 
function init()
{
	step = step_percent / 100;
}
 
function buy(var price)
{
	trade_action::buyMultiple(amount, ::lots, price);
	buy_count += 1;
}
 
 
function sell(var price)
{
	trade_action::sellMultiple(amount, ::lots, price);
	sell_count += 1;
}
 
function setOrders()
{
	var i = 1;
	while (i <= num) {
		buy(close * (1 - i*step));
		sell(close * (1 + i*step));
		i += 1;
	}
}
 
function onHistoryCalculated()
{
	setOrders();
}
 
function onATFOrder(var id)
{
	var order = getOrder(id);
	if (order["status"] == OS_MATCHED) {
		if (order["operation"] == OP_BUY) {
			buy_count -= 1;
			var newprice = order["price"] * (1 - step * num);
			var oldprice = order["price"] * (1 + step);
			if (buy_count < num) {buy(newprice);}
			sell(oldprice);
		}
		else {
			sell_count -= 1;
			var newprice = order["price"] * (1 + step * num);
			var oldprice = order["price"] * (1 - step);
			if (sell_count < num) {sell(newprice);}
			buy(oldprice);
		}
	}
}

Пример программирования торговых функций привязанных к клавиатуре

 
 
/*
 
При добавлении данного скрипта в торговое окно, в данном окне
становится возможно использовать дополнительные торговые функции.
Торговая команда набирается на клавиатуре с зажатой клавишей
shift и имеет двухбуквенное название. Доступны следующие команды:
 
BS - выставить одновременно заявки на покупку и продажу
CA - снять все заявки
CM - снять последние две заявки
UP - сдвинуть заявки вверх
DN - сдвинуть заявки вниз
CL - сдвинуть заявки ближе друг к другу
OP - расширить диапазон между заявками
FG - "забыть" старую выставленную позицию
 
При добавлении данного скрипта на график доступны для настройки
следующие параметры:
 
eps - начальное расстояние между выставляемыми заявками
move_eps - шаг сдвига заявок
range_eps - относительное изменение расстояния между заявками
quantity - объем заявок
 
Данный скрипт вряд ли имеет действительно полезный смысл, но
наглядно демонстрирует каким образом вы можете писать собственные
сложные торговые функции, управляемые с клавиатуры.
 
*/
 
#samewindow
#line 0 nodraw
 
extern eps = 0.005;
extern move_eps = 0.0005;
extern range_eps = 0.00025;
extern quantity = 1;
 
static prevKey = 0;
static buyord = 0;
static sellord = 0;
 
function cancelAll()
{
  trade_action::cancelAllOrders();
  buyord = 0;
  sellord = 0;
}
 
function onOrder(var id)
{
  var error;
  if (id != buyord and id != sellord) {
    return;
  }
  var order = getOrder(id);
  if (order["status"] != OS_ACTIVE) {
    cancelAll();
  }
}
 
function buy(var price)
{
  if (buyord) {trade_action::cancelOrder(buyord);}
  buyord = trade_action::buyMultiple(quantity, ::lots, price);
  if (not buyord) {
    signal::outputMultiple(getLastErrorMessage());
  }
}
 
function sell(var price)
{
  if (sellord) {trade_action::cancelOrder(sellord);}
  sellord = trade_action::sellMultiple(quantity, ::lots, price);
  if (not sellord) {
    signal::outputMultiple(getLastErrorMessage());
  }
}
 
function moveDown()
{
  if (not buyord or not sellord) {return;}
  var b = getOrder(buyord);
  var s = getOrder(sellord);
  buy(b["price"] * (1 - move_eps));
  sell(s["price"] * (1 - move_eps));
}
 
function moveUp()
{
  if (not buyord or not sellord) {return;}
  var b = getOrder(buyord);
  var s = getOrder(sellord);
  buy(b["price"] * (1 + move_eps));
  sell(s["price"] * (1 + move_eps));
}
 
function makeCloser()
{
  if (not buyord or not sellord) {return;}
  var b = getOrder(buyord);
  var s = getOrder(sellord);
  buy(b["price"] * (1 + range_eps));
  sell(s["price"] * (1 - range_eps));
}
 
function makeWider()
{
  if (not buyord or not sellord) {return;}
  var b = getOrder(buyord);
  var s = getOrder(sellord);
  buy(b["price"] * (1 - range_eps));
  sell(s["price"] * (1 + range_eps));
}
 
function buysell()
{
  if (buyord or sellord) {return;}
  buy(close*(1-eps));
  sell(close*(1+eps));
}
 
function forget()
{
  buyord = 0;
  sellord = 0;
}
 
function cancelMine()
{
  if (buyord) {
    trade_action::cancelOrder(buyord);
    buyord = 0;
  }
  if (sellord) {
    trade_action::cancelOrder(sellord);
    sellord = 0;
  }
}
 
function onKeyDown(var key)
{
  if (isKeyPressed(KEY_LSHIFT)) {
    if (prevKey == chr2num("B") and key == chr2num("S")) {
      buysell();
    }
    if (prevKey == chr2num("C") and key == chr2num("A")) {
      cancelAll();
    }
    if (prevKey == chr2num("C") and key == chr2num("M")) {
      cancelMine();
    }
    if (prevKey == chr2num("U") and key == chr2num("P")) {
      moveUp();
    }
    if (prevKey == chr2num("D") and key == chr2num("N")) {
      moveDown();
    }
    if (prevKey == chr2num("C") and key == chr2num("L")) {
      makeCloser();
    }
    if (prevKey == chr2num("O") and key == chr2num("P")) {
      makeWider();
    }
    if (prevKey == chr2num("F") and key == chr2num("G")) {
      forget();
    }
    prevKey = key;
  }
}

Равномерное совершение сделок (ATF 1.19)

#samewindow
#line 0 nodraw
 
// За какое время продать/купить всё
extern time;
 
// Как часто совершать сделки
extern frequency;
 
// Сколько всего лотов купить/продать
// Если >0, то покупка, если <0 - продажа
extern quantity;
 
// Погрешность частоты совершения сделок
extern freq_eps;
 
// Погрешность объема в отдельной сделке
extern quantity_eps;
 
static time_to;
static time_elapsed;
static quantity_elapsed;
 
static ready = 0;
 
static x_rand = 1;
 
function makeTrade(var q)
{
	var trnid;
	if (quantity > 0) {
		signal::outputMultiple("Покупаю " + q + " лотов.");
		trnid = trade_action::buyMultiple(q, ::lots);
	}
	else {
		signal::outputMultiple("Продаю " + q + " лотов.");
		trnid = trade_action::sellMultiple(q, ::lots);
	}
 
	if (not trnid) {
		signal::outputMultiple(getLastErrorMessage());
	}
}
 
 
function printStats()
{
	signal::outputMultiple("-----");
	if (quantity > 0) {
		signal::outputMultiple("Осталось купить " + quantity_elapsed +
			" бумаг за " + time_elapsed + " секунд.");
	}
	else {
		signal::outputMultiple("Осталось продать " + quantity_elapsed +
			" бумаг за " + time_elapsed + " секунд.");
	}
}
 
 
function arrangeNewTransaction()
{
	if (not isTradingAllowed() or not ready) {return;}
	time_elapsed = time_to - getSystemTime();
	var t = rand_uniform(frequency - freq_eps, frequency + freq_eps);
	if (t + getSystemTime() > time_to) {
		t = time_to - getSystemTime();
	}
	signal::outputMultiple("Следующая сделка через " + round(t) + " секунд.");
	setTimer("trade", t*1000, TIMER_AFTERDELAY);
}
 
function onStopRobot()
{
	if (quantity_elapsed) {
		time_elapsed = time_to - getSystemTime();
		printStats();
	}
	else {
		signal::outputMultiple("Задание выполнено.");
		ready = 0;
	}
}
 
 
function trade()
{
	time_elapsed = time_to - getSystemTime();
	if (not isTradingAllowed() or not ready) {return;}
	if (time_elapsed < frequency) {
		makeTrade(quantity_elapsed);
		signal::outputMultiple("Все бумаги проданы!");
	}
	else {
		var q = quantity_elapsed / (time_elapsed / frequency);
		q = round(rand_uniform(q - quantity_eps, q + quantity_eps));
		if (q > quantity_elapsed) {q = quantity_elapsed;}
		if (q > 0) {
			makeTrade(q);
			quantity_elapsed -= q;
			printStats();
		}
		else {
			signal::outputMultiple("Решил отложить сделку.");
			printStats();
		}
		if (quantity_elapsed) {arrangeNewTransaction();}
		else {onStopRobot();}
	}
}
 
 
function init()
{
	time_elapsed = time;
	time_to = getSystemTime() + time;
	quantity_elapsed = abs(quantity);
}
 
 
function onStartRobot()
{
	if (quantity != 0 and frequency > 0 and time > 0) {
		ready = 1;
		printStats();
		arrangeNewTransaction();
	}
	else {
		signal::output("Заданы некорректные параметры для торговли; выполнение скрипта отменено.");
		ready = 0;
	}
}

Максимум/минимум в конкретный интервал времени

// Функции getHigh и getLow вычисляют значения
// high и low в заданный промежуток времени

// В качестве примера сам скрипт вычисляет значения
// high и low за время с 9 до 11 и отрисовывает две
// две линии, соответствующие этим уровням

static H;
static L;

function getHigh(var from, var to)
{
	var n = getCandleByTime(from);
	setCurrentPosition(n);
	if (getCandleTime() != from) {
	  from = n + 1;
	}
	else {
	  from = n;
	}
	setCurrentPosition(0);
	to = getCandleByTime(to);
	var h = high[from, to];
	restoreCurrentPosition();
	return h;
}

function getLow(var from, var to)
{
	var n = getCandleByTime(from);
	setCurrentPosition(n);
	if (getCandleTime() != from) {
	  from = n + 1;
	}
	else {
	  from = n;
	}
	setCurrentPosition(0);
	to = getCandleByTime(to);
	var h = low[from, to];
	restoreCurrentPosition();
	return h;
}

function init()
{
  var from = getTimeObject(9, 0);
  var to = getTimeObject(11, 0);
  H = getHigh(from, to);
  L = getLow(from, to);
}

function calc()
{
  line[0] = H;
  line[1] = L;
}
atf/примеры.txt · Последние изменения: 2014/03/18 16:02 — heller