To solve this problem, we need to define the decision variables and the constraints based on the given information.

Let's denote:
- $x_r$ as the number of regular rate tickets sold,
- $x_c$ as the number of concession rate tickets sold.

The profit made from selling these tickets can be calculated as $2x_r + 0.5x_c$, since each regular ticket yields a profit of $2 and each concession ticket yields a profit of $0.50.

We have several constraints:
1. The ferry can carry at most 120 people, so $x_r + x_c \leq 120$.
2. At least 15 tickets are reserved for concession rate, so $x_c \geq 15$.
3. At least 5 times as many tickets sold are regular rate tickets than concession rate tickets, so $x_r \geq 5x_c$.

Our objective is to maximize the profit, which can be represented by the function $2x_r + 0.5x_c$.

To implement this problem in Gurobi using Python, we will use the following code:

```python
from gurobipy import *

# Create a model
m = Model("Ferry_Ticket_Sales")

# Define decision variables
x_r = m.addVar(vtype=GRB.CONTINUOUS, name="regular_tickets")
x_c = m.addVar(vtype=GRB.CONTINUOUS, name="concession_tickets")

# Set the objective function to maximize profit
m.setObjective(2*x_r + 0.5*x_c, GRB.MAXIMIZE)

# Add constraints
m.addConstr(x_r + x_c <= 120, "total_capacity")
m.addConstr(x_c >= 15, "concession_minimum")
m.addConstr(x_r >= 5*x_c, "regular_to_concession_ratio")

# Optimize the model
m.optimize()

# Print results if an optimal solution is found
if m.status == GRB.OPTIMAL:
    print("Optimal solution found:")
    print(f"Regular tickets sold: {x_r.x}")
    print(f"Concession tickets sold: {x_c.x}")
    print(f"Maximum profit: ${2*x_r.x + 0.5*x_c.x:.2f}")
else:
    print("No optimal solution found")
```