Комплект индикаторов из серии «черпаем издалека и намазываем на график».
Сайт московской биржи по окончании торгов приводит данные об открытых позициях на срочном рынке. Эти данные содержат информацию в следующих разрезах:
Эта информация является официальной. Она не всегда совпадает с количеством открытых позиций, которые показывает терминал Quik. Вернее она всегда показывает немного больше открытых позиций, чем терминал. Как я понимаю, дело во внебиржевых сделках, которые в терминал не попадают.
Информация интересная. На предложение визуализировать её я с удовольствием прикинулся золотой рыбкой. Написан шаблон, генерирующий комплект индикаторов, которые выводят на график историю как сырых данных, так и результат определённых математических действий над ними.
Известно, что все биржевые трейдеры делятся на две большие категории. Это т.н. “квалифицированные” – разной величины инвестиционные компании и “не квалифицированные” – в основном, одиночки физ. лица. Между ними есть огромная принципиальная разница. И дело тут вовсе не в размере торгового капитала как может показаться на первый взгляд, а в том, что “квалифицированные” это те, кто осуществляет торговлю системно. То есть, в компании всегда есть различные службы — такие как анализ информации, например, и служба оценки и учета рисков — “риск менеджмент”, который выдвигает перед трейдером ряд правил, обязательных к выполнению перед открытием позиции. Это означает, например, что каким бы верным ни казалась трейдеру какое-то решение, и как бы кого он ни умолял разрешить ему это решение принять, риск менеджер не даст ему превысить установленный лимит — не позволит взять на себя дополнительный, не просчитанный риск. Риск менеджер сам не торгует, а занимается только оценкой рисков, аналитик тоже не торгует – он делает только анализ имеющейся информации и т.д.
Таким образом, каждый занимается только свои кусочком одной большой задачи – зарабатывать торговлей на бирже. При этом критерии оценки труда различных служб разные. Это и есть система. Разница между разными системами только в степени фрагментации общей задачи и количества ресурсов выделяемых для решения различных кусочков – подзадач. В одной компании могут быть весьма сильна аналитика, но относительно слабый риск менеджмент, в другой — риск менеджмент сильнее, и разделен на еще более узкие подзадачи и т.д. Таким образом, ”квалифицированный” инвестор торгует системно. Сила системы в том, что она вычищает из всего массива принимаемых решений те из них, которые были продиктованы не какими-то объективными причинами, а — были вызваны стремлением потешить наше эго, которое вечно кому-то чего-то хочет доказать. Эго никуда не денешь и не выключишь — оно неизбежно в какой-то момент обходит толщу запретов и, замаскировавшись псевдообъективностью, берет контроль над принятием решения, что приводит к серьезным ошибкам. И не только в трейдинге, кстати. “Не квалифицированный” инвестор физ. лицо — одиночка вынужден в своем лице сочетать все эти составные части системы, и от этого он становится похож на многоликую индийскую богиню Кали. Но Кали богиня и может находиться в каждый момент времени в каждом своей лике, еще таким свойством обладает электрон в составе атома. Мы же простые смертные люди и с нами происходит следующее: в самом начале мы много времени уделяем разработке какой-то своей системы учета рисков, и часто она выходит весьма неплохой, что приносит свои плоды в виде первых успехов. Эти успехи становятся отличным удобрением для нашего эго, оно быстро вырастает и начинает подменять собой все разумное, лишенное эмоций. Именно поэтому, самая распространенная кривая, которая символизирует карьеру большинства одиночек это перевернутая латинская V. 99% трейдеров одиночек теряют весь свой капитал в пределах года — двух. Нетрудно догадаться, кому достаются их деньги – это ”квалифицированные” инвесторы. Вот, собственно, и все — других причин, объясняющих, почему одни всегда выигрывают, а другие всегда проигрывают, не существует.
Ну что же тогда делать бедному “не квалифицированному” инвестору? Как уравнять шансы и перестать быть добычей для акул трейдинга? Ответ напрашивается сам собой: стать хищником самому — создать систему, исключающую эмоциональную торговлю. Кто-то возразит: постойте, мы же живые люди, а эмоций нет только у бездушных машин. Все верно, стало быть, перед нами выбор: либо стать машиной самому (и именно те, кому это удалось, становятся стабильно зарабатывающими трейдерами), либо поставить нужную машину себе на службу. К счастью, такая машина есть — она называется торговый робот. Что это значит? Торговля через робота это не просто и не столько автоматизация, сколько способ уйти от эмоций к беспристрастной системе. Не больше — не меньше. Это возможность успешно найти свою нишу и спокойно зарабатывать, не вертясь полночи в постели в тревожных думах. Это, если хотите, способ вновь обрести себя, а вашей семье — вас. Знаете, в принципе можно и сейчас, допустим, совсем не иметь ни смартфона, ни просто мобильника даже и продолжать пользоваться телефонными будками – они еще кое-где сохранились, поддерживая тем самым, необходимый в настоящее время уровень коммуникаций. Но что это будет за жизнь? Вряд ли такой способ добавит вам конкурентных преимуществ. Причина — телефонная будка это устаревшая технология. Торговля вручную это тоже устаревшая технология, такая же, как телефонная будка. Робот – инновационная технология и торговать через робота значит идти в ногу со временем. *** WWW.TREIDING-ROBOT.COM
IsRun = true class_code="TQBR" function main() -- Получает доступный id для создания t_id = AllocTable() -- добавить столбцы AddColumn(t_id, 1, "Бумага", true, QTABLE_STRING_TYPE, 20) AddColumn(t_id, 2, "Кол-во", true, QTABLE_INT_TYPE, 7) AddColumn(t_id, 3, "Цена покупки", true, QTABLE_DOUBLE_TYPE, 14) AddColumn(t_id, 4, "Цена текущая", true, QTABLE_DOUBLE_TYPE, 14) AddColumn(t_id, 5, "Прибыль, р", true, QTABLE_DOUBLE_TYPE, 14) AddColumn(t_id, 6, "Прибыль, %", true, QTABLE_DOUBLE_TYPE, 14) t = CreateWindow(t_id) for iRow=1, getNumberOf("depo_limits")-1, 1 do rowInPortfolioTable = getItem("depo_limits", iRow) -- получить текущую строку из таблицы "Лимиты по бумагам" qtyBoughtLots = tonumber(rowInPortfolioTable.currentbal) limitKind = rowInPortfolioTable.limit_kind if qtyBoughtLots>0 and limitKind<1 then InsertRow(t_id, iRow)-- добавить новую строку вниз таблицы end end local rows, columns = GetTableSize (t_id) InsertRow(t_id, rows+1) -- добавить новую строку вниз таблицы для "Итого" SetWindowCaption(t_id, "Портфель: прибыли и убытки © ramirzaev@mail.ru") -- исполнять цикл, пока пользователь не остановит скрипт или не закроет окно таблицы while IsRun do if IsWindowClosed(t_id)==true then IsRun=false end local currentPrice=0 local qtyBoughtLots=0 local profitAbs = 0 local profitPerc = 0 local currentSecCode= "" local fullNameOfInstrument = "" local limitKind = 0 local rowInPortfolioTable = {} -- строка из таблицы "Лимиты по бумагам" local tableInstrument = {} -- данные "Таблицы текущих торгов" local iRowInOutTable = 1 local totalInvest = 0 local totalPortfolio = 0 local totalProfit = 0 local totalPercent = 0 for iRow=0, getNumberOf("depo_limits")-1, 1 do rowInPortfolioTable = getItem("depo_limits", iRow) -- получить текущую строку из таблицы "Лимиты по бумагам" qtyBoughtLots = tonumber(rowInPortfolioTable.currentbal) limitKind = rowInPortfolioTable.limit_kind if qtyBoughtLots>0 and limitKind<1 then -- если кол-во лотов >0 и тип лимита T0 currentSecCode = rowInPortfolioTable.sec_code fullNameOfInstrument = tostring(getParamEx(class_code, currentSecCode, "SHORTNAME").param_image or "0") --"LONGNAME" avgPrice = tonumber(rowInPortfolioTable.awg_position_price) currentPrice = GetAskPrice(currentSecCode) profitAbs = (currentPrice-avgPrice)*qtyBoughtLots profitPerc = 100*currentPrice/avgPrice - 100 totalInvest = totalInvest + avgPrice*qtyBoughtLots totalPortfolio = totalPortfolio + currentPrice*qtyBoughtLots SetCell(t_id, iRowInOutTable, 1, fullNameOfInstrument) -- "Бумага" SetCell(t_id, iRowInOutTable, 2, tostring(qtyBoughtLots)) -- "Кол-во"RemoveZero(tostring(qtyBoughtLots))) SetCell(t_id, iRowInOutTable, 3, tostring( math_round(avgPrice, 3) )) -- tostring(avgPrice)) -- "Цена покупки" SetCell(t_id, iRowInOutTable, 4, RemoveZero(tostring(currentPrice))) -- "Цена текущая" SetCell(t_id, iRowInOutTable, 5, tostring( math_round( profitAbs, 0)) ) -- "Прибыль, р" SetCell(t_id, iRowInOutTable, 6, tostring(math_round(profitPerc, 1)) .."%") -- "Прибыль, %" if profitPerc >5 then -- окрашиваем ColourRowInGreen(iRowInOutTable) elseif profitPerc<-5 then ColourRowInRed(iRowInOutTable) else ColourRowInYellow(iRowInOutTable) end iRowInOutTable = iRowInOutTable+1 end end totalProfit = totalPortfolio - totalInvest totalPercent = 100*totalProfit/totalInvest SetCell(t_id, iRowInOutTable, 1, "Итого") SetCell(t_id, iRowInOutTable, 3, tostring( math_round(totalInvest, 0) )) SetCell(t_id, iRowInOutTable, 4, tostring( math_round(totalPortfolio, 0))) SetCell(t_id, iRowInOutTable, 5, tostring( math_round( totalProfit, 0)) ) SetCell(t_id, iRowInOutTable, 6, tostring(math_round(totalPercent, 1)) .."%") if profitPerc >5 then -- окрашиваем ColourRowInGreen(iRowInOutTable) elseif profitPerc<-5 then ColourRowInRed(iRowInOutTable) else ColourRowInYellow(iRowInOutTable) end iRowInOutTable = iRowInOutTable+1 sleep(5000) -- пауза 5 сек. end --message("script table portfolio finished") end function ColourRowInRed(num_row) SetColor(t_id, num_row, QTABLE_NO_INDEX, RGB(255,150,150), RGB(0,0,0), RGB(255,150,150), RGB(0,0,0)) end function ColourRowInYellow(num_row) SetColor(t_id, num_row, QTABLE_NO_INDEX, RGB(255,255,200), RGB(0,0,0), RGB(255,255,200), RGB(0,0,0)) end function ColourRowInGreen(num_row) SetColor(t_id, num_row, QTABLE_NO_INDEX, RGB(150,255,150), RGB(0,0,0), RGB(150,255,150), RGB(0,0,0)) end function GetAskPrice(inp_Sec_Code ) local ask = tostring(getParamEx(class_code, inp_Sec_Code, "OFFER").param_value or 0) return ask end -- Округляет число до указанной точности function math_round (num, idp) local mult = 10^(idp or 0) return math.floor(num * mult + 0.5) / mult end -- удаление точки и нулей после нее function RemoveZero(str) while (string.sub(str,-1) == "0" and str ~= "0") do str = string.sub(str,1,-2) end if (string.sub(str,-1) == ".") then str = string.sub(str,1,-2) end return str end function OnStop() DestroyTable(t_id) IsRun = false end