Вопрос. Есть ли какие-то особенности при вызове этой функции на реальном счете? Скрипт выдаёт ошибку, мол, attempt to index a nil value Вызов такой: sizeDS=getFuturesLimit(Settings.FIRM_ID,Settings.ACCOUNT,0,"SUR").cbplimit;
В Firm_ID и Account соответственно хранятся фирма и торговый счет. При подстановке данных с тестового счета всё чудно работает, на реальном - фиг.
Sergey Gorokhov написал: Егор Масалкин , Алигатор показывает данные в будущее, в результате, в окне даграммы справа добавляются свечки. Пусть хоть и пустые, но они есть:
А значит правильно и логично что getNumCandles реагирует на эти самые свечки.
Значит, в принципе абсолютно неважно что передавать в функцию? Это разве логично и правильно, когда мне надо получить свечи с одного графика, а он реагирует на другой?
День добрый. Привожу часть кода. Заранее определенная глобальная переменная NP="Price" - хранит в себе название индикатора для свечей. И только для них. У всех остальных индикаторов свои названия. Переменная разумеется нигде не меняется.
Однако следующая связка N1=getNumCandles(NP); --количество свечей c=getCandlesByIndex(NP,0,N1-1,1)[0]; --последняя цена закрытия
выводит 0. Методом проб и ошибок пришел к выводу, что чтобы получить последнюю цену закрытия, надо от N1-1 отнять максимальный сдвиг аллигатора, т.е. получается, что в N1 хранится не количество свечей, а количество значений аллигатора! ЧЯДНТ?
P.s. индикатор аллигатора назван Alligator, т.е. не должно быть такого
Собственно, им я получаю значение АС текущей свечи и трёх предыдущих. Но вот в определенный момент эти числа получаются... из ниоткуда? Привожу пример (месседжами вывожу значения АС)
Скрытый текст
Относительно свечи N (числа примерные, всё ок): ac1=69 - у свечи N ac2=440 - у свечи N-1 ac3=508 - N-2 ac4=535 - N-3
Скрытый текст
Относительно свечи N-1 (числа примерные, всё ок): ac1=440 - у свечи N-1 ac2=508 - у свечи N-2 ac3=535 - N-3 ac4=446 - N-4
Скрытый текст
Относительно свечи N-2 (числа примерные, всё ок): ac1=508 - у свечи N-2 ac2=535 - у свечи N-3 ac3=446 - N-4 ac4=533 - N-5
Скрытый текст
Относительно свечи N-3 (числа примерные, всё ок): ac1=535 - у свечи N-3 ac2=446 - у свечи N-4 ac3=533 - N-5 ac4=753 - N-6
А вот дальше произошла какая-то магия...Относительно свечи N-4 (числа примерные, всё ок): ac1=-319 - у свечи N-4 ac2=-363 - у свечи N-5 ac3= 70 - N-6 ac4=418 - N-7
Добрый день. Такой вопрос - есть скрипт, обрабатывающий множество инструментов из файла, который является списком кодов класса и бумаг. Однако, в зависимости от запуска на тех или иных компьютерах, в зависимости от сервера, брокер предоставляет доступ к разному набору инструментов.
Вопрос - можно ли каким-либо образом устроить обработчик, который не будет вылетать с ошибкой на инструментах, которые брокер не предоставляет?
Здесь написана функция получения данных по инструменту, однако, к примеру, дойдя до класса SPBXM, данные о котором мне не предоставляются, вылетает с ошибкой "attempt to index global 'DS' (a nil value)". Как можно поправить код, чтобы в таком случае инструмент просто пропустился?
Код
function get_data() --получает базу данных
DS, strMessage = CreateDataSource( cur_class, cur_sec, INTERVAL_D1 )
tmTac = os.time()
repeat
sleep( 1000 )
until ( DS:Size() == nil ) or ( os.difftime( os.time(), tmTac ) <= 15 )
end;
На самом деле оказалось всё проще. Заказ данных --> поток обезличенных сделок. Почему-то слетели все галочки, выставил их обратно - инструменты появились.
Цитата
Zoya Skvorcova написал: Егор Масалкин ,Добрый день. Если Вы клиент брокерской компании, рекомендуем обратиться к брокеру и проверить Ваши права.
Здравствуйте. На прошлой неделе запускал Quik - мог спокойно создать таблицу сделок или график по таким инструментам, как Валюта, Облигации, Акции и прочее (т.е. был полный доступ ко всем инструментам). Сегодня же, запустив Quk, я обнаружил, что у меня в списке только Опционы и Фьючерсы Forts.
Куда делись остальные инструменты? Как их вернуть?
Проблема была в функции OnInit(), в которой я писал весь код. Как только я поменял на функцию main, что было у товарища Alexegin, всё сразу заработало.
Ваш код работает. Но как только меняют параметры, пишу dsData, strMessage = CreateDataSource( "SPBFUT", "RIU7", INTERVAL_MN1 )
то выдаёт, что размер будет 0. НО как только я делаю график, то он спокойно получает данные... но ведь он с сервера должен брать свечи, а не с графика?
ну серьёзно... может я такой аутист что правильно не могу переписать коды? Но нет... может опять какая-то беда с фьючерами?
Ставлю ожидание на 30 секунд, однако, всё равно возвращает пустые значения. Что-то долго голуби летят, или я чего-то не так делаю?
Код
DS,Error = CreateDataSource(CLASS_CODE, cur_sec, INTERVAL);
-- Проверка
if DS == nil then
message('Входила:ОШИБКА получения доступа к свечам! ');
end;
t=0;
while DS:Size() == 0 and t<30000 do
sleep( 1000 )
t=t+1000;
end
if t>29000 then message(cur_sec.." Empty") end;
При этом, что характерно - если у меня открыт график с каким-либо инструментом, он без проблем выцепит данные с него. Однако по задумке требуется работать с большим количеством инструментов и содержать армию графиков не вариант (собсно, cur_sec у меня и содержит название инструмента, берёт верно)
В руководстве по созданию индикаторов теханализа есть пример по написанию функции EMA
Сколько ни смотрю,не могу понять какие ИМЕННО параметры передаются в подпрограмму функции. Выше нигде нет определений переменных _p, v_t и kk, внутри функции они тоже не определяются. Так что это за параметры?
Код
function EMA()
local cache={}
return function(ind,_p,v_t,kk)
local n=0
local p=0
local period=_p
local v_type=v_t
local index=ind
local k=kk or 2/(period+1)
if index==1 then cache={} end
if index<period then
cache[index]=Average(1,index,v_type)
return nil
end
p=cache[index-1] or dValue(index,v_type)
n=k*dValue(index,v_type)+(1-k)*p
cache[index]=n
return n
end
end
Пытаюсь написать скрипт, задачей которого является получение значения индикаторов с большого числа инструментов. Делать свыше 70-80 таблиц и называть в них индикаторы смысла не имеет.
Разобрался, что через CreateDataSource можно получить данные со свечей любого инструмента... но можно ли это применить для индикаторов? Для аллигатора или хотя бы обычной скользящей средней? Или есть какие-то другие альтернативы для решения данной задачи?
Нет никакой возможности выцепить, на каком именно параметре рубит? Уже два дня пытаюсь понять что происходит, напрямую задал параметры функции, копировал прямо из таблицы... При этом заявки по тем же параметрам успешно выставляются.
Возникла такая проблема... На демо-счете программа работает верно, но когда ввожу данные реального счета - снова выдаёт ту же ошибку... Корректность данных проверил несколько раз, всё в норме... Я чего-то ещё не учел? На реальном счете есть какие-то особенности применения этой функции?
Разобрался.Действительно, ошибка была в передаче данных в функцию.
Однако, пока копался в документации, ещё один нюанс обнаружил. В описании функции указано, что pos_type является типом Number, а в описании параметров таблицы, во-первых, указан параметр type (разные названия), во-вторых, у него тип STRING.
Соответственно, предложение - привести к общему виду и название параметра, и его тип, как в описании функции, так и в описании таблицы параметров.
Однако, выдаёт ошибку, мол: attempt to index a nil value
Не понимаю, что делаю не так. Подскажите пожалуйста. Все значения FIRM_ID, ACCOUNT и SECCODE соответствуют полям "Фирма", "Торговый счет" и "Код класса" таблицы "Позиции по клиентским счетам".
N=getNumCandles("Price") for v=100,N,1 do t=getCandlesByIndex("Price",0,v-1,1)[0]; f=getCandlesByIndex("Fractal",0,v-1,1)[0]; if t.high==f.high then message("Fractal Up Year"..tostring(t.datetime.year).." Month"..tostring(t.datetime.month).." Day"..tostring(t.datetime.day).." Hour"..tostring(t.datetime.hour)); end; if t.low==f.low then message("Fractal Down Year"..tostring(t.datetime.year).." Month"..tostring(t.datetime.month).." Day"..tostring(t.datetime.day).." Hour"..tostring(t.datetime.hour)); end;
Если я правильно понял, то должно быть где-то так. Проверил по графику, стрелки вниз находит верно, а стрелки вверх игнорирует =_= В чем дело?
Здравствуйте! Использую следующий индикатор фрактала.
Но не могу понять, как мне вытащить с графика номер свечи... f=getCandlesByIndex("Fractal",v,N-1,1)[0]; if f.Type==TYPE_TRIANGLE_DOWN then message("Fractal Down "..tostring(v)); end; if f.Type==TYPE_TRIANGLE_UP then message("Fractal UP "..tostring(v)); end;
Пробовал и f.Setting.line.Type - не понимаю, как мне программно узнать, какой фрактал у свечи и есть ли он в принципе... Подскажите пожалуйста
Код
Settings = {
Name = "*FRACTALS (Fractals)",
Period = 5,
line = {{
Name = "FRACTALS - Down",
Type = TYPE_TRIANGLE_DOWN,
Color = RGB(255, 0, 0)
},
{
Name = "FRACTALS - Up",
Type = TYPE_TRIANGLE_UP,
Color = RGB(0, 255, 0)
}
}
}
function Init()
func = FRACTALS()
return #Settings.line
end
function OnCalculate(Index)
return func(Index, Settings)
end
function FRACTALS() --Fractals ("FRACTALS")
local H_tmp={}
local L_tmp={}
return function (I, Fsettings, ds)
local Fsettings=(Fsettings or {})
local P = (Fsettings.Period or 5)
P = math.floor(P/2)*2+1
H_tmp[I]=Value(I,"High",ds)
L_tmp[I]=Value(I,"Low",ds)
if I>=P then
local S = I-P+1+math.floor(P/2)
local val_h=math.max(unpack(H_tmp,I-P+1,I))
local val_l=math.min(unpack(L_tmp,I-P+1,I))
local L = Value(S,"Low",ds)
local H = Value(S,"High",ds)
if (val_h == H) and (val_h >0)
and (val_l == L) and (val_l > 0) then
if ds then return S,S else
SetValue(S, 1, val_l)
SetValue(S, 2, val_h)
end
else
if (val_h == H) and (val_h >0) then
if ds then return S,nil else
SetValue(S, 1, nil)
SetValue(S, 2, val_h)
end
end
if (val_l == L) and (val_l > 0) then
if ds then return nil,S else
SetValue(S, 1, val_l)
SetValue(S, 2, nil)
end
end
end
end
return nil,nil
end
end
function Value(I,VType,ds)
local Out = nil
VType=(VType and string.upper(string.sub(VType,1,1))) or "A"
if VType == "O" then --Open
Out = (O and O(I)) or (ds and ds:O(I))
elseif VType == "H" then --High
Out = (H and H(I)) or (ds and ds:H(I))
elseif VType == "L" then --Low
Out = (L and L(I)) or (ds and ds:L(I))
elseif VType == "C" then --Close
Out = (C and C(I)) or (ds and ds:C(I))
elseif VType == "V" then --Volume
Out = (V and V(I)) or (ds and ds:V(I))
elseif VType == "M" then --Median
Out = ((Value(I,"H",ds) + Value(I,"L",ds)) / 2)
elseif VType == "T" then --Typical
Out = ((Value(I,"M",ds) * 2 + Value(I,"C",ds))/3)
elseif VType == "W" then --Weighted
Out = ((Value(I,"T",ds) * 3 + Value(I,"O",ds))/4)
elseif VType == "D" then --Difference
Out = (Value(I,"H",ds) - Value(I,"L",ds))
elseif VType == "A" then --Any
if ds then Out = ds[I] end
end
return Out
end
Т.е. я правильно понимаю, что отдельно события "открытие новой свечи" нет, и кроме пересчета времени способа открыть сделку с первой сделкой в свече нет?
Всем доброго времени суток. Пишу робота, столкнулся с таким нюансом. Изначально спроектировал его так, чтобы проверка на выполнение условий выставления заявки была по времени (допустим, раз в минуту, путём pause(X) ).
Дело в том, что таким образом если я запускаю робота на 46-ой секунде на сервере, то первая проверка будет осуществляться на 46-ой секунде; следующая на 1 минуте 46; потом 2 минуты 46 и т.д.
Надо сделать так, чтобы проверка отрабатывала всегда на моменте открытия новой свечи. И не могу найти инфу, как программно выцепить именно момент открытия. Могу конечно время подогнать, но это не то. Подскажите, может есть какая-то встроенная функция... из справки в разделе "функции обратного вызова" вроде нет ничего подходящего, либо я не понял это(
TransOpenPos(): Error: Не указано значение поля "К/П"
Код:
function trade(Type) trans_id = trans_id + 1; price = 0; local Operation = ''; if Type=='B' then price=getParamEx(Settings.CLASS_CODE,Settings.SEC_CODE,"OFFER") else price=getParamEx(Settings.CLASS_CODE,Settings.SEC_CODE,"BID") end; TransOpenPos(); end
function TransOpenPos() -- Получает ID для следующей транзакции trans_id = trans_id + 1 -- Заполняет структуру для отправки транзакции local direction; local Transaction={ ['TRANS_ID'] = tostring(trans_id), ['ACTION'] = 'NEW_ORDER', ['CLASSCODE'] = Settings.CLASS_CODE, ['SECCODE'] = Settings.SEC_CODE, ['OPERATION'] = Type, -- операция ("B" - buy, или "S" - sell) ['TYPE'] = 'L', -- по рынку (LIMIT) ['QUANTITY'] = '1', -- количество ['ACCOUNT'] = Settings.ACCOUNT, ['PRICE'] = tostring(math.floor(price.param_value)), ['COMMENT'] = '' } -- Отправляет транзакцию local Res = sendTransaction(Transaction) if Res ~= '' then message('TransOpenPos(): Error: '..Res) else message('TransOpenPos(): FUCK YEAH') end end
Type - параметр типа заявки, либо 'B' либо 'S' Код переписал под "покупку\продажу", но ещё на запускал
function trade(Type) trans_id = trans_id + 1; price = 0; local Operation = ''; if Type=='B' then price=getParamEx(Settings.CLASS_CODE,Settings.SEC_CODE,"OFFER") else price=getParamEx(Settings.CLASS_CODE,Settings.SEC_CODE,"BID") end; TransOpenPos(); end
function TransOpenPos() -- Получает ID для следующей транзакции trans_id = trans_id + 1 -- Заполняет структуру для отправки транзакции local direction; if (Type=='B') then direction='Покупка' else direction='Продажа' end; local Transaction={ ['TRANS_ID'] = tostring(trans_id), ['ACTION'] = 'NEW_ORDER', ['CLASSCODE'] = Settings.CLASS_CODE, ['SECCODE'] = Settings.SEC_CODE, ['OPERATION'] = direction, -- операция ("B" - buy, или "S" - sell) ['TYPE'] = 'L', -- по рынку (LIMIT) ['QUANTITY'] = '1', -- количество ['ACCOUNT'] = Settings.ACCOUNT, ['PRICE'] = tostring(math.floor(price.param_value)), ['COMMENT'] = '' } -- Отправляет транзакцию local Res = sendTransaction(Transaction) if Res ~= '' then message('TransOpenPos(): Error: '..Res) else message('TransOpenPos(): FUCK YEAH') end end
Егор Масалкин написал: Здравствуйте! Пишу торгового робота. При запуске появляется ошибка в терминале:
"TransOpenPos(): Error: Не указано значение поля "К/П" "
Что такое это неизвестное "К/П"?
Здравствуйте,
Это направление транзакции. Покупка/Продажа. Откройте форму ввода заявки и посмотрите, как у Вас обозначено направление заявки. Именно так и нужно указать. Т.е если Купля, то в роботе указываете Купля, а не Покупка.
То есть если у меня написано "Покупка", то в строке отправки заявки ['OPERATION'] = Соответственно указываем "Покупка" или "Продажа", верно?
Борис Гудылин написал: Для начала - Вы игнорируете то, что у функции OnCalculate есть аргумент (номер свечи). Именно для этой свечки Вы и должны посчитать и вернуть значение индикатора.
Ваш индикатор последовательно вызовут для первой свечки, для второй и т.д. Для текущей свечки индикатор может вызываться много раз, она же меняется.
Т.е. мне следует в функции OnInit() через условия пересечения средних определять номера нужных свечей, и затем вызвать OnCalculate с этими номерами, где и вернуть значение?
Здравствуйте! Решил попрактиковаться в самостоятельном написании индикаторов технического анализа, но понял, что плохо себе представляю как работает функция OnCalculate. Как я понял, именно она отвечает за установку значений на индикатор. Пытаюсь сделать так, чтобы индикатор ставил точки в зависимости от определенных условий (например, пересечения скользящих средних)
График типа TYPE_POINT. Однако, количество точек четко совпадает с количеством свечей (и их координаты Х соответстенно), а по ординате все точки принимают одно и то же значение.
Где я фундаментально заблуждаюсь?
Код
function OnCalculate()
local short_pos=false;
local long_pos=false;
N1=getNumCandles("MVAs")
for v=2,N1,1 do
t=getCandlesByIndex("MVAs",0,v,1)[0];
t1=getCandlesByIndex("MVAs",0, v-1, 1)[0].close;
t2=getCandlesByIndex("MVAl",0, v-1, 1)[0].close;
t11=getCandlesByIndex("MVAs",0, v-2, 1)[0].close;
t22=getCandlesByIndex("MVAl",0, v-2, 1)[0].close;
if (t1>t2) and (t11<t22) then --короткая пересекает длинную снизу вверх
if (short_pos==false) then --если не в позиции то
long_pos=true; --открываем длинную позицию (покупка)
return t.open;
else --иначе
short_pos=false; --закрываем короткую позицию
return t.open;
end
else
if (t1<t2) and (t11>t22) then --короткая пересекает длинную сверху вниз
if (long_pos==false) then --если не в позиции то открываем короткую
short_pos=true;
return t.open;
else --иначе
long_pos=false; --закрывается длинная позиция
return t.open; --производим продажу; длинна позиция закрыта.
end
end
end
end
end
Егор Масалкин написал: если у datetime отдельно секунды, часы, минуты и прочее, а у метки эти параметры объединены?
Взять отдельно секунды, часы, минуты и прочее и объединить
И по какому принципу они объединяются? Вроде простейший инструмент, но почему-то требуется множество дополнительных действий чтобы поставить метку на график...
Хм, однако, в метках есть только параметры date и time... как можно datetime разделить на date и time, если у datetime отдельно секунды, часы, минуты и прочее, а у метки эти параметры объединены?
Переделал скрипт. Теперь он должен возле каждого пересечения графика ставить метку Icon.jpg, которая представляет собой оранжевый квадратик, и считает количество таких пересечений. Вот только количество пересечений он считает и выводит, а метки на графике не появляются... Что я делаю не так?
function SetLabel(x) label.date=x.date; label.time=x.time; label.Yvalue=x.close; AddLabel("MVAl",label); end
s=0; l=0;
function OnInit()
N1=getNumCandles("MVAs")
for v=2,N1,1 do t=getCandlesByIndex("MVAs",0, v, 1)[0]; t1=getCandlesByIndex("MVAs",0, v-1, 1)[0].close; t2=getCandlesByIndex("MVAl",0, v-1, 1)[0].close; t11=getCandlesByIndex("MVAs",0, v-2, 1)[0].close; t22=getCandlesByIndex("MVAl",0, v-2, 1)[0].close; if (t1>t2) and (t11<t22) then SetLabel(t); s=s+1; end if (t1<t2) and (t11>t22) then SetLabel(t); l=l+1; end end
Какая-то магия. Я убрал часть вывода, запустил. Потом вернул убранную часть вывода (ничего не менял), запустил, он показал полностью все строки, которые я указывал. Хм... Но похоже вопрос решён. Непонятно как, правда...
CSV:write("Kol-vo sdelok;"..count_L+count_S.."\n"); CSV:write("Kol-vo sdelok Long;"..count_L.."\n"); CSV:write("Kol-vo sdelok Short;"..count_S.."\n"); CSV:write("Srednii dohod na sdelku;"..dohod/(count_L+count_S).."\n"); CSV:write("Srednii dohod na sdelku Long;"..l_dohod/(count_L).."\n"); CSV:write("Srednii dohod na sdelku Short;"..s_dohod/(count_S).."\n"); CSV:write("Srednee kol-vo svechei v sdelke;"..s_dohod/(count_S).."\n");
CSV:write("-------------;-------------\n");
CSV:write("Pribilnost sdelok;"..(((pribil/money)-1)*100).."\n"); CSV:write("Summ pribil;"..pribil.."\n"); CSV:write("Srednaya pribil na sdelku;"..pribil/count_pribil.."\n"); CSV:write("Kol-vo sdelok s pribilu;"..count_pribil.."\n"); CSV:write("Max pribil za sdelku;"..pribil_max.."\n"); CSV:write("Max sdelok podryad;"..s_dohod/(count_S).."\n");
CSV:write("-------------;-------------\n");
CSV:write("Ubitochnost sdelok;"..(((ubil/money)-1)*100).."\n"); CSV:write("Summ ubitok;"..ubil.."\n"); CSV:write("Srednaya ubil na sdelku;"..ubil/count_ubil.."\n"); CSV:write("Kol-vo sdelok s ubilu;"..count_ubil.."\n"); CSV:write("Max ubil za sdelku;"..ubil_max.."\n"); CSV:write("Max prosadka;"..l_dohod/(count_L).."\n"); CSV:write("Max sdelok podryad;"..s_dohod/(count_S).."\n");
CSV:write("-------------;-------------\n");
CSV:flush();
Вот весь вывод. В данном случае он выведет вплоть до строки "CSV:write("Summ ubitok;"..ubil.."\n"); " включительно, остальные останутся... в подпространстве.
CSV=io.open(getScriptPath().."/Trades.csv","a+"); local Position = CSV:seek("end",0); if Position==0 then
и далее начинаю через CSV:Write() указывать строки для вывода. Так выходит, что мне надо вывести около 40 строк, которые я и заполняю. Но вот незадача: когда после запуска скрипта я открываю файл Excel, у меня оказывается 26 первых строк, перечисленных в скрипте. В чем дело? Как вывести все нужные мне строки? Я бы хотел именно это сделать именно строками, а не столбцами - так наглядней.