Дмитpий Hecтepук

Блог о программировании — C#, F#, C++, архитектура, и многое другое

Posts Tagged ‘quant

Обучение математике для quant finance

17 комментариев

Есть такая хорошая фраза — quit while you’re ahead. Уйти из игры до того, как ты стал немощный и уже не можещь даже номинально отрабатывать те деньги, которые тебе платят. Меня эта фраза всегда и драйвила, потому что я прекрасно понимал, что ничто не вечно. Собственно поэтому я всегда искал себе последнюю сферу деятельности, то есть что-то что может раз и навсегда закрыть хотя бы финансовый вопрос.

Поймите меня правильно — у меня на самом деле очень много хобби и много всяких интересных проектов (например, постройка дома) которые ведутся в параллель. Но количество именно профессиональных занятий, кмк, весьма ограничено ввиду того, что чем старее мы становимся, тем сложнее постигать какие-то новые области. А мне, честно говоря, чертовски надоело что знания в ИТ устаревают, поэтому я хотел пойти в сферу, где хотя бы фундаментальная база знаний в каком-то смысле «закреплена» и является вечной, даже если детали реализации придется периодически подкручивать.

В этом посте рассказ пойдет про математические навыки. Скажу сразу — в этом деле я не профессионал от слова вообще, у меня нет высшего математического, математику я учил сам и не то, чтобы я ее идеально знаю. Разница лишь в том, что в отличии от большинства выпускников условного МатМеха, я хоть что-то использую.

Итак, давайте возьмем как данное что у всех есть какие-то школьные знания. К сожалению этого совсем мало. Чтобы хоть как-то плавать в quant finance, нужно знать еще много всяких специфичных областей.

Во главе всего стоит, конечно, статистика — предмет, который я всегда ненавидел и начал хоть как-то понимать только когда пошел в аспирантуру. И то, начал понимать только когда начал косячить в экспериментах, а мой научный руководитель начал показывать мне ошибки в моем анализе (и это в SPSS, где все за тебя машина делает).

Для того чтобы прочитать учебник по мат статистике не нужно каких-то особых навыков. Обычно базовые понятия теории множеств вводятся прямо в учебнике, дается бытовое (не measure-theoretic) определение вероятности, а в выведении различных формул плотностей итд нужно разве что базовые знания дифференциалов и интегралов — школьной программы должно хватить.

Одна из вещей которые лучше вкурить сразу пока вы не получили люлей это понимание того, что такое тестирование гипотез. Иначе говоря, как доказать что тот эффект, который вы нашли в ваших данных, действительно имеет место быть. Это не так просто как кажется, и поверьте, в отличии от социальной психологии, в финансовой сфере у вас не получится делать p-hacking т.к. с натянутыми результатами вы просто получите маржин колл.

Ключевым с точки зрения финмата является не только знание того что такое стандартное отклонение (я кстати, как и Талеб, не фанат всего этого) или то или иное распределение, а оценка. Оценка, то что называется estimation, позволяет нам оценивать параметры распределения случайной переменной на основе некоторых тестов. Зачем это надо? На самом деле все просто: в финмате очень много времени посвящено анализу процесса цены и подгонки его под тот или иной процесс. Естественно, что идеально оно ложится не всегда, но нужно же хоть как-то понять, какая модель лучше всего подходит к тому или иному активу. Это называется calibration.

С базовыми знаниями статистики уже можно начать разбираться в анализе временных данных. Опять же, есть хорошая книга (Analysis of Financial Time Series, Tsay) которая с примерами на R расскажет вам про такие вещи как стационарность, GARCH, и все вот это. Параллельно с этим я бы советовал взять почитать какую-нибудь книгу по истории статистического арбитража, т.к. там очень хорошо рассказывается про то, с каких стратегий люди начинали арбитражить. Естественно, что мир сейчас намного сложнее, но все равно, это очень интересное чтиво.

Вообще современный финмат построен на анализе функций случайных переменных, если там можно выразиться. С этим можно делать очень много веселых экспериментов, с которыми я до сих пор балуюсь: например, делаешь набор данных, которые обладают тем или иным распределением (может даже каким-нибудь сложным, вроде VG) и потом пытаешься обратным числом понять, с какими параметрами была распределена случайная величина.

Есть хорошая книжка Brownian Motion Calculus (Wiersema), которая немного открыла мои глаза на всю эту кухню. Например, я раньше не мог думать в терминах «матожидание матожидания» (E[E[X]]) потому что мой мозг не был настроен на подобные вещи. Эта книжка оказалась хорошей переходной литературой от «бытовой» статистики до чего-то применимого.

Если говорить про процессы цены, то для этого есть целый отдельный раздел математики под названием Стохастика (stochastic calculus). К сожалению, порог входа в эту область достаточно высок, и подразумевает что вы знаете как классический анализ (а это минимум год вашей жизни) так и теорию меры — один из, вероятно, самых неприятных предметов в математике который существует. Но к сожалению, все книги, в т.ч. и основная книга которая у нас используется (Stochastic Differential Equations, Ocksendal) используют measure-theoretic язык чтобы донести свои идеи. К этому привыкаешь, но привыкаешь очень медленно. Кстати, анализ и теория меры приводят к серьезной «профдеформации» в голове со всякими там эпсилон-окрестностями и другим шумом. Плюс, конечно же, все это подразумевает что вы знаете дифф.ур.-ы на нормальном уровне, но с этим не должно быть каких-то серьезных проблем.

Еще одна сопряженная, и любимая мною область — это монте-карло симуляции, т.е. попытки делать выводы из множества симуляций тех или иных процессов. Тут тоже много теории (Glasserman написал шикарную книгу!) а также много веселья, которые можно применять и в других сферах. В моем случае, поскольку я фанат всяких CCG, для меня монте-карло так же естественно как и боты.

Да, пока не забыл, для всей этой кухни есть, конечно, свои языки программирования. Если говорить чисто про анализ, то тут используется все что душе угодно: R, Python, MATLAB, новые языки вроде Julia (SPSS не вариант, сорян). Когда у вас небольшие объемы данных, все нормально. Вот когда вы уже начинаете строить свою собственную инфру (RAID-ы всякие) для данных и анализа, тогда вам возможно придется перейти на что-то потяжелее. Основной язык финансовой инженерии — С++. Так что плюсы, которые используются на стороне исполнения, знать нужно. Они используются на классическом железе, но также С или С++ (зависит от ситуации) используются на аппаратных ускорителях. Так что С++ нужно знать и понимать без вариантов. У Mark Joshi есть книжка которая индикативна тому что реально пишут… for better or for worse.

Раз уж мы заговорили про программирование, у вас конечно должны быть навыки численных методов. Например, как интерполировать улыбку волатильности чтобы найти искривление, которое рынок почему-то не учел? Ну, надо использовать метод координатного спуска (кажется это Levenberg-Marquardt по-буржуйски), а это численная процедура. Тот же подсчет функций плотности по нормальному распределению делается численными методами (Abramowitz-Stegun, до сих пор где-то книжка лежит) которые тоже нужно знать и понимать. Еще было бы вообще здорово разжиться интуицией касательно того, когда нужно делать single/double floating point а когда вообще fixed-point (!). По секрету скажу, что у меня, особенно когда нет чего-то мерзко-итеративного, вычисления все single-point; сейчас single/double на CPU работают более-менее одинаково, а вот на GPU… это другая история.

Все что я описал выше займет годы изучения. Нет никаких коротких путей, и не нужно забывать, что помимо всего того что я перечислил выше (а также то, что я забыл), еще нужно разбираться в финансовой стороне дел (даже банальный money/risk management), плюс нужно кодить все это. Поскольку большинству людей это нафиг не надо, проще на 2-недельные курсы в местный форекс сходить и слить все, имеем то, что имеем. Интересно, что даже в профессиональных трейдерских сообществах (например смартлаб) мало кто знает эту кухню, ведь большинство людей занимаются тем что мы именуем systematic trading. Настоящих квантов мало, и в основном они сидят в банках и фондах, а не у себя дома. ■

Реклама

Written by Dmitri

15 декабря 2018 at 11:44

Опубликовано в Mathematics

Tagged with ,

Медленный путь в алготрейдинг

31 комментарий

Попробую продолжить мою историю, только для того, чтобы что-то дельное рассказать, придется сначала вернуться на студенческую «скамью» и начать рассказ оттуда.

Когда-то я сидел в аспирантуре и писал диссертацию по социальной психологии. Это был еще один фейл в моей жизни, т.к. профессия академического психолога предполагает не только нищенство (это само собой разумеется), но также весьма сомнительного качества исследования, 60% из которых (цифра официальная) не реплицируются от слова совсем. Вся эта тема налажена на поток чтобы тянуть исследовательские деньги из фондов вроде ESRC, и мне она не подошла тем, что было банально неинтересно. Но я тут не для того, чтобы разглагольствовать про психологию — это особая, очень специфичная, очень женская дисциплина в которой, в отличии от какого-нибудь программирования, до «применения по существу» как до луны. Вещь в себе.

Так вот, будучи на психологии, я периодически рыскал в рунетах (ностальгия? возможно!) и наткнулся, как вы думаете на что, на Форекс Клуб — один из наших старейших форексолохотронов которые убеждают домохозяек, что за 2 недели изучения технического анализа (лжедисциплина, но об этом позже) можно стать «трейдером на валютном рынке». Я, конечно, в тот момент был дебилом, и повелся на всю эту хрень. Денег я, конечно, туда не вливал, но целиком поверил что «мне везет» и я вообще понимаю что со всей этой кухней происходит.

Время шло, и я постепенно наткнулся на популярный терминал MetaTrader, который многие кухни использовали для якобы проведения сделок (на самом деле нет) с плечом аж до 200:1. Примечательным свойством МТ было то, что там можно было писать торговых роботов, а ушлые поставщики сего терминала даже запустили мировой чемпионат (!) где люди могли соревноваться в написании торговых ботов. Называется это сейчас World Cup Trading Championship и является прекрасной заманухой тех, кто считает, что торговать на голом спотовом инструменте это нормально.

Примечательным свойством MetaTrader является то, что прямо в систему встроен C++образный API для написания ботов, которых можно прямо в системе и тестировать. Под «тестировать» нужно понимать, что тесты он проводит на исторических данных без учета того беспредела с проскальзыванием и полным адом, который устраивают кухни. В общем, до реальной жизни тем бэктестам как до луны, но АПИ богат и напичкан всякими погремушками теханализа так что любой advanced домохозяйке надолго хватит.

В контексте этих ботов (их MT называет adviser-ами) у меня появился первый спортивный интерес. А почему бы не пописать роботов, которые там чем-то торгуют? Ведь это так весело, ты сидишь а софтинка тебе денежки приносит. Прям мечта, и масштабы практически безграничны.

Для начала я решил попробовать ручную торговлю. Открыл счет на FXCM (те еще проходимцы), влил туда тыщу фунтов (!) и начал «торговать» вручную. Естественно, что без какого либо базового мани менеджмента, я не мог ничего заработать даже когда фундаментальные показатели шли в мою пользу — при прибыли мои тейкпрофиты не отрабатывали, а кухня прикрывалась тем, что и не гарантирует исполнение в момент выхода новостей. В общем, результат был достаточно предсказуем, примерно как поиграть в казино. Мне кажется, этот опыт пошел мне на пользу т.к. лучше выкинуть тысячу чем «соточку».

Мои заигрывания с FXCM (баланс колебался туда-сюда) продолжились даже когда я переехал в РФ. Терминал стоял у меня прямо на рабочем компе и я периодчески поглядывал, оправдывались ли мои ожидания, базированные, вы угадали, на техническом анализе. Естественно, о том чтобы чуток поизучать математику всего этого не было и речи и, более того, я был убежден что математика программистам вообще не нужна и только отвлекает.

В какой-то момент я наткнулся на такой концепт как «нейронные сети». Систематической литературы по этому феномену тогда не было, были лишь тривиальные кейсы про то как это использовать в OCR плюс очень много воды про то что якобы это применимо в других областях, в т.ч. и в трейдинге. Меня все это как-то сильно цепануло, и я напечатал себе целую огромную папку статей (многие из которых я до конца не понимал т.к. в академии в comp sci все пишут очень плохо и размазано), плюс я начал писать код и даже тестировать торговлю с помощью нейросетей на исторических данных. У меня конечно ничего не работало, но и методологически я, в то время, не смог бы правильно оценить влияние ТС даже если бы все действительно работало как надо.

В общем, вся эта форексовая тема как-то схлопнулась сама собой. Сидя потом без работы, я прочитал в сети достаточно на эту тему чтобы понять, что эта сфера не для меня и что хитрые системы (т.н. «кухни») настроены против игроков и даже их ставки ни на какие «междунородные рынки» в большинстве случаев не выходят. А денег на полноценные ECN-ы у меня не было, да и игра без плеча 100:1 казалось какой-то уж совсем бессмысленной. Все это дело затихло и я не слишком горевал по этому поводу.

После того как я попал в JetBrains, оттуда уволился один из сотрудников из команды Решарпера, причем ушел он не в МС или Одноклассники (да-да, бывает и такое), а пошел делать свой стартап. Он вышел со мной на связь, и мы встретились с ним, а также с его другом и одновременно инвестором — человеком который делал реальные деньги торговлей на бирже. Мой интерес к алготрейдерской теме снова пробудился, и мне было приятно пообсуждать различные механизмы реального заработка на рынках.

Примерно на этом этапе я понял что я нифига не понимаю во всей этой канители, и что в первую очередь нужно учиться. Нужно понять рынки, инструменты которые на них торгуются, откуда берутся цены и где, собственно, есть возможности для заработка. Проблема оказалась лишь в том, что для тех математических знаний, которые были нужны для того чтобы даже только понять, ничего не заработав, пришлось несколько лет просидеть за книгами.

Изучение высшей математики когда тебе «за 30» — это не шутка. Это реально, но мозг уже забит всяким мусором, и раскочегаривание его занятие весьма мучительное. Поясню, что в Английских универах на comp sci, в отличии от РФ, не дается высшая математика а лишь азы, поэтому начать пришлось буквально с базовых вещей вроде математической статистики и вероятности, линейной алгебры, и прочими весьма банальными дисциплинами. Но было бы слишком легко если бы можно было просто копнуть эти темы на поверхностном уровне и бежать считать реальный рынок. На практике пришлось пройти вводный курс анализа, изучить теорию меры и углубиться в стохастику — тему, которая до того момента была мне вообще неизвестна. Тут, для полноты картины, следует упомянуть, что у меня склонности к математике — я сдал математику в школе в 9 классе, в универе по (рудиментарной) математике у меня был высший балл, да и вообще, у меня родители матфизики так что когда-то там, в далеком прошлом, мне это все очень легко давалось. Это я к тому, что я в очередной раз амортизировал то, что подходит лично мне и не факт что подойдет кому-то еще.

Даже освоив какие-то математические дисциплины, очень сложно понять как все это многообразие сухой математической теории применить к реальному рынку. Например, недостаточно знать какие-то базовые распределения, нужно еще знать как формулировать гипотезы присутствия этих распределений в цене. И конечно, существует огромный прыжок от известных и устоявшихся моделей до чего-то оригинального, для каких-то собственных моделей и изысканий.

Лучше всего на меня в этой истории повлияли проработанные кейсы. Например, удачно выбранная книга по time series analysis иллюстрировала с примерами кода как можно анализировать различные свойства рядов данных. Естественно, ни одна книга не ответит на вопрос «а где альфа?» (то есть прибыль), ее нужно искать самостоятельно. Но по крайней мере это толчок в нужном направлении.

Как изучить математику, нужную для финансовой области? Мой алгоритм примерно таков:

  • Оцените свой уровень и подготовьте список литературы

  • Начинайте читать несколько книг одновременно — я часто читаю по 2 книги из одной области. Например, у меня одновременно были 2 книги по мат статистике, очень похожие но с некоторыми отличиями

  • Ознакомитесь с системой компьютерной алгебры и начинайте писать простой код как только у вас есть знания чтобы его написать

  • Не бойтесь задавать глупые вопросы и делать расчеты «не как все». Например, если вам не нравится дисперсия и вы хотите считать mean absolute deviation, узнайте плюсы и минусы того и другого

  • Не бойтесь возвращаться к уже «изученным» темам, т.к. иногда знания раскрываются в нелинейном порядке, как бы не старались авторы книг

К сожалению, уровень усилий нужный для того чтобы понять современную финансовую теорию колоссальный. И это при понимании того, что инфу вы будете черпать из академических источников, а весь финансовый мир — банки, фонды, итд. — они лет на 10 ускакали вперед академии. Обидно? Да, но я как пешка в этом большом и жестоком мире мало могу сделать… ну, с одной стороны мало. С другой, если учесть то что репликация в облаке у нас бесплатна, почему это я как индивид не могу обуздать финансовые рынки?

«Квантовая» (от quantitative finance — количественные финансы) сфера является совокупностью трех направлений: финансов, математики и программирования. Математика является основой, она применяется к финансам и, в конце концов, кто-то должен сесть за компьютер и запрограммировать все это безобразие. К сожалению, в отсутствии альтернатив, этот кто-то — тоже я. Я пробовал искать себе помощников в этом нелегком деле, но оказалось что даже люди с высшим математическим не обучены тем областям которые нужны. А учить их долго и сложно.

Если брать очень грубо, то вся разработка делится на 2 этапа: анализ и исполнение. На этапе анализа, вы, сидя в тапочках с кружкой чая у себя в офисе, анализируете свои данные на каком-нибудь сверхмощном железе. Естественно, сверхмощное железо на дороге не валяется, но мне, признаюсь, в очередной раз повезло: я, видите ли, не увольнялся из своего универа после ухода (а зачем?), а мой универ часть консорциума, которому принадлежит 2й по размеру кластер в Англии. Что как бы хорошо, потому что студенты и профессора — бездари, которые не умеют пользоваться даже «классическими» ресурсами кластера, не говоря уже про всякие аппаратные ускорители которыми он тоже хорошо напичкан. А я умею. Так что это большой плюс.

Вторая сторона медали — исполнение — подразумевает собственно написание торговых роботов которые используют ваши алгоритмы и торгуют либо на тестовых счетах (что не возбраняется, т.к. никакие синтетические тесты не подготовят вас полностью к реальному трэшу рыночных АПИ), либо же на живых счетах с реальными деньгами. Не стоило бы говорить про то, что на живых счетах ошибки фатальны, но когда у нас даже именитые трейдерские конторы порой пересекают по ошибке биды и аски, буквально раздавая деньги всем направо и налево, не грех об этом лишний раз упомянуть.

Естественно, всем этим имеет смысл заниматься если играть по-крупному. Если ваш удел «делать соточку» (а я это стремление уважаю), то можно заниматься видеокурсами, стоковой фотографией, стримить игры в ютубах, и все вот это. Это все хорошие, веселые хобби и лично мне просто по кайфу все это. Но если есть желание куда-то расти, то алготрейдинг — это вполне себе актуальная область с достаточно большими рамками ликвидности (зависит от рынка, конечно) и — главное — огромной технологической составляющей, что должно радовать гиков.

Алготрейдинг привлекает меня тем, что я почти никого не кормлю. Да, я подкармливаю биржу и маркетмейкеров, но это не те проценты! Udemy у вас возьмет 50% дохода, PS или же, например, издатель книг — все 80% (ну, я попробовал и self-publishing, только что-то никто не берет). Вообще мне алготрейдинг больше подходит по идеологическим соображениям, т.к. мне крайне не нравится навязанная модель что я обязательно должен кому-то приносить пользу. 😀 Никому я ничего не должен! И в трейдинге весь код который я пишу, я пишу для себя, с моими стандартами качества и косяками, под мою, заранее известную, инфраструктуру.

Самое же классное в алготрейдинге то, что у тебя другие ограничения. Конечно, торгуя крупными лотами ты сам влияешь на рынок (а это влияние спрогнозировать очень сложно), конечно есть ограничения по ликвидности, но масштабы рынка не сравнимы с той лужицей ликвидности мейнстримовых занятий вроде ИТ. Это просто небо и земля. И соответственно для человека вроде меня, для которого реальный сектор как вампиру в церковь войти, меня вся эта идея управлять торговыми ботами привлекает намного больше.

Теперь-то вы, мои дорогие читатели, поняли почему я затеял весь этот эпос у себя в блоге. Суть всего этого в том, чтобы не только идеологически толкнуть вас в направлении финансовой независимости (думаю все образованные люди понимают что это the only way), но также рассказать про финансы и рынки. Так что до скорой встречи! ■

Written by Dmitri

3 декабря 2018 at 10:47

Опубликовано в Algotrading

Tagged with ,

Нужен ли математикам статический анализ?

10 комментариев

Есть такая профессия, в которой люди на 50% процентов занимаются программированием, но при этом сидят на порой весьма “несовременных” технологиях, пишут в основном на С++, и никаких особых бенефитов от IDE вообще не имеют. И при этом не жалуются. В этом посте – про то, кто эти люди, чем они заниматся и чем мы можем сделать их жизнь лучше.

Знакомьтесь – квонты

Квонт, он же quant (quantitative analyst – численный, так сказать, аналитик) — это человек, который занимается применением математики в финансах, часто – для создания торговых систем, т.е. программ, которые занимаются автоматизированной торговлей на бирже. Эти люди – чаще всего магистры или PhD в области физики (да-да) или математики (в частности, с дипломами вроде MFE – Masters in Financial Engineering), в некоторых случаях, с дипломом CQF (один из очень небольшого кол-ва “неакадемических” дипломов) или даже с MBA Finance или а ля.

Квонты (я бы называл их квантами) программируют в очень узком ключе – их в большинстве случаев не волнуют новые тренды в Asp.Net или новых языках вроде Scala или D. Они живут в совершенно другой реальности, где доминантным маст-хэв языком был, есть и будет С++. Конечно, есть варинты (например, вспомним Jane Street и их любовь к OCaml), но суть остается одна – эти разработчики привыкли работать с достаточно ограниченным tool support, и не особо от этого страдают. Ведь согласитесь, для того чтобы эффективно выполнять математические рассчеты нужно лишь чтобы у вас худо-бедно работал intellisense, и то, это не так критично если нужно вызвать что-то вроде std::min().

Соответственно, текущее положение вещей наводит на мысль, что людям которые используют в основном C++ (а также MATLAB, VBS, R, ну и другие языки на вкус) tool support как бы не очень нужен.

И все же…

Приведу конкретный пример. На многих графических устройствах, операция a*x+b оптимизирована и проходит быстрее, чем умножение и сложение отдельно. Соответственно, когда я работаю с GPU.NET, у меня есть в R2P контекстное действие, которое превращает все, что похоже на “умножение-в-сложении” на вызов вроде DeviceMath.MultiplyAdd(a, x, b). Мелочь, а приятно, и программу ускоряет.

И это далеко не частный случай. Вот еще пример – допустим что вы попросили студента за еду реализовать вам ряд формул в коде, и студент в качестве реализации написал что-то вроде y = a * Math.Pow(x, 2.0) + b * x. Бред, не так ли?

И тут снова можно включить “электронный мозг” статического анализатора и начать помогать несчастному разработчику. Для начала ему нужно объяснить, что считать ряды Тэйлора в подобном случае раз, эээ, в 50 медленнее чем сделать x*x. Но даже объяснив это, вы получите вот такой результат:

y = a * x * x + b * x;

Это тоже не очень-то эффективно. Ведь тут целых 3 умножения, хотя можно обойтись двумя:

y = x * (a * x + b);

Опаньки, а это факторизация, задачка уже посложнее, особенно в контексте статического анализа. Тем не менее, она решабельна, и позволит квонту хоть немного но ускорить вычисления.

А это имеет смысл?

Действительно, кому нужна скорость? Ну, наблюдения показывают что ряд задач (например, Монте-Карло симуляции) очень любят кушать CPU. Микрооптимизация вычислений – это как раз то, что позволит аналитику протестировать свою стратегию быстрее, на большем объеме данных.

Еще одна полезная, хотя и тривиальная вещь – это рефакторинги с уклонов в сторону параллелизации – например рефакторинг for и foreach циклов в параллельные с сохранением правильной семантики. То есть, если разработчик написал

int [] elems = new int[] { ⋮ };
int sum = 0;
foreach (var e in elems) sum += e;

то почему бы нам не дать ему возможность отрефакторить этот цикл в параллельный:

Parallel.ForEach(elems, () => 0, 
                 (n, loopState, localSum) => 
                 {
                   localSum += n;
                   return localSum;
                 },
                 localSum => Interlocked.Add(ref sum, localSum));

У меня в R2P уже реализованы некоторые приведения простых циклов в параллельные, но это большая задача, и за один день ее не решить.

Другие языки?

Я привел пример поддержки C#, т.к. не знаю доступной инфраструктуры для написания рефакторингов для С++ или (это было бы еще интересней) для CUDA C. Было бы интересно услышать мнение читателей насчет применимости всех этих идей.

Written by Dmitri

18 августа 2011 at 22:22

Опубликовано в .NET

Tagged with , ,