У меня есть два торговых робота: один "Судак", а другой "Xsar"
Вот их код:
Судак:
Скрытый текст
-- ************************ СЕКЦИЯ ОБЩИХ ПАРАМЕТРОВ ****************************
CLIENT_CODE ="D62154"-- общий код для акций и фьючерсов.
LogFileName ="c:\\SudakTudak\\short\\sudaktudak_log.txt"-- Технический лог.
ParamPath ="c:\\SudakTudak\\short\\"-- здесь хранятся файлики с параметрами. Три файла на каждый инструкмент.
SdelkaLog ="c:\\SudakTudak\\short\\sudaktudak_sdelki.txt"-- Лог сделок. Сюда пишутся ТОЛЬКО сделки.
SleepDuration =20;-- отдыхаем 10 секунд. Слишком часто не надо молотить.
DemoMode =false-- Включите, чтобы начать "боевые" сделки. Если = false, сделок не будет, просто запишет в лог.-- ************************ СЕКЦИЯ МАССИВОВ ДЛЯ ИНСТРУМЕНТОВ ************************
aTickerList ={"MMM0"};-- сюда массив инструментов. Не забывайте перекладывать фьючерсы!!!-- А при перекладывании фьючерсов не забывайте менять код как здесь, так и в следующих массивах.-- Следующие массивы должны иметь значения для каждого инструмента из aTickerList
aClassCode ={MMM0="SPBFUT"}-- TQBR для акций, SPBFUT для фьючерсов.
aAccountCode ={MMM0="SPBFUT00Q00"}-- может отличаться для акций и фьючерсов.
aLotSize ={MMM0=1};-- Массив лотов для покупки.
aProskalzivanie ={MMM0=0.05};-- Проскальзывание при сделке.
maxVolume =-8;-- Сколько всего можем набрать
aCurrentPrice =0;
aHour_1 =10;-- Час начала работы
aHour_2 =23;-- Час конца работы
aMinutes_1 =00;-- Минуты начала работы
fibo =0.1;-- Множитель увеличения каждого уровня усреднения
fiboStepSize ={MMM0=20};-- Размер уровня для усреднения по каждому инструменту
full_flat_size =false;-- false - торговля между средней и крайней линией ББ, true - между крайними линиями
is_run=truefunction main()while is_run do
curr_date=os.date("*t")if(curr_date["hour"]>=aHour_1 and curr_date["min"]>aMinutes_1)and curr_date["hour"]<aHour_2 thenfor k,v in pairs(aTickerList)do
Obrabotka(v,k);endend;
sleep(SleepDuration*1000)-- Отдыхаем SleepDuration секунд.endendfunction GetLastPrice(TickerName, CandleType)-- Берем цену из графика. CreateDataSource пока не используем, т.к. при необходимости модификации-- алгоритма, хотим легко добавлять индикаторы.-- Плюс меньше зависим от коннекта - графики всегда с нами.local NL=getNumCandles(TickerName.."_Price_Sudak")
tL, nL, lL = getCandlesByIndex (TickerName.."_Price_Sudak",0, NL-1,1)-- last свечаif tL ~=nilthenif tL[0]~=nilthenif CandleType=="LOW"then
aCurrentPrice=tL[0].low -- получили текущую цену (ЦПС)elseif CandleType=="OPEN"then
aCurrentPrice=tL[0].open
elseif CandleType=="HIGH"then
aCurrentPrice=tL[0].high
else
aCurrentPrice=tL[0].close
endend;end;return aCurrentPrice
endfunction GetXsar(TickerName, LineCode)-- получаем текущие значения Боллинлжера.-- LineCode может иметь значения: "High", "Middle", "Low"local NbbL=getNumCandles(TickerName.."_BB_Sudak")
tbbL, nbbL, lbbL = getCandlesByIndex (TickerName.."_BB_Sudak",0, NbbL-1,1)-- last свеча, средняя линия Боллинджера
iBB_Local_Middle = tbbL[0].close -- тек значение средней BB Local
tbbL, nbbL, lbbL = getCandlesByIndex (TickerName.."_BB_Sudak",1, NbbL-1,1)-- last свеча, верхняя линия Боллинджера
iBB_Local_High = tbbL[0].close -- тек значение верхней BB Local
tbbL, nbbL, lbbL = getCandlesByIndex (TickerName.."_BB_Sudak",2, NbbL-1,1)-- last свеча, нижняя линия Боллинджера
iBB_Local_Low = tbbL[0].close -- тек значение нижней BB Localif LineCode =="High"thenreturn iBB_Local_High endif LineCode =="Middle"thenreturn iBB_Local_Middle endif LineCode =="Low"thenreturn iBB_Local_Low endendfunction PriceCrossMAToUp(TickerName)-- Функция возвращает TRUE, если пересекли среднюю линию Боллинджера снизу вверхif GetLastPrice(TickerName,"OPEN")<GetBollinger(TickerName,"Middle")and GetLastPrice(TickerName,"LAST")>GetBollinger(TickerName,"Middle")thenreturntrueelsereturnfalseend;endfunction PriceCrossMAToDown(TickerName)-- Функция возвращает TRUE, если пересекли среднюю линию Боллинджера снизу вверхif GetLastPrice(TickerName,"OPEN")>GetBollinger(TickerName,"Middle")and GetLastPrice(TickerName,"LAST")<GetBollinger(TickerName,"Middle")thenreturntrueelsereturnfalseend;endfunction PriceEnterToBollingerFromDown(TickerName)-- Функция возвращает TRUE, если пересекли нижнюю линию Боллинджера снизу вверх-- (то есть вошли внутрь канала Боллинджера снизу).if GetLastPrice(TickerName,"LOW")<GetBollinger(TickerName,"Low")and GetLastPrice(TickerName,"LAST")>GetBollinger(TickerName,"Low")thenreturntrueelsereturnfalseend;endfunction PriceEnterToBollingerFromUp(TickerName)-- Функция возвращает TRUE, если пересекли верхнюю линию Боллинджера сверху вниз-- (то есть вошли внутрь канала Боллинджера сверху).if GetLastPrice(TickerName,"HIGH")>GetBollinger(TickerName,"High")and GetLastPrice(TickerName,"LAST")<GetBollinger(TickerName,"High")thenreturntrueelsereturnfalseend;end--Функция Обработки отдельного тикераfunction Obrabotka(sTickerName, sNum)-- Теперь откываем файлы с нашим тикетом, и читаем оттуда значения: LastPrice, LastDirection, Объем Позы.
LastPrice = tonumber(GetValueFromFile(ParamPath..sTickerName.."_LastPrice.txt"));
LastDirection = GetValueFromFile(ParamPath..sTickerName.."_LastDirection.txt");
iVolume = tonumber(GetValueFromFile(ParamPath..sTickerName.."_Volume.txt"));local CurrentPrice=GetLastPrice(sTickerName)-- вытаскиваем из графика текущую цену.local profit = tonumber(GetValueFromFile(ParamPath..sTickerName.."_Profit.txt"));-- Логируем текущую и последнюю цены и разницу между ними.
WLOG(sTickerName.." Current="..CurrentPrice.." Last="..LastPrice.." Razn = "..((CurrentPrice-LastPrice)-(CurrentPrice-LastPrice)%aProskalzivanie[sTickerName]).." FlatBBSize = "..FiboSize(sTickerName).." Vol="..iVolume.." LastDir="..LastDirection.." FiboStepSize = "..FiboLevels(sTickerName).." Profit="..profit);-- Теперь проверяем, не надо ли докупиться или скинуть шортif(((CurrentPrice<LastPrice-FiboSize(sTickerName)and LastDirection=="S")or(CurrentPrice<LastPrice-FiboLevels(sTickerName)))and iVolume<0)and PriceEnterToBollingerFromDown(sTickerName)then-- Покупаем или Начинаемif LastDirection=="S"then
WLOG("BUY PROFIT "..(LastPrice-CurrentPrice));
SetValueToFile(ParamPath..sTickerName.."_Profit.txt", profit + LastPrice-CurrentPrice)-- начислили прибыль и записали.else
WLOG("BUY PROFIT NEW LEVEL"..(LastPrice-CurrentPrice));
SetValueToFile(ParamPath..sTickerName.."_Profit.txt", profit + LastPrice-CurrentPrice)-- начислили прибыль и записали.endif(DoFire(sTickerName,"B", CurrentPrice)=="")then
iVolume = tonumber(iVolume)+aLotSize[sTickerName];
SetValueToFile(ParamPath..sTickerName.."_LastPrice.txt", CurrentPrice)
SetValueToFile(ParamPath..sTickerName.."_LastDirection.txt","B")
SetValueToFile(ParamPath..sTickerName.."_Volume.txt", tostring(iVolume))
LastPrice = CurrentPrice;-- чтобы не продать сразу на следующем условии.endend-- Теперь проверяем, не надо ли еще продать? Если поза нуль, то набираем в шортif(((CurrentPrice>LastPrice+FiboLevels(sTickerName))or(CurrentPrice>LastPrice+FiboSize(sTickerName)and LastDirection=="B"))or iVolume==0)and PriceEnterToBollingerFromUp(sTickerName)and iVolume>maxVolume then-- Продаемif LastDirection=="B"then
WLOG("SELL AGAIN");else
WLOG("SELL NEW LEVEL");endif(DoFire(sTickerName,"S", CurrentPrice)=="")then
iVolume = tonumber(iVolume)-aLotSize[sTickerName];
SetValueToFile(ParamPath..sTickerName.."_LastPrice.txt", CurrentPrice)
SetValueToFile(ParamPath..sTickerName.."_LastDirection.txt","S")
SetValueToFile(ParamPath..sTickerName.."_Volume.txt", tostring(iVolume))endendend;function FiboLevels (sTickerName)-- Функция увеличения размера уровня в зависимости от позиции по тикеруlocal Volume = math.abs(iVolume / aLotSize[sTickerName]);local iniStepSize = fiboStepSize[sTickerName];local newStepSize = iniStepSize +(iniStepSize * fibo)^Volume;return newStepSize;end;function FiboSize (sTickerName)-- Функция определение ширины между линиями Боллинжераlocal CurrentPrice=GetLastPrice(sTickerName,"OPEN")-- вытаскиваем из графика текущую цену.local Size=0if full_flat_size then
Size = math.floor (GetBollinger(sTickerName,"High")- GetBollinger(sTickerName,"Low"))return Size
endif CurrentPrice >= GetBollinger(sTickerName,"Middle")and full_flat_size==falsethen
Size = math.floor (GetBollinger(sTickerName,"High")- GetBollinger(sTickerName,"Middle"))return Size
else
Size = math.floor (GetBollinger(sTickerName,"Middle")- GetBollinger(sTickerName,"Low"))return Size
endend;function DoFire(SEC_CODE, p_dir, p_price)-- Функция - СДЕЛКА ПО РЫНКУ!if p_dir =="B"then AAA =1else AAA =-1end
t ={["CLASSCODE"]=aClassCode[SEC_CODE],["SECCODE"]=SEC_CODE,["ACTION"]="NEW_ORDER",-- новая сделка.["ACCOUNT"]=aAccountCode[SEC_CODE],["CLIENT_CODE"]=CLIENT_CODE,["TYPE"]="L",-- "M" "L". По M давал ошибку на TQBR.["OPERATION"]=p_dir,-- направление сделки, "B" или "S"["QUANTITY"]=tostring(aLotSize[SEC_CODE]),-- объем, (акции - в лотах, а не штуках).["PRICE"]=tostring(p_price+(aProskalzivanie[SEC_CODE]*AAA)),-- цену лимитки ставим для мгновенного исполнения.["TRANS_ID"]="1"}if DemoMode==falsethen-- Если всё по серьезному, то ...
res1 = sendTransaction(t)-- ... передаем сделку по рынку.endif(res1~="")then-- Ошибочка вышла. Логируем ошибку.
WLOG("SendTransaction Error = "..res1);endlocal l_file1=io.open(SdelkaLog,"a")
l_file1:write(os.date()..";SECCODE="..SEC_CODE..";PRICE="..p_price..";DIR="..p_dir.."\n")
l_file1:close()return res1
endfunction GetValueFromFile(FileName)-- Читаем параметр из файла.local f = io.open(FileName,"r");if f ==nilthen-- если файла нет, но создаем пустой.
f = io.open(FileName,"w");
DefaultValueForFile ="0"-- по умолчанию пишем нуль.-- Для LastDirection надо бы писать не нуль, а "B", но пусть будет нуль, т.к.-- этого условия достаточно для открытия начальной сделки.
f:write(DefaultValueForFile)
f:close();-- Открывает уже гарантированно существующий файл в режиме "чтения/записи"
f = io.open(FileName,"r");end;
aValue = f:read("*l")
f:close()return aValue
endfunction SetValueToFile(FileName, aValue)-- Пишем параметр в файл.local ff=io.open(FileName,"w")-- используем "w", а не "a", чтобы перезаписать существующий.
ff:write(aValue)
ff:close()endfunction OnStop(stop_flag)
is_run=falseendfunction WLOG(st)-- Универсальная функция записи в лог.local l_file=io.open(LogFileName,"a")-- используем "a", чтобы добавить новую строку.
l_file:write(os.date().." "..st.."\n")
l_file:close()end
Xsar:
Скрытый текст
Settings ={
Name ="xSarATR",
periodATR =21,
ddd=3,
line={{
Name ="xSarATR",
Color = RGB(0,192,0),
Type = TYPET_BAR,
Width =2},{
Name ="xSarATR",
Color = RGB(192,0,0),
Type = TYPET_BAR,
Width =2},{
Name ="xSarATR",
Color = RGB(0,0,255),
Type = TYPE_TRIANGLE_UP,
Width =3},{
Name ="xSarATR",
Color = RGB(255,0,0),
Type = TYPE_TRIANGLE_DOWN,
Width =3}}}------------------------------------------------------------------------------------------------------------------------------------------------------------------------------function cached_SAR()local cache_H={}local cache_L={}local cache_SAR={}local cache_ST={}local AMA2={}local CC={}local CC_N={}local ATR={}returnfunction(ind, _p4,_ddd)local index = ind
local ZZZ =0if index ==1then
cache_H={}
cache_L={}
cache_SAR={}
cache_ST={}
AMA2={}
CC={}
CC_N={}
ATR={}------------------
CC[index]=C(index)
CC_N[index]=(C(index)+H(index)+L(index))/3
cache_H[index]=H(index)
cache_L[index]=L(index)
cache_SAR[index]=L(index)-2*(H(index)-L(index))
AMA2[index]=(C(index)+O(index))/2
cache_ST[index]=1
ATR[index]=math.abs(H(index)-L(index))returnnilend------------------------------
ZZZ=math.max(math.abs(H(index)-L(index)),math.abs(H(index)-C(index-1)),math.abs(L(index)-C(index-1)))
ATR[index]=(ATR[index-1]*(_p4-1)+ZZZ)/_p4
cache_SAR[index]=cache_SAR[index-1]
CC[index]=C(index)
AMA2[index]=(2/(_p4/2+1))*CC[index]+(1-2/(_p4/2+1))*AMA2[index-1]
CC_N[index]=(C(index)-AMA2[index])/2+AMA2[index]
cache_ST[index]=cache_ST[index-1]
cache_H[index]=cache_H[index-1]
cache_L[index]=cache_L[index-1]---------------------------------------------------------------------------------------if index ==2thenreturnnilend---------------------------------------------------------------------- if cache_ST[index]==1thenif cache_H[index]< CC[index]then
cache_H[index]=CC[index]end
cache_SAR[index]=math.max((cache_H[index]-ATR[index]*_ddd),cache_SAR[index-1])if(cache_SAR[index]> CC_N[index])and(cache_SAR[index]> C(index))then
cache_ST[index]=0
cache_L[index]=CC[index]
cache_SAR[index]=cache_L[index]+ATR[index]*_ddd*1returnnil,cache_SAR[index],nil,cache_H[index]-ATR[index]*_ddd
endreturn cache_SAR[index],nil,nil,nilend---------------------------------------------------------------------------------------if cache_ST[index]==0thenif cache_L[index]> CC[index]then
cache_L[index]=CC[index]end
cache_SAR[index]=math.min((cache_L[index]+ATR[index]*_ddd),cache_SAR[index-1])if(cache_SAR[index]< CC_N[index])and(cache_SAR[index]< C(index))then
cache_ST[index]=1
cache_H[index]=CC[index]
cache_SAR[index]=cache_H[index]-ATR[index]*_ddd*1return cache_SAR[index],nil, cache_L[index]+ATR[index]*_ddd,nilendreturnnil,cache_SAR[index],nil,nilendendend------------------------------------------------------------------------------------------------------------------------------------------------------------------------------function Init()
mySAR = cached_SAR()return4endfunction OnCalculate(index)return mySAR(index, Settings.periodATR,Settings.ddd)end
У меня есть два торговых робота: один "Судак", а другой "Xsar"
Вот их код:
Судак:
Xsar:
спойлеры, оформление кода
Поделиться сообщением
Ссылка на сообщение
Поделиться на других сайтах