Viacheslav Merten
Viacheslav Merten личный блог
21 июля 2020, 08:55

Индикатор BullBearPower

Приветствую, коллеги!

Не думал, что будет такой интерес к моему посту https://smart-lab.ru/blog/634217.php , а точнее к индикатору, о котором в нем написано. Много сообщений в личку, не успеваю. Поэтому просто выкладываю код индикатора. Написан в QLua. Копируйте, вставляйте, запускайте и пользуйтесь! ВАЖНО: Для нормальной работы индикатора нужно, что бы была открыта таблица обезличенных сделок и шел поток данных по вашему инструменту!!!

p_CLASSCODE = «SPBFUT» --Код класса
p_SECCODE = «SiU0» --Код инструмента

function OnInit()

frame_60min = CreateDataSource (p_CLASSCODE, p_SECCODE, INTERVAL_H1)
frame_5min = CreateDataSource (p_CLASSCODE, p_SECCODE, INTERVAL_M5)

Index_60min = nil
Index_5min = nil

LastPrice = nil

IsRun = true

end

function main()

CreateTable()

while IsRun do

if Index_60min ~= frame_60min:Size() then

Index_60min = frame_60min:Size()

end

if Index_5min ~= frame_5min:Size() then

Index_5min = frame_5min:Size()

Transaq = 0
BuyWay = 0
SellWay = 0

end

if LastPrice ~= frame_60min:C(Index_60min) then

LastPrice = frame_60min:C(Index_60min)

BuySignal(frame_60min, Index_60min)
SellSignal(frame_60min, Index_60min)

if BuySpeed ~= nil and SellSpeed ~= nil then

if LastPrice < BuyPrice and BuySpeed > SellSpeed then

SetCell(t_id, 1, 4, «Buy»)

elseif LastPrice > SellPrice and SellSpeed > BuySpeed then

SetCell(t_id, 1, 4, «Sell»)

else

SetCell(t_id, 1, 4, «None»)

end

end

end

sleep(10)

end

end

function OnStop()

IsRun = false;

end

function BuySignal(frame, index)

local Open = frame:O(index)
local Close = frame:C(index)
local OL = {}

OL[index-2] = frame:O(index — 2) — frame:L(index — 2)
OL[index-1] = frame:O(index — 1) — frame:L(index — 1)
OL[index] = frame:O(index) — frame:L(index)

local mid_OL = (OL[index-2] + OL[index-1] + OL[index]) / 3
local buy_price = CorrectPrice(Open — mid_OL)

if BuyPrice ~= buy_price then

BuyPrice = buy_price
SetCell(t_id, 1, 2, tostring(BuyPrice))

end

end

function SellSignal(frame, index)

local Open = frame:O(index)
local Close = frame:C(index)
local OH = {}

OH[index-2] = frame:H(index — 2) — frame:O(index — 2)
OH[index-1] = frame:H(index — 1) — frame:O(index — 1)
OH[index] = frame:H(index) — frame:O(index)

local mid_OH = (OH[index-2] + OH[index-1] + OH[index]) / 3
local sell_price = CorrectPrice(Open + mid_OH)

if SellPrice ~= sell_price then

SellPrice = sell_price
SetCell(t_id, 1, 3, tostring(SellPrice))

end

end

function CreateTable()

t_id = AllocTable()

AddColumn(t_id, 0, «BuyPower», true, QTABLE_INT_TYPE, 15)
AddColumn(t_id, 1, «SellPower», true, QTABLE_INT_TYPE, 15)
AddColumn(t_id, 2, «BuyPrice», true, QTABLE_INT_TYPE, 15)
AddColumn(t_id, 3, «SellPrice», true, QTABLE_INT_TYPE, 15)
AddColumn(t_id, 4, «Recommendation», true, QTABLE_INT_TYPE, 15)

t = CreateWindow(t_id)

SetWindowCaption(t_id, «BullBearPower»)

InsertRow(t_id, -1)

end

function OnAllTrade(alltrade)

if alltrade.sec_code == p_SECCODE then

if alltrade.flags == 1025 then

if CurrentSellPrice == nil then

CurrentSellPrice = alltrade.price

if CurrentBuyPrice ~= nil then

StartCheckSpeed = os.time()

end

elseif CurrentBuyPrice ~= nil then

DeltaSellPrice = CurrentBuyPrice — alltrade.price
CurrentSellPrice = alltrade.price

if SellWay == nil then

SellWay = DeltaSellPrice

else

SellWay = SellWay + DeltaSellPrice

end

end

else

if CurrentBuyPrice == nil then

CurrentBuyPrice = alltrade.price

if CurrentSellPrice ~= nil then

StartCheckSpeed = os.time()

end

elseif CurrentSellPrice ~= nil then

DeltaBuyPrice = alltrade.price — CurrentSellPrice
CurrentBuyPrice = alltrade.price

if BuyWay == nil then

BuyWay = DeltaBuyPrice

else

BuyWay = BuyWay + DeltaBuyPrice

end

end

end

if Transaq == nil then

Transaq = 1

else

Transaq = Transaq + 1

end

if StartCheckSpeed ~= nil then

Work_Time = os.time() — StartCheckSpeed

if Transaq >= 10 and Work_Time >= 60 then

BuySpeed = BuyWay / Transaq
SellSpeed = SellWay / Transaq

SetCell(t_id, 1, 0, tostring(math_round(BuySpeed, 2)))
SetCell(t_id, 1, 1, tostring(math_round(SellSpeed, 2)))

end

end

end

end

CorrectPrice = function(_price)

local scale = getSecurityInfo(p_CLASSCODE, p_SECCODE).scale

local PriceStep = tonumber(getParamEx(p_CLASSCODE, p_SECCODE, «SEC_PRICE_STEP»).param_value)

if scale > 0 then

_price = tostring(_price)

local dot_pos = _price:find('.')
local comma_pos = _price:find(',')

if dot_pos == nil and comma_pos == nil then

_price = _price..','
for i=1,scale do _price = _price..'0' end
return tonumber(_price)

else

if comma_pos ~= nil then _price:gsub(',', '.') end

_price = math_round(tonumber(_price), scale)

_price = math_round(_price/PriceStep)*PriceStep
return _price

end

else

_price = math_round(_price/PriceStep)*PriceStep

return tonumber(math.floor(_price))

end

end

math_round = function(num, idp)

if num == nil then num = 0 end
local mult = 10^(idp or 0)
return math.floor(num * mult + 0.5) / mult

end

51 Комментарий
  • еще бы пару слов про него написал или скопипастил хотя бы .

  • Сергей777
    21 июля 2020, 10:09
    спасибо. подскажите ваши роботы торгуют по этим индикаторам?
      • Paulmarko
        24 июля 2020, 22:24
        Viacheslav Merten, Интересный индикатор получилось. По некоторым инструментам отличное совпадение. Если будет время, напишите в лч, есть пару вопросов.
  • Аксенов Руслан
    21 июля 2020, 10:55
    Для тех, кто еще больший нуб, чем я.
    Скопировать полностью, вставить в блокнот. Сохранить с расширением lua.
    Исправить в тексте кавычки « на "
    Исправить '—' на -.
  • Аксенов Руслан
    21 июля 2020, 11:12
    Спасибо, запустил на фьюче Сбера.
      • A3hedge
        21 июля 2020, 11:32
        Viacheslav Merten, добрый день
        пишет ошибку: LuaIndicators\Induk.lua:1: unexpected symbol near '<\194>'
          • A3hedge
            21 июля 2020, 11:39
            Viacheslav Merten, как ее обновить? библиотека точно есть
              • A3hedge
                21 июля 2020, 11:42
                Viacheslav Merten, 8.5.2.11
              • A3hedge
                21 июля 2020, 11:43
                Viacheslav Merten, 8.6.0.97 — ту же ошибку выдает

                  • A3hedge
                    21 июля 2020, 11:48
                    Viacheslav Merten, разобрался — ошибка с " и минусом — все исправил и заработало. спасибо
  • Сергей777
    21 июля 2020, 11:47
    подскажите, пожалуйста, рекомендация и BuySpeed и SellSpeed начинают проявляться через час после работы скрипта? Work_Time >= 60
    А когда набирается Transaq >= 10?

    Час прошел, а в таблице только BuyPrice/SellPrice
  • Аксенов Руслан
    21 июля 2020, 11:51
     Да, забыл, файл сохранять в кодировке АНСИ
  • Сергей777
    21 июля 2020, 12:13
    Спасибо за ответ.

    Подскажите, а зачем вы используете 5M таймфрейм Index_5min? Раз в 5 минут обновляются индикаторы Buy/Sell Power? 
      • A3hedge
        21 июля 2020, 13:24
        Viacheslav Merten, подскажите, вы не добавляли столбец «время сигнала»
        было бы удобно контролировать процесс
  • АлексейФ
    21 июля 2020, 17:59
    Не понятно пара моментов.
    Запустил индикатор. Периодически проскакивают сигналы Buy и Sell Но вот отображение истории в Окне сообщений не наблюдаю. Это значит в этом варианте кода не записывается эта информация?
    В коде используются таймфреймы 60 мин и 5 мин. Эти графики должны быть открыты в квике для работы индикатора?
  • Винни Пух
    21 июля 2020, 21:37
    Вроде корректно отредактировал.
    Не забудьте заказать поток обезличенных сделок!
    p_CLASSCODE = "SPBFUT" --Код класса
    p_SECCODE = "SiU0" --Код инструмента
    
    function OnInit()
    	frame_60min = CreateDataSource (p_CLASSCODE, p_SECCODE, INTERVAL_H1)
    	frame_5min = CreateDataSource (p_CLASSCODE, p_SECCODE, INTERVAL_M5)
    
    	Index_60min = nil
    	Index_5min = nil
    
    	LastPrice = nil
    
    	IsRun = true
    end
    
    function main()
    
    	CreateTable()
    
    	while IsRun do
    
    		if Index_60min ~= frame_60min:Size() then
    			Index_60min = frame_60min:Size()
    		end
    
    		if Index_5min ~= frame_5min:Size() then
    			Index_5min = frame_5min:Size()
    			Transaq = 0
    			BuyWay = 0
    			SellWay = 0
    		end
    
    		if LastPrice ~= frame_60min:C(Index_60min) then
    			LastPrice = frame_60min:C(Index_60min)
    
    			BuySignal(frame_60min, Index_60min)
    			SellSignal(frame_60min, Index_60min)
    
    			if BuySpeed ~= nil and SellSpeed ~= nil then
    
    				if LastPrice < BuyPrice and BuySpeed > SellSpeed then
    					SetCell(t_id, 1, 4, "Buy")
    					
    				elseif LastPrice > SellPrice and SellSpeed > BuySpeed then
    					SetCell(t_id, 1, 4, "Sell")
    				else
    					SetCell(t_id, 1, 4, "None")
    				end
    			end
    		end
    		sleep(10)
    	end
    end
    
    function OnStop()
    	IsRun = false;
    end
    
    function BuySignal(frame, index)
    
    	local Open = frame:O(index)
    	local Close = frame:C(index)
    	local OL = {}
    
    	OL[index-2] = frame:O(index - 2) - frame:L(index - 2)
    	OL[index-1] = frame:O(index - 1) - frame:L(index - 1)
    	OL[index] = frame:O(index) - frame:L(index)
    
    	local mid_OL = (OL[index-2] + OL[index-1] + OL[index]) / 3
    	local buy_price = CorrectPrice(Open - mid_OL)
    
    	if BuyPrice ~= buy_price then
    		BuyPrice = buy_price
    		SetCell(t_id, 1, 2, tostring(BuyPrice))
    	end
    
    end
    
    function SellSignal(frame, index)
    	local Open = frame:O(index)
    	local Close = frame:C(index)
    	local OH = {}
    
    	OH[index-2] = frame:H(index - 2) - frame:O(index - 2)
    	OH[index-1] = frame:H(index - 1) - frame:O(index - 1)
    	OH[index] = frame:H(index) - frame:O(index)
    
    	local mid_OH = (OH[index-2] + OH[index-1] + OH[index]) / 3
    	local sell_price = CorrectPrice(Open + mid_OH)
    
    	if SellPrice ~= sell_price then
    		SellPrice = sell_price
    		SetCell(t_id, 1, 3, tostring(SellPrice))
    	end
    end
    
    function CreateTable()
    
    	t_id = AllocTable()
    
    	AddColumn(t_id, 0, "BuyPower", true, QTABLE_INT_TYPE, 15)
    	AddColumn(t_id, 1, "SellPower", true, QTABLE_INT_TYPE, 15)
    	AddColumn(t_id, 2, "BuyPrice", true, QTABLE_INT_TYPE, 15)
    	AddColumn(t_id, 3, "SellPrice", true, QTABLE_INT_TYPE, 15)
    	AddColumn(t_id, 4, "Recommendation", true, QTABLE_INT_TYPE, 15)
    
    	t = CreateWindow(t_id)
    	SetWindowCaption(t_id, "BullBearPower")
    	InsertRow(t_id, -1)
    end
    
    function OnAllTrade(alltrade)
    	if alltrade.sec_code == p_SECCODE then
    		if alltrade.flags == 1025 then
    			if CurrentSellPrice == nil then
    				CurrentSellPrice = alltrade.price
    				if CurrentBuyPrice ~= nil then
    					StartCheckSpeed = os.time()
    				end
    			elseif CurrentBuyPrice ~= nil then
    				DeltaSellPrice = CurrentBuyPrice - alltrade.price
    				CurrentSellPrice = alltrade.price
    				if SellWay == nil then
    					SellWay = DeltaSellPrice
    				else
    					SellWay = SellWay + DeltaSellPrice
    				end
    			end
    		else
    			if CurrentBuyPrice == nil then
    				CurrentBuyPrice = alltrade.price
    				if CurrentSellPrice ~= nil then
    					StartCheckSpeed = os.time()
    				end
    			elseif CurrentSellPrice ~= nil then
    				DeltaBuyPrice = alltrade.price - CurrentSellPrice
    				CurrentBuyPrice = alltrade.price
    				if BuyWay == nil then
    					BuyWay = DeltaBuyPrice
    				else
    					BuyWay = BuyWay + DeltaBuyPrice
    				end
    			end
    
    		end
    
    		if Transaq == nil then
    			Transaq = 1
    		else
    			Transaq = Transaq + 1
    		end
    
    		if StartCheckSpeed ~= nil then
    			Work_Time = os.time() - StartCheckSpeed
    
    			if Transaq >= 10 and Work_Time >= 60 then
    				BuySpeed = BuyWay / Transaq
    				SellSpeed = SellWay / Transaq
    				
    				SetCell(t_id, 1, 0, tostring(math_round(BuySpeed, 2)))
    				SetCell(t_id, 1, 1, tostring(math_round(SellSpeed, 2)))
    			end
    		end
    	end
    end
    
    CorrectPrice = function(_price)
    	local scale = getSecurityInfo(p_CLASSCODE, p_SECCODE).scale
    	local PriceStep = tonumber(getParamEx(p_CLASSCODE, p_SECCODE, "SEC_PRICE_STEP").param_value)
    
    	if scale > 0 then
    		_price = tostring(_price)
    		local dot_pos = _price:find('.')
    		local comma_pos = _price:find(',')
    
    		if dot_pos == nil and comma_pos == nil then
    			_price = _price..','
    			for i=1,scale do _price = _price..'0' end
    			return tonumber(_price)
    		else
    			if comma_pos ~= nil then _price:gsub(',', '.') end
    			_price = math_round(tonumber(_price), scale)
    			_price = math_round(_price/PriceStep)*PriceStep
    			return _price
    		end
    	else
    		_price = math_round(_price/PriceStep)*PriceStep
    		return tonumber(math.floor(_price))
    	end
    end
    
    math_round = function(num, idp)
    	if num == nil then num = 0 end
    	local mult = 10^(idp or 0)
    	return math.floor(num * mult + 0.5) / mult
    end
    • besttrader
      22 июля 2020, 16:21
      Винни Пух, твой вариант у меня заработал, спасиба :)
  • Сергей777
    30 июля 2020, 14:40
    индикатор у вас получился очень интересный, но не хватает понимания остального алгоритма для полноценной работы. еще что нибудь не планируете выложили или дополнить описание алгоритма? вы наращивание long при сигнале buy, а потом сокращаете когда получаете сигнал sell, если он выше средней?
      • Сергей777
        30 июля 2020, 18:28
        Viacheslav Merten, понятно. спасибо. полноценно рабочей ТС пока нет. экспериментирую с вашим индикатором)

Активные форумы
Что сейчас обсуждают

Старый дизайн
Старый
дизайн