diff --git a/.travis.yml b/.travis.yml index 73e0fac..88523c9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -11,8 +11,8 @@ install: - pip install coveralls script: - - python -m pytest --cov=pytrade/ - - flake8 pytrade + - python -m pytest --cov=pytrading/ + - flake8 pytrading after_success: - coveralls diff --git a/.vscode/settings.json b/.vscode/settings.json index 5b2a292..640851f 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,7 +1,7 @@ { "python.pythonPath": "env\\Scripts\\python.exe", "python.testing.pytestArgs": [ - "pytrade" + "pytrading" ], "python.testing.pytestEnabled": true, "python.formatting.provider": "black", diff --git a/README.md b/README.md index 2133b77..3b3c398 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# pytrade +# pytrading -[![Build Status](https://travis-ci.org/simongarisch/pytrade.svg?branch=master)](https://travis-ci.org/simongarisch/pytrade) -[![Coverage Status](https://coveralls.io/repos/github/simongarisch/pytrade/badge.svg)](https://coveralls.io/github/simongarisch/pytrade?branch=master) +[![Build Status](https://travis-ci.org/simongarisch/pytrading.svg?branch=master)](https://travis-ci.org/simongarisch/pytrading) +[![Coverage Status](https://coveralls.io/repos/github/simongarisch/pytrading/badge.svg)](https://coveralls.io/github/simongarisch/pytrading?branch=master) diff --git a/create_environment.bat b/create_environment.bat index 9a25ec6..3d17db4 100644 --- a/create_environment.bat +++ b/create_environment.bat @@ -7,4 +7,4 @@ pip install -r requirements-dev.txt REM CREATE A UNIQUE JUPYTER KERNEL FOR THIS PROJECT pip install ipykernel -ipython kernel install --user --name=pytrade +ipython kernel install --user --name=pytrading diff --git a/notes/01 Assets and Portfolios.ipynb b/notes/01 Assets and Portfolios.ipynb index 7dc46c3..64a8972 100644 --- a/notes/01 Assets and Portfolios.ipynb +++ b/notes/01 Assets and Portfolios.ipynb @@ -34,11 +34,11 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ - "from pytrade.assets import (\n", + "from pytrading.assets import (\n", " reset,\n", " Asset,\n", " Cash,\n", @@ -57,7 +57,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -70,7 +70,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 4, "metadata": {}, "outputs": [ { @@ -87,7 +87,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 5, "metadata": {}, "outputs": [ { @@ -104,7 +104,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 6, "metadata": {}, "outputs": [ { @@ -128,7 +128,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 7, "metadata": {}, "outputs": [ { @@ -137,7 +137,7 @@ "(1.0, None)" ] }, - "execution_count": 20, + "execution_count": 7, "metadata": {}, "output_type": "execute_result" } @@ -155,7 +155,7 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 8, "metadata": {}, "outputs": [], "source": [ @@ -164,7 +164,7 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 9, "metadata": {}, "outputs": [ { @@ -185,7 +185,7 @@ }, { "cell_type": "code", - "execution_count": 27, + "execution_count": 10, "metadata": {}, "outputs": [ { @@ -194,7 +194,7 @@ "(1.0, 10)" ] }, - "execution_count": 27, + "execution_count": 10, "metadata": {}, "output_type": "execute_result" } @@ -205,7 +205,7 @@ }, { "cell_type": "code", - "execution_count": 32, + "execution_count": 11, "metadata": {}, "outputs": [ { @@ -214,7 +214,7 @@ "(1.0, 10.0)" ] }, - "execution_count": 32, + "execution_count": 11, "metadata": {}, "output_type": "execute_result" } @@ -232,7 +232,7 @@ }, { "cell_type": "code", - "execution_count": 39, + "execution_count": 12, "metadata": {}, "outputs": [ { @@ -241,7 +241,7 @@ "('USD', 'AAA US')" ] }, - "execution_count": 39, + "execution_count": 12, "metadata": {}, "output_type": "execute_result" } @@ -259,7 +259,7 @@ }, { "cell_type": "code", - "execution_count": 40, + "execution_count": 13, "metadata": {}, "outputs": [ { @@ -286,7 +286,7 @@ }, { "cell_type": "code", - "execution_count": 44, + "execution_count": 14, "metadata": {}, "outputs": [ { @@ -295,7 +295,7 @@ "True" ] }, - "execution_count": 44, + "execution_count": 14, "metadata": {}, "output_type": "execute_result" } @@ -327,7 +327,7 @@ }, { "cell_type": "code", - "execution_count": 28, + "execution_count": 15, "metadata": {}, "outputs": [], "source": [ @@ -337,7 +337,7 @@ }, { "cell_type": "code", - "execution_count": 30, + "execution_count": 16, "metadata": {}, "outputs": [ { @@ -356,7 +356,7 @@ }, { "cell_type": "code", - "execution_count": 35, + "execution_count": 17, "metadata": {}, "outputs": [ { @@ -365,7 +365,7 @@ "2000.0" ] }, - "execution_count": 35, + "execution_count": 17, "metadata": {}, "output_type": "execute_result" } @@ -385,7 +385,7 @@ }, { "cell_type": "code", - "execution_count": 37, + "execution_count": 18, "metadata": {}, "outputs": [ { @@ -412,12 +412,12 @@ "metadata": {}, "source": [ "### Movements in FX rates\n", - "pytrade supports multiple currencies. For example, you could have an AUD denominated portfolio holding assets in USD, GBP, EUR... The only requirement is that FX rates must be avaliable for the portfolio to use in valuation. FxRateEvent is a supported event type which we'll cover later. For this example we'll just set the rates manually." + "pytrading supports multiple currencies. For example, you could have an AUD denominated portfolio holding assets in USD, GBP, EUR... The only requirement is that FX rates must be avaliable for the portfolio to use in valuation. FxRateEvent is a supported event type which we'll cover later. For this example we'll just set the rates manually." ] }, { "cell_type": "code", - "execution_count": 52, + "execution_count": 19, "metadata": {}, "outputs": [], "source": [ @@ -431,7 +431,7 @@ }, { "cell_type": "code", - "execution_count": 53, + "execution_count": 20, "metadata": {}, "outputs": [ { @@ -440,7 +440,7 @@ "('AUDUSD', None)" ] }, - "execution_count": 53, + "execution_count": 20, "metadata": {}, "output_type": "execute_result" } @@ -451,7 +451,7 @@ }, { "cell_type": "code", - "execution_count": 54, + "execution_count": 21, "metadata": {}, "outputs": [], "source": [ @@ -461,7 +461,7 @@ }, { "cell_type": "code", - "execution_count": 55, + "execution_count": 22, "metadata": {}, "outputs": [ { @@ -486,7 +486,7 @@ }, { "cell_type": "code", - "execution_count": 56, + "execution_count": 23, "metadata": {}, "outputs": [ { @@ -495,7 +495,7 @@ "3857.142857142857" ] }, - "execution_count": 56, + "execution_count": 23, "metadata": {}, "output_type": "execute_result" } @@ -516,7 +516,7 @@ }, { "cell_type": "code", - "execution_count": 57, + "execution_count": 24, "metadata": {}, "outputs": [ { @@ -525,7 +525,7 @@ "3857.142857142857" ] }, - "execution_count": 57, + "execution_count": 24, "metadata": {}, "output_type": "execute_result" } @@ -543,7 +543,7 @@ }, { "cell_type": "code", - "execution_count": 59, + "execution_count": 25, "metadata": {}, "outputs": [ { @@ -552,7 +552,7 @@ "4076.923076923076" ] }, - "execution_count": 59, + "execution_count": 25, "metadata": {}, "output_type": "execute_result" } @@ -578,11 +578,11 @@ }, { "cell_type": "code", - "execution_count": 60, + "execution_count": 26, "metadata": {}, "outputs": [], "source": [ - "from pytrade.assets import (\n", + "from pytrading.assets import (\n", " StaticPriceAsset,\n", " VariablePriceAsset,\n", ")" @@ -590,7 +590,7 @@ }, { "cell_type": "code", - "execution_count": 61, + "execution_count": 27, "metadata": {}, "outputs": [ { @@ -599,7 +599,7 @@ "(True, True)" ] }, - "execution_count": 61, + "execution_count": 27, "metadata": {}, "output_type": "execute_result" } @@ -617,7 +617,7 @@ }, { "cell_type": "code", - "execution_count": 62, + "execution_count": 28, "metadata": {}, "outputs": [ { @@ -626,7 +626,7 @@ "True" ] }, - "execution_count": 62, + "execution_count": 28, "metadata": {}, "output_type": "execute_result" } @@ -644,7 +644,7 @@ }, { "cell_type": "code", - "execution_count": 63, + "execution_count": 29, "metadata": {}, "outputs": [ { @@ -653,7 +653,7 @@ "True" ] }, - "execution_count": 63, + "execution_count": 29, "metadata": {}, "output_type": "execute_result" } diff --git a/notes/02 The Trade Lifecycle.ipynb b/notes/02 The Trade Lifecycle.ipynb index 47f20fd..d35cdf6 100644 --- a/notes/02 The Trade Lifecycle.ipynb +++ b/notes/02 The Trade Lifecycle.ipynb @@ -31,9 +31,9 @@ "metadata": {}, "outputs": [], "source": [ - "from pytrade.compliance import Compliance\n", - "from pytrade.broker import Broker\n", - "from pytrade.assets import (\n", + "from pytrading.compliance import Compliance\n", + "from pytrading.broker import Broker\n", + "from pytrading.assets import (\n", " reset,\n", " Cash,\n", " Stock,\n", @@ -117,7 +117,7 @@ } ], "source": [ - "from pytrade import Trade\n", + "from pytrading import Trade\n", "\n", "trade = Trade(portfolio, stock, 100)\n", "print(trade)" @@ -139,7 +139,7 @@ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 10, @@ -159,7 +159,7 @@ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 11, @@ -201,7 +201,7 @@ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 22, @@ -210,7 +210,7 @@ } ], "source": [ - "from pytrade.trade import trade_pipeline\n", + "from pytrading.trade import trade_pipeline\n", "\n", "trade_pipeline" ] @@ -238,7 +238,7 @@ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 12, @@ -247,7 +247,7 @@ } ], "source": [ - "from pytrade.compliance import Compliance\n", + "from pytrading.compliance import Compliance\n", "\n", "compliance = Compliance()\n", "compliance" @@ -297,7 +297,7 @@ } ], "source": [ - "from pytrade.compliance import UnitLimit\n", + "from pytrading.compliance import UnitLimit\n", "\n", "compliance.add_rule(\n", " UnitLimit(stock, 100)\n", @@ -364,7 +364,7 @@ "metadata": {}, "outputs": [], "source": [ - "from pytrade.compliance import ComplianceRule\n", + "from pytrading.compliance import ComplianceRule\n", "\n", "\n", "class RestrictedSecurityCode(ComplianceRule):\n", @@ -436,7 +436,7 @@ "metadata": {}, "outputs": [], "source": [ - "from pytrade.compliance import UnitLimit, WeightLimit" + "from pytrading.compliance import UnitLimit, WeightLimit" ] }, { @@ -475,7 +475,7 @@ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 31, @@ -520,12 +520,12 @@ "metadata": {}, "outputs": [], "source": [ - "from pytrade.broker import ( # execution strategies\n", + "from pytrading.broker import ( # execution strategies\n", " FillAtLast, # default\n", " FillAtLastWithSlippage,\n", ")\n", "\n", - "from pytrade.broker import ( # charge strategies\n", + "from pytrading.broker import ( # charge strategies\n", " NoCharges, # default\n", " FixedRatePlusPercentage,\n", ")" diff --git a/notes/03 Events.ipynb b/notes/03 Events.ipynb index 8a3602f..16e9fb1 100644 --- a/notes/03 Events.ipynb +++ b/notes/03 Events.ipynb @@ -25,7 +25,7 @@ "metadata": {}, "outputs": [], "source": [ - "from pytrade.events import (\n", + "from pytrading.events import (\n", " AbstractEvent,\n", " AssetPriceEvent,\n", " FxRateEvent,\n", @@ -38,7 +38,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "All events in pytrade inherit from AbstractEvent." + "All events in pytrading inherit from AbstractEvent." ] }, { @@ -76,7 +76,7 @@ "metadata": {}, "outputs": [], "source": [ - "from pytrade.assets import reset, Stock" + "from pytrading.assets import reset, Stock" ] }, { @@ -260,8 +260,8 @@ "outputs": [], "source": [ "from datetime import datetime\n", - "from pytrade import Trade\n", - "from pytrade.assets import reset, Cash, Stock, FxRate, Portfolio\n", + "from pytrading import Trade\n", + "from pytrading.assets import reset, Cash, Stock, FxRate, Portfolio\n", "\n", "reset()\n", "aud = Cash(\"AUD\")\n", @@ -447,7 +447,7 @@ } ], "source": [ - "from pytrade import EventsQueue\n", + "from pytrading import EventsQueue\n", "\n", "reset()\n", "queue = EventsQueue()\n", diff --git a/notes/04 Backtesting.ipynb b/notes/04 Backtesting.ipynb index d9d1059..8fc29d2 100644 --- a/notes/04 Backtesting.ipynb +++ b/notes/04 Backtesting.ipynb @@ -32,9 +32,9 @@ "metadata": {}, "outputs": [], "source": [ - "from pytrade.assets import reset, Cash, Stock, Portfolio\n", - "from pytrade.backtest import Backtest\n", - "from pytrade.strategy import Strategy" + "from pytrading.assets import reset, Cash, Stock, Portfolio\n", + "from pytrading.backtest import Backtest\n", + "from pytrading.strategy import Strategy" ] }, { @@ -83,7 +83,7 @@ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 4, @@ -103,7 +103,7 @@ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 5, @@ -139,7 +139,7 @@ } ], "source": [ - "from pytrade.compliance import Compliance, UnitLimit\n", + "from pytrading.compliance import Compliance, UnitLimit\n", "\n", "portfolio.compliance = Compliance().add_rule(\n", " UnitLimit(stock, 1000)\n", @@ -161,7 +161,7 @@ "metadata": {}, "outputs": [], "source": [ - "from pytrade.broker import (\n", + "from pytrading.broker import (\n", " Broker,\n", " FillAtLastWithSlippage,\n", " FixedRatePlusPercentage,\n", @@ -179,7 +179,7 @@ "source": [ "### Setting the backtest strategy\n", "\n", - "All backtests should have a strategy that inherits from pytrade.strategy.Strategy and implements a generate_trades method. Returned trades can either be None, a single trade instance or a list of trades." + "All backtests should have a strategy that inherits from pytrading.strategy.Strategy and implements a generate_trades method. Returned trades can either be None, a single trade instance or a list of trades." ] }, { @@ -188,8 +188,8 @@ "metadata": {}, "outputs": [], "source": [ - "from pytrade import Trade\n", - "from pytrade.strategy import Strategy\n", + "from pytrading import Trade\n", + "from pytrading.strategy import Strategy\n", "\n", "class BuyAndHold(Strategy):\n", " def generate_trades(self):\n", @@ -219,7 +219,7 @@ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 9, @@ -228,7 +228,7 @@ } ], "source": [ - "from pytrade.backtest import Backtest\n", + "from pytrading.backtest import Backtest\n", "\n", "backtest = Backtest(BuyAndHold())\n", "\n", @@ -249,7 +249,7 @@ "metadata": {}, "outputs": [], "source": [ - "from pytrade.history import History\n", + "from pytrading.history import History\n", "\n", "history = History(\n", " portfolios=portfolio,\n", @@ -330,7 +330,7 @@ { "data": { "text/plain": [ - ">" + ">" ] }, "execution_count": 12, @@ -360,7 +360,7 @@ ], "source": [ "from datetime import datetime\n", - "from pytrade.events import AssetPriceEvent\n", + "from pytrading.events import AssetPriceEvent\n", "\n", "events = [\n", " AssetPriceEvent(stock, datetime(2020, 10, 1), 2.50),\n", @@ -619,13 +619,13 @@ "outputs": [], "source": [ "from datetime import datetime\n", - "from pytrade import Trade\n", - "from pytrade.assets import reset, Cash, Stock, Portfolio\n", - "from pytrade.compliance import Compliance, UnitLimit\n", - "from pytrade.backtest import Backtest\n", - "from pytrade.strategy import Strategy\n", - "from pytrade.events import AssetPriceEvent\n", - "from pytrade.broker import (\n", + "from pytrading import Trade\n", + "from pytrading.assets import reset, Cash, Stock, Portfolio\n", + "from pytrading.compliance import Compliance, UnitLimit\n", + "from pytrading.backtest import Backtest\n", + "from pytrading.strategy import Strategy\n", + "from pytrading.events import AssetPriceEvent\n", + "from pytrading.broker import (\n", " Broker,\n", " FillAtLastWithSlippage,\n", " FixedRatePlusPercentage,\n", diff --git a/notes/05 Bulk Event Loads.ipynb b/notes/05 Bulk Event Loads.ipynb index dee948d..86c4dbd 100644 --- a/notes/05 Bulk Event Loads.ipynb +++ b/notes/05 Bulk Event Loads.ipynb @@ -28,7 +28,7 @@ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 2, @@ -37,7 +37,7 @@ } ], "source": [ - "from pytrade.events.yahoo import load_yahoo_prices\n", + "from pytrading.events.yahoo import load_yahoo_prices\n", "\n", "load_yahoo_prices" ] @@ -57,7 +57,7 @@ { "data": { "text/plain": [ - "" + "" ] }, "execution_count": 3, @@ -66,8 +66,8 @@ } ], "source": [ - "from pytrade.assets import reset, Cash, Stock, FxRate, Portfolio\n", - "from pytrade import Trade, Strategy, Backtest, History\n", + "from pytrading.assets import reset, Cash, Stock, FxRate, Portfolio\n", + "from pytrading import Trade, Strategy, Backtest, History\n", "\n", "reset()\n", "spy = Stock(\"SPY\", currency_code=\"USD\") # SPDR S&P 500 ETF Trust (SPY) traded in USA\n", @@ -121,7 +121,7 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "If this yahoo_ticker attribute is None then pytrade will use the asset code instead." + "If this yahoo_ticker attribute is None then pytrading will use the asset code instead." ] }, { @@ -353,7 +353,7 @@ } ], "source": [ - "from pytrade.events import load_frame_events, AssetPriceEvent\n", + "from pytrading.events import load_frame_events, AssetPriceEvent\n", "\n", "load_frame_events(\n", " aaa, # load events for stock 'AAA'\n", diff --git a/notes/06 Example - Buy And Hold.ipynb b/notes/06 Example - Buy And Hold.ipynb index 3a5023c..2c771a3 100644 --- a/notes/06 Example - Buy And Hold.ipynb +++ b/notes/06 Example - Buy And Hold.ipynb @@ -27,7 +27,10 @@ "metadata": {}, "outputs": [], "source": [ - "import pytrade" + "from pytrading import Trade, Strategy, History, Backtest\n", + "from pytrading.assets import Cash, Stock, Portfolio\n", + "from pytrading.events import AssetPriceEvent\n", + "from pytrading.compliance import Compliance, UnitLimit" ] }, { @@ -35,18 +38,6 @@ "execution_count": 3, "metadata": {}, "outputs": [], - "source": [ - "from pytrade import Trade, Strategy, History, Backtest\n", - "from pytrade.assets import Cash, Stock, Portfolio\n", - "from pytrade.events import AssetPriceEvent\n", - "from pytrade.compliance import Compliance, UnitLimit" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [], "source": [ "stock = Stock(\"SPY\", currency_code=\"USD\")\n", "cash = Cash(\"USD\")\n", @@ -57,7 +48,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 4, "metadata": {}, "outputs": [ { @@ -74,7 +65,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 5, "metadata": {}, "outputs": [ { @@ -91,7 +82,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 6, "metadata": {}, "outputs": [ { @@ -109,7 +100,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 7, "metadata": {}, "outputs": [ { @@ -118,7 +109,7 @@ "1" ] }, - "execution_count": 8, + "execution_count": 7, "metadata": {}, "output_type": "execute_result" } @@ -133,7 +124,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 8, "metadata": {}, "outputs": [], "source": [ @@ -144,16 +135,16 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 9, "metadata": {}, "outputs": [ { "data": { "text/plain": [ - "" + "" ] }, - "execution_count": 10, + "execution_count": 9, "metadata": {}, "output_type": "execute_result" } @@ -169,12 +160,12 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 10, "metadata": {}, "outputs": [], "source": [ "from datetime import date\n", - "from pytrade.events.yahoo import load_yahoo_prices\n", + "from pytrading.events.yahoo import load_yahoo_prices\n", "\n", "start_date = date(2020, 9, 1)\n", "end_date = date(2020, 10, 1)\n", @@ -183,7 +174,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 11, "metadata": {}, "outputs": [], "source": [ @@ -192,7 +183,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 12, "metadata": {}, "outputs": [ { @@ -201,7 +192,7 @@ "100" ] }, - "execution_count": 13, + "execution_count": 12, "metadata": {}, "output_type": "execute_result" } @@ -212,7 +203,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 13, "metadata": {}, "outputs": [ { @@ -231,7 +222,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 14, "metadata": {}, "outputs": [ { @@ -240,7 +231,7 @@ "48584.58251953125" ] }, - "execution_count": 15, + "execution_count": 14, "metadata": {}, "output_type": "execute_result" } @@ -260,7 +251,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 15, "metadata": {}, "outputs": [ { @@ -269,7 +260,7 @@ "-1414.9999999999977" ] }, - "execution_count": 16, + "execution_count": 15, "metadata": {}, "output_type": "execute_result" } @@ -280,7 +271,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 16, "metadata": {}, "outputs": [ { @@ -518,7 +509,7 @@ "2020-10-01 48584.582520 100.0 14880.581665 337.040009 1.0" ] }, - "execution_count": 18, + "execution_count": 16, "metadata": {}, "output_type": "execute_result" } @@ -530,7 +521,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 17, "metadata": {}, "outputs": [ { @@ -1557,21 +1548,21 @@ "
\n", " \n", " \n", - "
\n", + "
\n", "