Избранное трейдера Bullet
Одной из самых частых просьб читателей в прошлом обзоре был разбор кейсов, на которых можно заработать с помощью ОФЗ и/или фьючерсов на ОФЗ. Поэтому сейчас мы разберём стратегии, но только две, сконцентрировавшись на технической части торговли для большего понимания. Конечно, представленные ниже стратегии не единственные, и о других вариантах можно прочесть на www.futofz.moex.com/s1257. Я отобрал, на мой взгляд, наиболее понятные и простые, чтобы как раз сконцентрироваться на технических аспектах. В следующей части мы разберём уже менее тривиальные стратегии.
Чтобы правильно выбрать между ОФЗ и фьючерсом на ОФЗ надо чётко понимать, что вы получаете от первого и второго инструмента.
1. ОФЗ даёт Вам прибыль за счёт изменения доходности и за счет получения первоначальной
VWAP — это внутридневный расчет, используемый в основном HFT алгоритмами и институциональными трейдерами для оценки того, где акции торгуются относительно среднего значения объема за день. Внутридневные трейдеры также используют VWAP для оценки направления рынка и фильтрации торговых сигналов. Перед использованием VWAP, необходимо понять, как он рассчитывается, как его интерпретировать и использовать, а также какие недостатки у этого инструмента.
VWAP (Volume Weighted Average Price) — это аббревиатура от Средневзвешенной цены по объему. На первый взгляд, вы можете думать, что VWAP — это всего лишь индикатор средней цены. Но VWAP — это нечто большее.
Индикатор скользящей средней чаще всего основан только на одной цене (закрытия) актива, и он никогда не даст вам точной информации об истинной средней цене. Чтобы определить истинную среднюю цену акции (или другого актива), вам необходимо фактическое количество транзакций по целому ряду цен. Это то, что может делать VWAP.
«Несколько моих знакомых попросили меня высказать свое мнение. Что я думаю о новых санкциях. Действительно, что то серьезное или как обычно. Очень неприятно, но ничего катастрофического...
Я полагаю, что последние действия США — это на порядки более серьезно и болезненно, чем то, что было ранее.
Не буду пересказывать содержание этого документа. Думаю, все его просмотрели.
Решил внимательнейшим образом сам перечитать первоисточник. А не комментарии.
Честно говоря — говоря простым языком, прифигел.
Очень и очень жестко.
Что принципиально нового-
1. Теперь — это закон. Не указ президента. А именно закон. То есть ОЧЕНЬ НАДОЛГО.
БЕЗ НАДЕЖД НА ОТМЕНУ В ТЕЧЕНИЕ ГОДА — двух.
2. Данный пакет санкций как мне видится, ставит крест практически на ЛЮБЫХ НОВЫХ ТЕХНОЛОГИЯХ, которые могли бы поступить в Россию. Дело в том, что строго говоря, Практически любая технология может быть по желанию США объявлена технологией санкционного назначения. Более того, любой человек, гражданин любой страны мира, любая компания, поставляющая данные технологии может иметь очень серьезные последствия.
Невероятно. Долго и стабильно прибыльный для игроков рынка продукт превращается в убыточный, в головную боль для всех торговцев и производителей. Рынок продукта, стабильно дававшего хорошую прибыль его производителям и продавцам, превращается в низкорентабельный и с отрицательной рентабельностью. И находится в таком стагнирующем состоянии долгие годы.
В чём дело, какие причины? Глобальный и/или региональный экономический кризис? Нет. Просто много конкурентов? Нет. Конкуренты всегда были, есть и будут на рынках. Новые ниши потребления быстро заполняются производителями и торговцами.
И в то же время соседние рынки продуктов, близких по технологии производства, способу хранения и распространения, рынки с той же самой клиентской базой как давали, так и продолжают давать хорошую норму прибыли. Мы раз-другой попадали в подобную ситуацию. Вопрос требовал ответа.
require"QL"
log = "sbrf.log"
seccode = "SRM6"
lots_in_trade = 80
accnt = ""
better = -5
chart = "sberbankxxx"
is_run = true
prev_datetime = {}
len = 100
basis = 9
k_bal = {0,1,2,3}
sell = false
buy = false
id = 0
first = true
function trade_signal(shift)
number_of_candles = getNumCandles(chart)
bars_temp,res,legend = getCandlesByIndex(chart,0,number_of_candles-2*len-shift,2*len)
bars={}
i=len
j=2*len
while i>=1 do
if bars_temp[j-1].datetime.hour>=10 then
sk=true
if bars_temp[j-1].datetime.hour==18 and bars_temp[j-1].datetime.min==45 then
sk=false
end
if sk then
bars[i]=bars_temp[j-1]
i=i-1
end
end
j=j-1
end
t = len+1
do_sell = false
do_buy = true
value = 0
if do_sell then value = 1 end
if do_buy then value = -1 end
toLog(log,"value="..value.." on candle: "..bars[len].datetime.year.."-"..bars[len].datetime.month.."-"..bars[len].datetime.day.." "..bars[len].datetime.hour..":"..bars[len].datetime.min.." O="..bars[len].open.." H="..bars[len].high.." L="..bars[len].low.." C="..bars[len].close.." V="..bars[len].volume)
return value
end
function mysplit(inputstr, sep)
if sep == nil then
sep = "%s"
end
local t={} ; i=1
for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
t[i] = str
i = i + 1
end
return t
end
function OnInit(path)
log=getScriptPath()..'\\'..log
toLog(log,"==========OnInit: START")
toLog(log,"==========OnInit: FINISH")
end
function OnStop()
is_run = false
toLog(log,"==========OnStop: script finished manually")
end
function CheckBit(flags, bit)
-- Проверяет, что переданные аргументы являются числами
if type(flags) ~= "number" then error("Ошибка!!! Checkbit: 1-й аргумент не число!"); end;
if type(bit) ~= "number" then error("Ошибка!!! Checkbit: 2-й аргумент не число!"); end;
local RevBitsStr = ""; -- Перевернутое (задом наперед) строковое представление двоичного представления переданного десятичного числа (flags)
local Fmod = 0; -- Остаток от деления
local Go = true; -- Флаг работы цикла
while Go do
Fmod = math.fmod(flags, 2); -- Остаток от деления
flags = math.floor(flags/2); -- Оставляет для следующей итерации цикла только целую часть от деления
RevBitsStr = RevBitsStr ..tostring(Fmod); -- Добавляет справа остаток от деления
if flags == 0 then Go = false; end; -- Если был последний бит, завершает цикл
end;
-- Возвращает значение бита
local Result = RevBitsStr :sub(bit+1,bit+1);
if Result == "0" then return 0;
elseif Result == "1" then return 1;
else return nil;
end;
end;
function killorders(ccode,scode)
for i=0,getNumberOf("orders")-1,1 do
local t=getItem("orders", i)
if t ~= nil and type(t) == "table" then
if( t.seccode == scode and CheckBit(t.flags, 0) == 1) then
local transaction={
["TRANS_ID"]=tostring(math.random(2000000000)),
["ACTION"]="KILL_ORDER",
["CLASSCODE"]=ccode,
["SECCODE"]=scode,
["ACCOUNT"] = accnt,
["ORDER_KEY"]=tostring(t.ordernum),
}
res=sendTransaction(transaction)
end
end
end
end
function killstoporders(ccode,scode)
for i=0,getNumberOf("stop_orders")-1,1 do
local t=getItem("stop_orders", i)
if t ~= nil and type(t) == "table" then
if( t.seccode == scode and CheckBit(t.flags, 0) == 1) then
local transaction={
["TRANS_ID"]=tostring(math.random(2000000000)),
["ACTION"]="KILL_STOP_ORDER",
["CLASSCODE"]=ccode,
["SECCODE"]=scode,
["ACCOUNT"] = accnt,
["STOP_ORDER_KEY"]=tostring(t.ordernum),
}
res=sendTransaction(transaction)
end
end
end
end
function main()
toLog(log,"==========main: START")
while is_run do
if isConnected() == 1 then
ss = getInfoParam("SERVERTIME")
if string.len(ss) >= 5 then
hh = mysplit(ss,":")
str=hh[1]..hh[2]
h = tonumber(str)
if (h>=1000 and h<1400) or (h>=1405 and h<1845) or (h>=1905 and h<2350) then
if first then
for ti = 50,2,-1 do trade_signal(ti) end
if buy and not sell then message(seccode.." Current state: green and buy",1) end
if sell and not buy then message(seccode.." Current state: red and sell",1) end
if buy and sell then message(seccode.." ERROR: green and red",1) end
if not buy and not sell then message(seccode.." WARNING: nothing",1) end
first = false
end
prev_candle = getPrevCandle(chart,0)
if not isEqual(prev_candle.datetime,prev_datetime) then
current_value = trade_signal(1)
if current_value ~= 0 then
optn = "B"
if current_value==1 then optn = "S" end
curvol=0
no=getNumberOf("FUTURES_CLIENT_HOLDING")
if no>0 then
for i=0,no-1,1 do
im=getItem("FUTURES_CLIENT_HOLDING", i)
if im.sec_code==seccode then
curvol=im.totalnet
end
end
end
trvol = -current_value*lots_in_trade-curvol
if trvol ~= 0 then
killorders("SPBFUT",seccode)
killstoporders("SPBFUT",seccode)
f = io.open(getScriptPath().."\\sbrf2_pos.txt","r")
sbrf2_pos=f:read("*n")
f:close()
f = io.open(getScriptPath().."\\sbrf3_pos.txt","r")
sbrf3_pos=f:read("*n")
f:close()
pr,n,l = getCandlesByIndex ("futsber", 0, getNumCandles("futsber")-1, 1)
local trans =
{
["ACTION"] = "NEW_ORDER",
["CLASSCODE"] = "SPBFUT",
["SECCODE"] = seccode,
["ACCOUNT"] = accnt,
["OPERATION"] = optn,
["PRICE"] = toPrice(seccode,pr[0].close+current_value*better),
["QUANTITY"] = tostring(math.abs(curvol-sbrf2_pos-sbrf3_pos)),
["TRANS_ID"] = tostring(getTradeDate().month*100+getTradeDate().day+id)
}
id = id+1
--res = sendTransaction(trans)
message(seccode.." Send : " .. res, 2)
toLog(log,"Send: ".. res)
for btr=0,200,5 do
local trans =
{
["ACTION"] = "NEW_STOP_ORDER",
["CLASSCODE"] = "SPBFUT",
["SECCODE"] = seccode,
["ACCOUNT"] = accnt,
["OPERATION"] = optn,
["PRICE"] = toPrice(seccode,pr[0].close-current_value*btr),
["STOPPRICE"] = toPrice(seccode,pr[0].close-current_value*(btr+better)),
["QUANTITY"] = tostring(6),
["TRANS_ID"] = tostring(getTradeDate().month*100+getTradeDate().day+id),
["EXPIRY_DATE"] = "GTC"
}
id = id+1
--res = sendTransaction(trans)
message(seccode.." Send : " .. res, 2)
toLog(log,"Send: ".. res)
end
if current_value == 1 then
message(seccode..' RED: buy->sell',1)
toLog(log,"RED signal")
else
message(seccode..' GREEN: sell->buy',1)
toLog(log,"GREEN signal")
end
else
if current_value == 1 then
message(seccode..' RED: buy->sell',1)
toLog(log,"RED signal, but nothing to do")
else
message(seccode..' GREEN: sell->buy',1)
toLog(log,"GREEN signal, but nothing to do")
end
end
else
if buy and not sell then toLog(log,"Nothing to do. Current state: green and buy",1) end
if sell and not buy then toLog(log,"Nothing to do. Current state: red and sell",1) end
if buy and sell then toLog(log,"Nothing to do. ERROR: green and red",1) end
if not buy and not sell then toLog(log,"Nothing to do. WARNING: nothing",1) end
end
prev_datetime = prev_candle.datetime
end
end
end
end
sleep(5*1000)
end
toLog(log,"==========main: FINISH")
end

